Browse Source

fix(lint): fix all lint errors/warnings

renovate/lint-staged-8.x
Jack Mallers 7 years ago
parent
commit
88c577d248
  1. 8
      .eslintrc
  2. 1
      app/main.dev.js
  3. 2
      app/menu.js
  4. 4
      app/reducers/channels.js
  5. 8
      app/reducers/form.js
  6. 28
      app/reducers/invoice.js
  7. 9
      app/reducers/payment.js
  8. 13
      app/reducers/peers.js
  9. 6
      app/routes/activity/components/Activity.js
  10. 18
      app/routes/activity/components/components/Invoices.js
  11. 2
      app/routes/activity/components/components/Modal.js
  12. 14
      app/routes/activity/components/components/Payments.js
  13. 6
      app/routes/app/components/App.js
  14. 9
      app/routes/app/components/components/Form/Form.js
  15. 178
      app/routes/app/components/components/Nav.js
  16. 9
      app/routes/app/containers/AppContainer.js
  17. 16
      app/routes/wallet/components/Wallet.js
  18. 4
      app/routes/wallet/components/components/Channels/Channels.js
  19. 26
      app/routes/wallet/components/components/Channels/components/ChannelForm/ChannelForm.js
  20. 159
      app/routes/wallet/components/components/Channels/components/ChannelModal/ChannelModal.js
  21. 6
      app/routes/wallet/components/components/Channels/components/ClosedPendingChannel/ClosedPendingChannel.js
  22. 1
      app/routes/wallet/components/components/Channels/components/OpenPendingChannel/OpenPendingChannel.js
  23. 137
      app/routes/wallet/components/components/Peers/components/PeerForm/PeerForm.js
  24. 128
      app/routes/wallet/components/components/Peers/components/PeerModal/PeerModal.js
  25. 14
      app/store/configureStore.prod.js
  26. 13
      app/utils/btc.js
  27. 2
      app/utils/usd.js
  28. 2
      test/e2e/e2e.spec.js
  29. 1
      webpack.config.renderer.dev.js

8
.eslintrc

@ -16,7 +16,13 @@
"jsx-quotes": ["error", "prefer-single"], "jsx-quotes": ["error", "prefer-single"],
"react/jsx-filename-extension": [1, { "extensions": [".js", ".jsx"] }], "react/jsx-filename-extension": [1, { "extensions": [".js", ".jsx"] }],
"jsx-a11y/no-static-element-interactions": 0, "jsx-a11y/no-static-element-interactions": 0,
"react/forbid-prop-types": 0 "jsx-a11y/no-noninteractive-element-interactions": 0,
"react/no-array-index-key": 0,
"react/forbid-prop-types": 0,
"camelcase": 0,
"react/require-default-props": 0,
"max-len": ["error", 150],
"import/no-extraneous-dependencies": 0
}, },
"plugins": [ "plugins": [
"flowtype", "flowtype",

1
app/main.dev.js

@ -1,3 +1,4 @@
/* eslint-disable */
/* eslint global-require: 1, flowtype-errors/show-errors: 0 */ /* eslint global-require: 1, flowtype-errors/show-errors: 0 */
/** /**

2
app/menu.js

@ -1,3 +1,5 @@
/* eslint-disable */
// @flow // @flow
import { app, Menu, shell, BrowserWindow } from 'electron'; import { app, Menu, shell, BrowserWindow } from 'electron';

4
app/reducers/channels.js

@ -119,7 +119,9 @@ channelsSelectors.allChannels = createSelector(
pendingOpenChannelsSelector, pendingOpenChannelsSelector,
pendingClosedChannelsSelector, pendingClosedChannelsSelector,
pendingForceClosedChannelsSelector, pendingForceClosedChannelsSelector,
(channels, pendingOpenChannels, pendingClosedChannels, pendingForcedClosedChannels) => [...channels, ...pendingOpenChannels, ...pendingClosedChannels, ...pendingForcedClosedChannels] (channels, pendingOpenChannels, pendingClosedChannels, pendingForcedClosedChannels) => (
[...channels, ...pendingOpenChannels, ...pendingClosedChannels, ...pendingForcedClosedChannels]
)
) )
export { channelsSelectors } export { channelsSelectors }

8
app/reducers/form.js

@ -49,10 +49,10 @@ export function setPubkey(pubkey) {
} }
} }
export function setPaymentRequest(paymentRequest) { export function setPaymentRequest(payment_request) {
return { return {
type: SET_PAYMENT_REQUEST, type: SET_PAYMENT_REQUEST,
paymentRequest payment_request
} }
} }
@ -70,9 +70,7 @@ const ACTION_HANDLERS = {
[SET_AMOUNT]: (state, { amount }) => ({ ...state, amount }), [SET_AMOUNT]: (state, { amount }) => ({ ...state, amount }),
[SET_MESSAGE]: (state, { message }) => ({ ...state, message }), [SET_MESSAGE]: (state, { message }) => ({ ...state, message }),
[SET_PUBKEY]: (state, { pubkey }) => ({ ...state, pubkey }), [SET_PUBKEY]: (state, { pubkey }) => ({ ...state, pubkey }),
[SET_PAYMENT_REQUEST]: (state, { paymentRequest }) => ( [SET_PAYMENT_REQUEST]: (state, { payment_request }) => ({ ...state, payment_request }),
{ ...state, payment_request: paymentRequest }
),
[RESET_FORM]: () => (initialState) [RESET_FORM]: () => (initialState)
} }

28
app/reducers/invoice.js

@ -83,6 +83,12 @@ export function invoiceSuccessful(invoice) {
} }
} }
export function invoiceFailed() {
return {
type: INVOICE_FAILED
}
}
export const fetchInvoice = payreq => async (dispatch) => { export const fetchInvoice = payreq => async (dispatch) => {
dispatch(getInvoice()) dispatch(getInvoice())
const invoice = await callApi(`invoice/${payreq}`, 'get') const invoice = await callApi(`invoice/${payreq}`, 'get')
@ -91,17 +97,18 @@ export const fetchInvoice = payreq => async (dispatch) => {
dispatch(receiveFormInvoice(invoice.data)) dispatch(receiveFormInvoice(invoice.data))
return true return true
} }
dispatch(invoicesFailed()) dispatch(invoiceFailed())
return false return false
} }
export const fetchInvoices = () => async (dispatch) => { export const fetchInvoices = () => async (dispatch) => {
dispatch(getInvoice()) dispatch(getInvoice())
const invoices = await callApi('invoices') const invoices = await callApi('invoices')
invoices ? if (invoices) {
dispatch(receiveInvoices(invoices.data)) dispatch(receiveInvoices(invoices.data))
: } else {
dispatch(invoiceFailed()) dispatch(invoiceFailed())
}
return invoices return invoices
} }
@ -119,13 +126,6 @@ export const createInvoice = (amount, memo, currency, rate) => async (dispatch)
return invoice return invoice
} }
export function invoiceFailed() {
return {
type: INVOICE_FAILED
}
}
// ------------------------------------ // ------------------------------------
// Action Handlers // Action Handlers
// ------------------------------------ // ------------------------------------
@ -136,13 +136,17 @@ const ACTION_HANDLERS = {
[GET_INVOICE]: state => ({ ...state, invoiceLoading: true }), [GET_INVOICE]: state => ({ ...state, invoiceLoading: true }),
[RECEIVE_INVOICE]: (state, { invoice }) => ({ ...state, invoiceLoading: false, invoice }), [RECEIVE_INVOICE]: (state, { invoice }) => ({ ...state, invoiceLoading: false, invoice }),
[RECEIVE_FORM_INVOICE]: (state, { formInvoice }) => ({ ...state, invoiceLoading: false, formInvoice }), [RECEIVE_FORM_INVOICE]: (state, { formInvoice }) => (
{ ...state, invoiceLoading: false, formInvoice }
),
[GET_INVOICES]: state => ({ ...state, invoiceLoading: true }), [GET_INVOICES]: state => ({ ...state, invoiceLoading: true }),
[RECEIVE_INVOICES]: (state, { invoices }) => ({ ...state, invoiceLoading: false, invoices }), [RECEIVE_INVOICES]: (state, { invoices }) => ({ ...state, invoiceLoading: false, invoices }),
[SEND_INVOICE]: state => ({ ...state, invoiceLoading: true }), [SEND_INVOICE]: state => ({ ...state, invoiceLoading: true }),
[INVOICE_SUCCESSFUL]: (state, { invoice }) => ({ ...state, invoiceLoading: false, invoices: [invoice, ...state.invoices] }), [INVOICE_SUCCESSFUL]: (state, { invoice }) => (
{ ...state, invoiceLoading: false, invoices: [invoice, ...state.invoices] }
),
[INVOICE_FAILED]: state => ({ ...state, invoiceLoading: false, data: null }) [INVOICE_FAILED]: state => ({ ...state, invoiceLoading: false, data: null })
} }

9
app/reducers/payment.js

@ -68,14 +68,15 @@ export const fetchPayments = () => async (dispatch) => {
return payments return payments
} }
export const payInvoice = paymentRequest => async (dispatch) => { export const payInvoice = payment_request => async (dispatch) => {
dispatch(sendPayment()) dispatch(sendPayment())
const payment = await callApi('sendpayment', 'post', { payment_request: paymentRequest }) const payment = await callApi('sendpayment', 'post', { payment_request })
payment ? if (payment) {
dispatch(fetchPayments()) dispatch(fetchPayments())
: } else {
dispatch(paymentFailed()) dispatch(paymentFailed())
}
return payment return payment
} }

13
app/reducers/peers.js

@ -95,7 +95,11 @@ export const fetchPeers = () => async (dispatch) => {
export const connectRequest = ({ pubkey, host }) => async (dispatch) => { export const connectRequest = ({ pubkey, host }) => async (dispatch) => {
dispatch(connectPeer()) dispatch(connectPeer())
const success = await callApi('connect', 'post', { pubkey, host }) const success = await callApi('connect', 'post', { pubkey, host })
success.data ? dispatch(connectSuccess({ pub_key: pubkey, address: host, peer_id: success.data.peer_id })) : dispatch(connectFailure()) if (success.data) {
dispatch(connectSuccess({ pub_key: pubkey, address: host, peer_id: success.data.peer_id }))
} else {
dispatch(connectFailure())
}
return success return success
} }
@ -103,8 +107,11 @@ export const connectRequest = ({ pubkey, host }) => async (dispatch) => {
export const disconnectRequest = ({ pubkey }) => async (dispatch) => { export const disconnectRequest = ({ pubkey }) => async (dispatch) => {
dispatch(disconnectPeer()) dispatch(disconnectPeer())
const success = await callApi('disconnect', 'post', { pubkey }) const success = await callApi('disconnect', 'post', { pubkey })
console.log('success: ', success) if (success) {
success ? dispatch(disconnectSuccess(pubkey)) : dispatch(disconnectFailure()) dispatch(disconnectSuccess(pubkey))
} else {
dispatch(disconnectFailure())
}
return success return success
} }

6
app/routes/activity/components/Activity.js

@ -1,6 +1,5 @@
import React, { Component } from 'react' import React, { Component } from 'react'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import CSSTransitionGroup from 'react-transition-group/CSSTransitionGroup'
import { MdSearch } from 'react-icons/lib/md' import { MdSearch } from 'react-icons/lib/md'
import Payments from './components/Payments' import Payments from './components/Payments'
import Invoices from './components/Invoices' import Invoices from './components/Invoices'
@ -39,7 +38,7 @@ class Activity extends Component {
return ( return (
<div> <div>
<div className={styles.search}> <div className={styles.search}>
<label className={`${styles.label} ${styles.input}`}> <label className={`${styles.label} ${styles.input}`} htmlFor='invoiceSearch'>
<MdSearch /> <MdSearch />
</label> </label>
<input <input
@ -48,6 +47,7 @@ class Activity extends Component {
className={`${styles.text} ${styles.input}`} className={`${styles.text} ${styles.input}`}
placeholder={tab === 1 ? 'Search transactions by amount, public key, channel' : 'Search requests by memo'} placeholder={tab === 1 ? 'Search transactions by amount, public key, channel' : 'Search requests by memo'}
type='text' type='text'
id='invoiceSearch'
/> />
</div> </div>
@ -93,6 +93,8 @@ class Activity extends Component {
} }
Activity.propTypes = { Activity.propTypes = {
fetchPayments: PropTypes.func.isRequired,
fetchInvoices: PropTypes.func.isRequired,
ticker: PropTypes.object.isRequired, ticker: PropTypes.object.isRequired,
searchInvoices: PropTypes.func.isRequired, searchInvoices: PropTypes.func.isRequired,
invoices: PropTypes.array.isRequired, invoices: PropTypes.array.isRequired,

18
app/routes/activity/components/components/Invoices.js

@ -77,26 +77,26 @@ const Invoices = ({
</div> </div>
</li> </li>
{ {
invoices.map((invoice, index) => invoices.map((invoiceItem, index) => (
(<li key={index} className={styles.invoice} onClick={() => setInvoice(invoice)}> <li key={index} className={styles.invoice} onClick={() => setInvoice(invoiceItem)}>
<div className={styles.left}> <div className={styles.left}>
<div className={styles.path}>{`${invoice.payment_request.substring(0, 75)}...`}</div> <div className={styles.path}>{`${invoiceItem.payment_request.substring(0, 75)}...`}</div>
</div> </div>
<div className={styles.center}> <div className={styles.center}>
<div>{invoice.memo}</div> <div>{invoiceItem.memo}</div>
</div> </div>
<div className={styles.right}> <div className={styles.right}>
<div className={invoice.settled ? styles.settled : null}> <div className={invoiceItem.settled ? styles.settled : null}>
{ {
ticker.currency === 'btc' ? ticker.currency === 'btc' ?
btc.satoshisToBtc(invoice.value) btc.satoshisToBtc(invoiceItem.value)
: :
btc.satoshisToUsd(invoice.value, ticker.btcTicker.price_usd) btc.satoshisToUsd(invoiceItem.value, ticker.btcTicker.price_usd)
} }
</div> </div>
</div> </div>
</li>) </li>
) ))
} }
</ul> </ul>
</div> </div>

2
app/routes/activity/components/components/Modal.js

@ -1,8 +1,6 @@
import React from 'react' import React from 'react'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import ReactModal from 'react-modal' import ReactModal from 'react-modal'
import Moment from 'react-moment'
import 'moment-timezone'
const Modal = ({ isOpen, resetObject, children }) => { const Modal = ({ isOpen, resetObject, children }) => {
const customStyles = { const customStyles = {

14
app/routes/activity/components/components/Payments.js

@ -65,23 +65,23 @@ const Payments = ({
</div> </div>
</li> </li>
{ {
payments.map((payment, index) => payments.map((paymentItem, index) =>
(<li key={index} className={styles.payment} onClick={() => setPayment(payment)}> (<li key={index} className={styles.payment} onClick={() => setPayment(payment)}>
<div className={styles.left}> <div className={styles.left}>
<div className={styles.path}>{payment.path[0]}</div> <div className={styles.path}>{paymentItem.path[0]}</div>
</div> </div>
<div className={styles.center}> <div className={styles.center}>
<div className={styles.date}> <div className={styles.date}>
<Moment format='MMMM Do'>{payment.creation_date * 1000}</Moment> <Moment format='MMMM Do'>{paymentItem.creation_date * 1000}</Moment>
</div> </div>
</div> </div>
<div className={styles.right}> <div className={styles.right}>
<span className={styles.fee}> <span className={styles.fee}>
{ {
ticker.currency === 'btc' ? ticker.currency === 'btc' ?
btc.satoshisToBtc(payment.fee) btc.satoshisToBtc(paymentItem.fee)
: :
btc.satoshisToUsd(payment.fee, ticker.btcTicker.price_usd) btc.satoshisToUsd(paymentItem.fee, ticker.btcTicker.price_usd)
} }
</span> </span>
</div> </div>
@ -89,9 +89,9 @@ const Payments = ({
<span className={styles.value}> <span className={styles.value}>
{ {
ticker.currency === 'btc' ? ticker.currency === 'btc' ?
btc.satoshisToBtc(payment.value) btc.satoshisToBtc(paymentItem.value)
: :
btc.satoshisToUsd(payment.value, ticker.btcTicker.price_usd) btc.satoshisToUsd(paymentItem.value, ticker.btcTicker.price_usd)
} }
</span> </span>
</div> </div>

6
app/routes/app/components/App.js

@ -1,8 +1,8 @@
import React, { Component } from 'react' import React, { Component } from 'react'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import Form from './components/Form' import Form from './components/Form'
import Nav from './components/Nav.js' import Nav from './components/Nav'
import Socket from './components/Socket.js' import Socket from './components/Socket'
import styles from './App.scss' import styles from './App.scss'
export const CHANNEL_DATA = 'CHANNEL_DATA' export const CHANNEL_DATA = 'CHANNEL_DATA'
@ -74,6 +74,8 @@ class App extends Component {
} }
App.propTypes = { App.propTypes = {
fetchTicker: PropTypes.func.isRequired,
fetchBalance: PropTypes.func.isRequired,
ticker: PropTypes.object.isRequired, ticker: PropTypes.object.isRequired,
balance: PropTypes.object.isRequired, balance: PropTypes.object.isRequired,
invoice: PropTypes.object.isRequired, invoice: PropTypes.object.isRequired,

9
app/routes/app/components/components/Form/Form.js

@ -117,18 +117,9 @@ const Form = ({
Form.propTypes = { Form.propTypes = {
form: PropTypes.object.isRequired, form: PropTypes.object.isRequired,
ticker: PropTypes.object.isRequired, ticker: PropTypes.object.isRequired,
formType: PropTypes.string,
amount: PropTypes.oneOfType([
PropTypes.string,
PropTypes.number
]),
message: PropTypes.string,
payment_request: PropTypes.string,
setAmount: PropTypes.func.isRequired, setAmount: PropTypes.func.isRequired,
setMessage: PropTypes.func.isRequired, setMessage: PropTypes.func.isRequired,
setPaymentRequest: PropTypes.func.isRequired, setPaymentRequest: PropTypes.func.isRequired,
currency: PropTypes.string,
btcTicker: PropTypes.object,
isOpen: PropTypes.bool.isRequired, isOpen: PropTypes.bool.isRequired,
close: PropTypes.func.isRequired, close: PropTypes.func.isRequired,
createInvoice: PropTypes.func.isRequired, createInvoice: PropTypes.func.isRequired,

178
app/routes/app/components/components/Nav.js

@ -1,5 +1,5 @@
// @flow import React from 'react'
import React, { Component } from 'react' import PropTypes from 'prop-types'
import { NavLink } from 'react-router-dom' import { NavLink } from 'react-router-dom'
import ReactSVG from 'react-svg' import ReactSVG from 'react-svg'
import { MdAccountBalanceWallet, MdSettings } from 'react-icons/lib/md' import { MdAccountBalanceWallet, MdSettings } from 'react-icons/lib/md'
@ -7,102 +7,92 @@ import { FaClockO, FaBitcoin, FaDollar } from 'react-icons/lib/fa'
import { btc } from '../../../../utils' import { btc } from '../../../../utils'
import styles from './Nav.scss' import styles from './Nav.scss'
class Nav extends Component { const Nav = ({ ticker, balance, setCurrency, formClicked }) => (
render() { <nav className={styles.nav}>
const { <ul className={styles.info}>
ticker, <li className={`${styles.currencies} ${styles.link}`}>
balance, <span
setCurrency, data-hint={ticker.btcTicker ? ticker.btcTicker.price_usd : null}
formClicked className={`${styles.currency} ${ticker.currency === 'btc' ? styles.active : ''} hint--bottom`}
} = this.props onClick={() => setCurrency('btc')}
>
<FaBitcoin />
</span>
<span
className={`${styles.currency} ${ticker.currency === 'usd' ? styles.active : ''}`}
onClick={() => setCurrency('usd')}
>
<FaDollar />
</span>
</li>
<li className={`${styles.balance} ${styles.link}`}>
<p data-hint='Wallet balance' className='hint--bottom-left'>
<span>{ticker.currency === 'btc' ? <FaBitcoin /> : <FaDollar />}</span>
<span>
{
ticker.currency === 'btc' ?
btc.satoshisToBtc(balance.walletBalance)
:
btc.satoshisToUsd(balance.walletBalance, ticker.btcTicker.price_usd)
}
</span>
</p>
<p data-hint='Channel balance' className='hint--bottom-left'>
<span>
{ticker.currency === 'btc' ? <FaBitcoin /> : <FaDollar />}
</span>
<span>
{
ticker.currency === 'btc' ?
btc.satoshisToBtc(balance.channelBalance)
:
btc.satoshisToUsd(balance.channelBalance, ticker.btcTicker.price_usd)
}
</span>
</p>
</li>
</ul>
return ( <div className={styles.logo}>
<nav className={styles.nav}> <ReactSVG path='../resources/zap_2.svg' />
<ul className={styles.info}> </div>
<li className={`${styles.currencies} ${styles.link}`}>
<span
data-hint={ticker.btcTicker ? ticker.btcTicker.price_usd : null}
className={`${styles.currency} ${ticker.currency === 'btc' ? styles.active : ''} hint--bottom`}
onClick={() => setCurrency('btc')}
>
<FaBitcoin />
</span>
<span
className={`${styles.currency} ${ticker.currency === 'usd' ? styles.active : ''}`}
onClick={() => setCurrency('usd')}
>
<FaDollar />
</span>
</li>
<li className={`${styles.balance} ${styles.link}`}>
<p data-hint='Wallet balance' className='hint--bottom-left'>
<span>{ticker.currency === 'btc' ? <FaBitcoin /> : <FaDollar />}</span>
<span>
{
ticker.currency === 'btc' ?
btc.satoshisToBtc(balance.walletBalance)
:
btc.satoshisToUsd(balance.walletBalance, ticker.btcTicker.price_usd)
}
</span>
</p>
<p data-hint='Channel balance' className='hint--bottom-left'>
<span>
{ticker.currency === 'btc' ? <FaBitcoin /> : <FaDollar />}
</span>
<span>
{
ticker.currency === 'btc' ?
btc.satoshisToBtc(balance.channelBalance)
:
btc.satoshisToUsd(balance.channelBalance, ticker.btcTicker.price_usd)
}
</span>
</p>
</li>
</ul>
<div className={styles.logo}> <ul className={styles.links}>
<ReactSVG path='../resources/zap_2.svg' /> <li>
</div> <NavLink exact to='/' activeClassName={styles.active} className={styles.link}>
<FaClockO />
<ul className={styles.links}> <span>Activity</span>
<li> </NavLink>
<NavLink exact to='/' activeClassName={styles.active} className={styles.link}> </li>
<FaClockO /> <li>
<span>Activity</span> <NavLink exact to='/wallet' activeClassName={styles.active} className={styles.link}>
</NavLink> <MdAccountBalanceWallet />
</li> <span>Wallet</span>
<li> </NavLink>
<NavLink exact to='/wallet' activeClassName={styles.active} className={styles.link}> </li>
<MdAccountBalanceWallet /> <li>
<span>Wallet</span> <NavLink to='/settings' activeClassName={styles.active} className={styles.link}>
</NavLink> <MdSettings />
</li> <span>Settings</span>
<li> </NavLink>
<NavLink to='/settings' activeClassName={styles.active} className={styles.link}> </li>
<MdSettings /> </ul>
<span>Settings</span> <div className={styles.buttons}>
</NavLink> <div className={styles.button} onClick={() => formClicked('pay')}>
</li> <span>Pay</span>
</ul> </div>
<div className={styles.buttons}> <div className={styles.button} onClick={() => formClicked('request')}>
<div className={styles.button} onClick={() => formClicked('pay')}> <span>Request</span>
<span>Pay</span> </div>
</div> </div>
<div className={styles.button} onClick={() => formClicked('request')}> </nav>
<span>Request</span> )
</div>
</div>
</nav>
)
}
}
Nav.propTypes = { Nav.propTypes = {
ticker: React.PropTypes.object.isRequired, ticker: PropTypes.object.isRequired,
balance: React.PropTypes.object.isRequired, balance: PropTypes.object.isRequired,
formClicked: React.PropTypes.func.isRequired setCurrency: PropTypes.func.isRequired,
formClicked: PropTypes.func.isRequired
} }
export default Nav export default Nav

9
app/routes/app/containers/AppContainer.js

@ -3,11 +3,16 @@ import App from '../components/App'
import { fetchTicker, setCurrency } from '../../../reducers/ticker' import { fetchTicker, setCurrency } from '../../../reducers/ticker'
import { fetchBalance } from '../../../reducers/balance' import { fetchBalance } from '../../../reducers/balance'
import { fetchInfo } from '../../../reducers/info' import { fetchInfo } from '../../../reducers/info'
import { setForm } from '../../../reducers/form'
import { createInvoice, fetchInvoice } from '../../../reducers/invoice' import { createInvoice, fetchInvoice } from '../../../reducers/invoice'
import { payInvoice } from '../../../reducers/payment' import { payInvoice } from '../../../reducers/payment'
import { fetchChannels } from '../../../reducers/channels' import { fetchChannels } from '../../../reducers/channels'
import { setAmount, setMessage, setPubkey, setPaymentRequest } from '../../../reducers/form' import {
setForm,
setAmount,
setMessage,
setPubkey,
setPaymentRequest
} from '../../../reducers/form'
const mapDispatchToProps = { const mapDispatchToProps = {
fetchTicker, fetchTicker,

16
app/routes/wallet/components/Wallet.js

@ -73,7 +73,21 @@ class Wallet extends Component {
Wallet.propTypes = { Wallet.propTypes = {
fetchInfo: PropTypes.func.isRequired, fetchInfo: PropTypes.func.isRequired,
fetchPeers: PropTypes.func.isRequired, fetchPeers: PropTypes.func.isRequired,
fetchChannels: PropTypes.func.isRequired fetchChannels: PropTypes.func.isRequired,
info: PropTypes.object.isRequired,
ticker: PropTypes.object.isRequired,
peers: PropTypes.object.isRequired,
channels: PropTypes.object.isRequired,
setPeer: PropTypes.func.isRequired,
setChannel: PropTypes.func.isRequired,
peerModalOpen: PropTypes.bool.isRequired,
channelModalOpen: PropTypes.bool.isRequired,
setPeerForm: PropTypes.func.isRequired,
setChannelForm: PropTypes.func.isRequired,
connectRequest: PropTypes.func.isRequired,
disconnectRequest: PropTypes.func.isRequired,
allChannels: PropTypes.array.isRequired,
openChannel: PropTypes.func.isRequired
} }

4
app/routes/wallet/components/components/Channels/Channels.js

@ -37,11 +37,11 @@ const Channels = ({
{ {
!channelsLoading ? !channelsLoading ?
allChannels.map((channel, index) => { allChannels.map((channel, index) => {
if (channel.hasOwnProperty('blocks_till_open')) { if (Object.prototype.hasOwnProperty.call(channel, 'blocks_till_open')) {
return ( return (
<OpenPendingChannel key={index} channel={channel} ticker={ticker} /> <OpenPendingChannel key={index} channel={channel} ticker={ticker} />
) )
} else if (channel.hasOwnProperty('closing_txid')) { } else if (Object.prototype.hasOwnProperty.call(channel, 'closing_txid')) {
return ( return (
<ClosedPendingChannel key={index} channel={channel} ticker={ticker} /> <ClosedPendingChannel key={index} channel={channel} ticker={ticker} />
) )

26
app/routes/wallet/components/components/Channels/components/ChannelForm/ChannelForm.js

@ -7,7 +7,8 @@ import styles from './ChannelForm.scss'
const ChannelForm = ({ form, setForm, ticker, peers, openChannel }) => { const ChannelForm = ({ form, setForm, ticker, peers, openChannel }) => {
const submitClicked = () => { const submitClicked = () => {
const { form: { node_key, local_amt, push_amt }, openChannel, ticker } = this.props const { node_key, local_amt, push_amt } = form
const localamt = ticker.currency === 'btc' ? btc.btcToSatoshis(local_amt) : btc.btcToSatoshis(usd.usdToBtc(local_amt, ticker.btcTicker.price_usd)) const localamt = ticker.currency === 'btc' ? btc.btcToSatoshis(local_amt) : btc.btcToSatoshis(usd.usdToBtc(local_amt, ticker.btcTicker.price_usd))
const pushamt = ticker.currency === 'btc' ? btc.btcToSatoshis(push_amt) : btc.btcToSatoshis(usd.usdToBtc(push_amt, ticker.btcTicker.price_usd)) const pushamt = ticker.currency === 'btc' ? btc.btcToSatoshis(push_amt) : btc.btcToSatoshis(usd.usdToBtc(push_amt, ticker.btcTicker.price_usd))
@ -47,17 +48,18 @@ const ChannelForm = ({ form, setForm, ticker, peers, openChannel }) => {
<h1 className={styles.title}>Open a new channel</h1> <h1 className={styles.title}>Open a new channel</h1>
<section className={styles.pubkey}> <section className={styles.pubkey}>
<label><FaUser /></label> <label htmlFor='nodekey'><FaUser /></label>
<input <input
type='text' type='text'
size='' size=''
placeholder='Peer public key' placeholder='Peer public key'
value={form.node_key} value={form.node_key}
onChange={event => setForm({ node_key: event.target.value })} onChange={event => setForm({ node_key: event.target.value })}
id='nodekey'
/> />
</section> </section>
<section className={styles.local}> <section className={styles.local}>
<label> <label htmlFor='localamount'>
{ {
ticker.currency === 'btc' ? ticker.currency === 'btc' ?
<FaBitcoin /> <FaBitcoin />
@ -71,10 +73,11 @@ const ChannelForm = ({ form, setForm, ticker, peers, openChannel }) => {
placeholder='Local amount' placeholder='Local amount'
value={form.local_amt} value={form.local_amt}
onChange={event => setForm({ local_amt: event.target.value })} onChange={event => setForm({ local_amt: event.target.value })}
amount='localamount'
/> />
</section> </section>
<section className={styles.push}> <section className={styles.push}>
<label> <label htmlFor='pushamount'>
{ {
ticker.currency === 'btc' ? ticker.currency === 'btc' ?
<FaBitcoin /> <FaBitcoin />
@ -88,6 +91,7 @@ const ChannelForm = ({ form, setForm, ticker, peers, openChannel }) => {
placeholder='Push amount' placeholder='Push amount'
value={form.push_amt} value={form.push_amt}
onChange={event => setForm({ push_amt: event.target.value })} onChange={event => setForm({ push_amt: event.target.value })}
id='pushamount'
/> />
</section> </section>
@ -96,10 +100,16 @@ const ChannelForm = ({ form, setForm, ticker, peers, openChannel }) => {
{ {
peers.length ? peers.length ?
peers.map(peer => peers.map(peer =>
(<li key={peer.peer_id} className={styles.peer} onClick={() => setForm({ node_key: peer.pub_key })}> (
<h4>{peer.address}</h4> <li
<h1>{peer.pub_key}</h1> key={peer.peer_id}
</li>) className={styles.peer}
onClick={() => setForm({ node_key: peer.pub_key })}
>
<h4>{peer.address}</h4>
<h1>{peer.pub_key}</h1>
</li>
)
) )
: :
null null

159
app/routes/wallet/components/components/Channels/components/ChannelModal/ChannelModal.js

@ -1,93 +1,94 @@
// @flow
import { shell } from 'electron' import { shell } from 'electron'
import React, { Component } from 'react' import React from 'react'
import PropTypes from 'prop-types'
import ReactModal from 'react-modal' import ReactModal from 'react-modal'
import styles from './ChannelModal.scss' import styles from './ChannelModal.scss'
class ChannelModal extends Component { const ChannelModal = ({ isOpen, resetChannel, channel }) => {
render() { const customStyles = {
const customStyles = { overlay: {
overlay: { cursor: 'pointer',
cursor: 'pointer', overflowY: 'auto'
overflowY: 'auto' },
}, content: {
content: { top: 'auto',
top: 'auto', left: '20%',
left: '20%', right: '0',
right: '0', bottom: 'auto',
bottom: 'auto', width: '40%',
width: '40%', margin: '50px auto',
margin: '50px auto', padding: '40px'
padding: '40px'
}
} }
}
const { isOpen, resetChannel, channel } = this.props return (
<ReactModal
return ( isOpen={isOpen}
<ReactModal contentLabel='No Overlay Click Modal'
isOpen={isOpen} ariaHideApp
contentLabel='No Overlay Click Modal' shouldCloseOnOverlayClick
ariaHideApp onRequestClose={() => resetChannel(null)}
shouldCloseOnOverlayClick parentSelector={() => document.body}
onRequestClose={() => resetChannel(null)} style={customStyles}
parentSelector={() => document.body} >
style={customStyles} {
> channel ?
{ <div className={styles.channel}>
channel ? <header className={styles.header}>
<div className={styles.channel}> <h1 data-hint='Remote public key' className='hint--top-left'>{channel.remote_pubkey}</h1>
<header className={styles.header}> <h2
<h1 data-hint='Remote public key' className='hint--top-left'>{channel.remote_pubkey}</h1> data-hint='Channel point'
<h2 className='hint--top-left'
data-hint='Channel point' onClick={() => shell.openExternal(`https://testnet.smartbit.com.au/tx/${channel.channel_point.split(':')[0]}`)}
className='hint--top-left' >
onClick={() => shell.openExternal(`https://testnet.smartbit.com.au/tx/${channel.channel_point.split(':')[0]}`)} {channel.channel_point}
> </h2>
{channel.channel_point} </header>
</h2>
</header>
<div className={styles.balances}> <div className={styles.balances}>
<section className={styles.capacity}> <section className={styles.capacity}>
<h3>{channel.capacity}</h3> <h3>{channel.capacity}</h3>
<span>Capacity</span> <span>Capacity</span>
</section>
<div className={styles.balance}>
<section className={styles.local}>
<h4>{channel.local_balance}</h4>
<span>Local</span>
</section>
<section className={styles.remote}>
<h4>{channel.remote_balance}</h4>
<span>Remote</span>
</section> </section>
<div className={styles.balance}>
<section className={styles.local}>
<h4>{channel.local_balance}</h4>
<span>Local</span>
</section>
<section className={styles.remote}>
<h4>{channel.remote_balance}</h4>
<span>Remote</span>
</section>
</div>
</div>
<div className={styles.details}>
<dl>
<dt>Sent</dt>
<dd>{channel.total_satoshis_sent}</dd>
<dt>Received</dt>
<dd>{channel.total_satoshis_received}</dd>
<dt>Updates</dt>
<dd>{channel.num_updates}</dd>
</dl>
</div>
<div className={styles.close}>
<div>Close channel</div>
</div> </div>
<footer className={styles.active}>
<p>{channel.active ? 'Active' : 'Not active'}</p>
</footer>
</div> </div>
: <div className={styles.details}>
null <dl>
} <dt>Sent</dt>
</ReactModal> <dd>{channel.total_satoshis_sent}</dd>
) <dt>Received</dt>
} <dd>{channel.total_satoshis_received}</dd>
<dt>Updates</dt>
<dd>{channel.num_updates}</dd>
</dl>
</div>
<div className={styles.close}>
<div>Close channel</div>
</div>
<footer className={styles.active}>
<p>{channel.active ? 'Active' : 'Not active'}</p>
</footer>
</div>
:
null
}
</ReactModal>
)
} }
ChannelModal.propTypes = {
isOpen: PropTypes.bool.isRequired,
resetChannel: PropTypes.func.isRequired,
channel: PropTypes.object
}
export default ChannelModal export default ChannelModal

6
app/routes/wallet/components/components/Channels/components/ClosedPendingChannel/ClosedPendingChannel.js

@ -4,7 +4,7 @@ import PropTypes from 'prop-types'
import { btc } from '../../../../../../../utils' import { btc } from '../../../../../../../utils'
import styles from './ClosedPendingChannel.scss' import styles from './ClosedPendingChannel.scss'
const ClosedPendingChannel = ({ ticker, channel: { channel, closing_txid }, setChannel }) => ( const ClosedPendingChannel = ({ ticker, channel: { channel, closing_txid } }) => (
<li className={styles.channel} onClick={() => shell.openExternal(`https://testnet.smartbit.com.au/tx/${closing_txid}`)}> <li className={styles.channel} onClick={() => shell.openExternal(`https://testnet.smartbit.com.au/tx/${closing_txid}`)}>
<h1 className={styles.closing}>Status: Closing</h1> <h1 className={styles.closing}>Status: Closing</h1>
<div className={styles.left}> <div className={styles.left}>
@ -59,9 +59,7 @@ const ClosedPendingChannel = ({ ticker, channel: { channel, closing_txid }, setC
ClosedPendingChannel.propTypes = { ClosedPendingChannel.propTypes = {
ticker: PropTypes.object.isRequired, ticker: PropTypes.object.isRequired,
channel: PropTypes.object.isRequired, channel: PropTypes.object.isRequired
closing_txid: PropTypes.string,
setChannel: PropTypes.func
} }
export default ClosedPendingChannel export default ClosedPendingChannel

1
app/routes/wallet/components/components/Channels/components/OpenPendingChannel/OpenPendingChannel.js

@ -1,4 +1,3 @@
// @flow
import { shell } from 'electron' import { shell } from 'electron'
import React from 'react' import React from 'react'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'

137
app/routes/wallet/components/components/Peers/components/PeerForm/PeerForm.js

@ -1,80 +1,85 @@
// @flow import React from 'react'
import React, { Component } from 'react' import PropTypes from 'prop-types'
import ReactModal from 'react-modal' import ReactModal from 'react-modal'
import styles from './PeerForm.scss' import styles from './PeerForm.scss'
class PeerForm extends Component { const PeerForm = ({ form, setForm, connect }) => {
render() { const submit = () => {
const submit = () => { const { pubkey, host } = form
const { form: { pubkey, host } } = this.props
this.props.connect({ pubkey, host }).then((success) => { connect({ pubkey, host }).then((success) => {
if (success.data) { setForm({ isOpen: false }) } if (success.data) { setForm({ isOpen: false }) }
}) })
} }
const customStyles = { const customStyles = {
overlay: { overlay: {
cursor: 'pointer', cursor: 'pointer',
overflowY: 'auto' overflowY: 'auto'
}, },
content: { content: {
top: 'auto', top: 'auto',
left: '20%', left: '20%',
right: '0', right: '0',
bottom: 'auto', bottom: 'auto',
width: '40%', width: '40%',
margin: '50px auto', margin: '50px auto',
padding: '40px' padding: '40px'
}
} }
}
const { form, setForm, connect } = this.props return (
return ( <div>
<div> <ReactModal
<ReactModal isOpen={form.isOpen}
isOpen={form.isOpen} contentLabel='No Overlay Click Modal'
contentLabel='No Overlay Click Modal' ariaHideApp
ariaHideApp shouldCloseOnOverlayClick
shouldCloseOnOverlayClick onRequestClose={() => setForm({ isOpen: false })}
onRequestClose={() => setForm({ isOpen: false })} parentSelector={() => document.body}
parentSelector={() => document.body} style={customStyles}
style={customStyles} >
> <div className={styles.form}>
<div className={styles.form}> <h1 className={styles.title}>Connect to a peer</h1>
<h1 className={styles.title}>Connect to a peer</h1>
<section className={styles.pubkey}> <section className={styles.pubkey}>
<label>Pubkey</label> <label htmlFor='pubkey'>Pubkey</label>
<input <input
type='text' type='text'
size='' size=''
placeholder='Public key' placeholder='Public key'
value={form.pubkey} value={form.pubkey}
onChange={event => setForm({ pubkey: event.target.value })} onChange={event => setForm({ pubkey: event.target.value })}
/> id='pubkey'
</section> />
<section className={styles.local}> </section>
<label>Address</label> <section className={styles.local}>
<input <label htmlFor='address'>Address</label>
type='text' <input
size='' type='text'
placeholder='Host address' size=''
value={form.host} placeholder='Host address'
onChange={event => setForm({ host: event.target.value })} value={form.host}
/> onChange={event => setForm({ host: event.target.value })}
</section> id='address'
/>
</section>
<div className={styles.buttonGroup}> <div className={styles.buttonGroup}>
<div className={styles.button} onClick={submit}> <div className={styles.button} onClick={submit}>
Submit Submit
</div>
</div> </div>
</div> </div>
</ReactModal> </div>
</div> </ReactModal>
) </div>
} )
}
PeerForm.propTypes = {
form: PropTypes.object.isRequired,
setForm: PropTypes.func.isRequired,
connect: PropTypes.func.isRequired
} }
export default PeerForm export default PeerForm

128
app/routes/wallet/components/components/Peers/components/PeerModal/PeerModal.js

@ -1,76 +1,76 @@
// @flow import React from 'react'
import React, { Component } from 'react' import PropTypes from 'prop-types'
import ReactModal from 'react-modal' import ReactModal from 'react-modal'
import styles from './PeerModal.scss' import styles from './PeerModal.scss'
class PeerModal extends Component { const PeerModal = ({ isOpen, resetPeer, peer, disconnect }) => {
render() { const disconnectClicked = () => {
const disconnectClicked = () => { disconnect({ pubkey: peer.pub_key })
const { peer, disconnect } = this.props .then(success => (success ? resetPeer(null) : null))
}
disconnect({ pubkey: peer.pub_key }) const customStyles = {
.then(success => (success ? resetPeer(null) : null)) overlay: {
cursor: 'pointer',
overflowY: 'auto'
},
content: {
top: 'auto',
left: '20%',
right: '0',
bottom: 'auto',
width: '40%',
margin: '50px auto',
padding: '40px'
} }
}
const customStyles = { return (
overlay: { <ReactModal
cursor: 'pointer', isOpen={isOpen}
overflowY: 'auto' contentLabel='No Overlay Click Modal'
}, ariaHideApp
content: { shouldCloseOnOverlayClick
top: 'auto', onRequestClose={() => resetPeer(null)}
left: '20%', parentSelector={() => document.body}
right: '0', style={customStyles}
bottom: 'auto', >
width: '40%', {
margin: '50px auto', peer ?
padding: '40px' <div className={styles.peer}>
} <header className={styles.header}>
} <h1 data-hint='Peer address' className='hint--top-left'>{peer.address}</h1>
<h2 data-hint='Peer public key' className='hint--top-left'>{peer.pub_key}</h2>
const { isOpen, resetPeer, peer, disconnect } = this.props </header>
return (
<ReactModal
isOpen={isOpen}
contentLabel='No Overlay Click Modal'
ariaHideApp
shouldCloseOnOverlayClick
onRequestClose={() => resetPeer(null)}
parentSelector={() => document.body}
style={customStyles}
>
{
peer ?
<div className={styles.peer}>
<header className={styles.header}>
<h1 data-hint='Peer address' className='hint--top-left'>{peer.address}</h1>
<h2 data-hint='Peer public key' className='hint--top-left'>{peer.pub_key}</h2>
</header>
<div className={styles.details}> <div className={styles.details}>
<dl> <dl>
<dt>Satoshis Received</dt> <dt>Satoshis Received</dt>
<dd>{peer.sat_recv}</dd> <dd>{peer.sat_recv}</dd>
<dt>Satoshis Sent</dt> <dt>Satoshis Sent</dt>
<dd>{peer.sat_sent}</dd> <dd>{peer.sat_sent}</dd>
<dt>Bytes Received</dt> <dt>Bytes Received</dt>
<dd>{peer.bytes_recv}</dd> <dd>{peer.bytes_recv}</dd>
<dt>Bytes Sent</dt> <dt>Bytes Sent</dt>
<dd>{peer.bytes_sent}</dd> <dd>{peer.bytes_sent}</dd>
</dl> </dl>
</div>
<div className={styles.close} onClick={disconnectClicked}>
<div>Disconnect peer</div>
</div>
</div> </div>
: <div className={styles.close} onClick={disconnectClicked}>
null <div>Disconnect peer</div>
} </div>
</ReactModal> </div>
) :
} null
}
</ReactModal>
)
} }
PeerModal.propTypes = {
isOpen: PropTypes.bool.isRequired,
resetPeer: PropTypes.func.isRequired,
peer: PropTypes.object,
disconnect: PropTypes.func.isRequired
}
export default PeerModal export default PeerModal

14
app/store/configureStore.prod.js

@ -1,16 +1,14 @@
// @flow import { createStore, applyMiddleware } from 'redux'
import { createStore, applyMiddleware } from 'redux'; import thunk from 'redux-thunk'
import thunk from 'redux-thunk'; import { createBrowserHistory } from 'history'
import { createBrowserHistory } from 'history'; import { routerMiddleware } from 'react-router-redux'
import { routerMiddleware } from 'react-router-redux'; import rootReducer from '../reducers'
import rootReducer from '../reducers';
import type { counterStateType } from '../reducers/counter';
const history = createBrowserHistory(); const history = createBrowserHistory();
const router = routerMiddleware(history); const router = routerMiddleware(history);
const enhancer = applyMiddleware(thunk, router); const enhancer = applyMiddleware(thunk, router);
function configureStore(initialState?: counterStateType) { function configureStore(initialState) {
return createStore(rootReducer, initialState, enhancer); return createStore(rootReducer, initialState, enhancer);
} }

13
app/utils/btc.js

@ -1,26 +1,27 @@
import sb from 'satoshi-bitcoin' import sb from 'satoshi-bitcoin'
export function btcToSatoshis(btc) { export function btcToSatoshis(btc) {
if (btc == undefined || btc === '') return if (btc === undefined || btc === null || btc === '') return null
return sb.toSatoshi(btc) return sb.toSatoshi(btc)
} }
export function satoshisToBtc(satoshis) { export function satoshisToBtc(satoshis) {
if (satoshis == undefined || satoshis === '') return if (satoshis === undefined || satoshis === null || satoshis === '') return null
return sb.toBitcoin(satoshis).toFixed(8) return sb.toBitcoin(satoshis).toFixed(8)
} }
export function btcToUsd(btc, price) {
return parseFloat((btc * price).toFixed(2)).toLocaleString('en')
}
export function satoshisToUsd(satoshis, price) { export function satoshisToUsd(satoshis, price) {
if (satoshis == undefined || satoshis === '') return if (satoshis === undefined || satoshis === null || satoshis === '') return null
return btcToUsd(satoshisToBtc(satoshis), price) return btcToUsd(satoshisToBtc(satoshis), price)
} }
export function btcToUsd(btc, price) {
return parseFloat((btc * price).toFixed(2)).toLocaleString('en')
}
export default { export default {
btcToSatoshis, btcToSatoshis,

2
app/utils/usd.js

@ -1,5 +1,5 @@
export function usdToBtc(usd, rate) { export function usdToBtc(usd, rate) {
if (usd === undefined || usd === '') return null if (usd === undefined || usd === null || usd === '') return null
return (usd / rate).toFixed(8) return (usd / rate).toFixed(8)
} }

2
test/e2e/e2e.spec.js

@ -1,3 +1,5 @@
/* eslint-disable */
import { Application } from 'spectron'; import { Application } from 'spectron';
import electronPath from 'electron'; import electronPath from 'electron';
import path from 'path'; import path from 'path';

1
webpack.config.renderer.dev.js

@ -1,3 +1,4 @@
/* eslint-disable */
/* eslint global-require: 0, import/no-dynamic-require: 0 */ /* eslint global-require: 0, import/no-dynamic-require: 0 */
/** /**

Loading…
Cancel
Save