Browse Source

fix(merge): fix merging conflicts with master

renovate/lint-staged-8.x
Jack Mallers 7 years ago
parent
commit
4017e29cdb
  1. 2
      .eslintrc
  2. 3
      .gitignore
  3. 14
      README.md
  4. 3
      app/app.global.scss
  5. 2
      app/components/ChannelForm/StepOne.js
  6. 4
      app/components/Channels/Channel.scss
  7. 25
      app/components/Channels/OpenPendingChannel.js
  8. 13
      app/components/Channels/OpenPendingChannel.scss
  9. 2
      app/components/LndSyncing/LndSyncing.js
  10. 55
      app/components/Peers/PeerModal.js
  11. 42
      app/components/Peers/PeerModal.scss
  12. 56
      app/components/Wallet/ReceiveModal.js
  13. 79
      app/components/Wallet/ReceiveModal.scss
  14. 21
      app/components/Wallet/Wallet.js
  15. 4
      app/components/Wallet/Wallet.scss
  16. 14
      app/containers/Root.js
  17. 22
      app/index.js
  18. 2
      app/lnd/config/index.js
  19. 2
      app/lnd/lib/lightning.js
  20. 2
      app/lnd/methods/paymentsController.js
  21. 2
      app/lnd/subscribe/transactions.js
  22. 42
      app/lnd/utils/index.js
  23. 1
      app/main.dev.js
  24. 2
      app/package.json
  25. 2
      app/reducers/address.js
  26. 19
      app/reducers/channels.js
  27. 5
      app/reducers/info.js
  28. 4
      app/reducers/lnd.js
  29. 6
      app/reducers/network.js
  30. 2
      app/reducers/peers.js
  31. 49
      app/routes/activity/components/components/Modal/Invoice/Invoice.js
  32. 79
      app/routes/activity/components/components/Modal/Invoice/Invoice.scss
  33. 13
      app/routes/activity/components/components/Modal/Modal.js
  34. 13
      app/routes/activity/components/components/Modal/Modal.scss
  35. 33
      app/routes/activity/components/components/Modal/Payment/Payment.js
  36. 48
      app/routes/activity/components/components/Modal/Payment/Payment.scss
  37. 54
      app/routes/activity/components/components/Modal/Transaction/Transaction.js
  38. 53
      app/routes/activity/components/components/Modal/Transaction/Transaction.scss
  39. 2
      app/routes/app/components/App.js
  40. 10
      app/routes/channels/components/Channels.js
  41. 2
      app/routes/peers/components/Peers.js
  42. 34
      app/store/configureStore.dev.js
  43. 4
      app/store/configureStore.js
  44. 35
      app/yarn.lock
  45. 2
      internals/mocks/fileMock.js
  46. 16
      internals/scripts/CheckBuiltsExist.js
  47. 8
      internals/scripts/CheckNodeEnv.js
  48. 2
      package.json
  49. BIN
      resources/bin/darwin/lnd
  50. 3
      test/components/Nav.spec.js
  51. 6
      test/example.js
  52. 11
      test/reducers/__snapshots__/peers.spec.js.snap
  53. 12
      test/runTests.js
  54. 6
      webpack.config.base.js
  55. 4
      webpack.config.eslint.js
  56. 16
      webpack.config.main.prod.js
  57. 18
      webpack.config.renderer.dev.dll.js
  58. 20
      webpack.config.renderer.prod.js
  59. 6
      yarn.lock

2
.eslintrc

@ -11,7 +11,7 @@
}, },
"rules": { "rules": {
"comma-dangle": ["error", "never"], "comma-dangle": ["error", "never"],
"semi": 0, "semi": ["error", "never"],
"indent": 2, "indent": 2,
"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"] }],

3
.gitignore

@ -50,3 +50,6 @@ main.js.map
.idea .idea
npm-debug.log.* npm-debug.log.*
# lnd binary
resources/bin/*

14
README.md

@ -33,6 +33,18 @@ $ cd zap-desktop
$ yarn $ yarn
$ npm run install-grpc $ npm run install-grpc
``` ```
Zap does not store `lnd` binaries in the Github repo so you will now need to go [install lnd](https://github.com/lightningnetwork/lnd/blob/master/docs/INSTALL.md). You can then copy the `lnd` binary that will be located in your `$GOPATH/bin` and paste it into Zap. Zap expectes `lnd` to be in one of these directories depending on your OS:
```
# mac
resources/bin/darwin
#linux
resources/bin/linux
#win32
resources/bin/win32
```
Then to start it: Then to start it:
```bash ```bash
@ -53,7 +65,7 @@ $ npm run lint
Please see the [contributing guide](https://github.com/LN-Zap/zap-desktop/blob/master/CONTRIBUTING.md) Please see the [contributing guide](https://github.com/LN-Zap/zap-desktop/blob/master/CONTRIBUTING.md)
## Todos (Last updated August 16th): ## Todos (Last updated August 16th):
Join us on [slack](https://join.slack.com/t/zaphq/shared_invite/enQtMjYzNDQyMTQxOTU4LTY3ZDk4M2Y3YmEzOTM1ODk1NjEwYjJmMmY3NmU2YTM3ZmJmOTViODcxN2E3MmYyNjAxOGNmNzY1ZDhhYmEwMDI) before tackling a todo to avoid duplicate work. Join us on [slack](https://join.slack.com/t/zaphq/shared_invite/enQtMjc5Njg3NjU5MzMzLWE1M2RiNjYxNWEyMTRjMzhmZDIyNTQ0YTRjNDg4MWNiMzI1ODNlODhhMzE5ZWVmMGVkOWVkMTVmNzBhNDhiZjQ) before tackling a todo to avoid duplicate work.
The old todo list was recently removed. Come on slack or check open Github issues to see what contributions are needed. The old todo list was recently removed. Come on slack or check open Github issues to see what contributions are needed.

3
app/app.global.scss

@ -86,7 +86,8 @@ body {
padding-bottom: 15px; padding-bottom: 15px;
border-radius: 2px; border-radius: 2px;
text-align: center; text-align: center;
font-size: 18px; font-size: 16px;
letter-spacing: 1.5px;
transition: none; transition: none;
position: relative; position: relative;
color: white; color: white;

2
app/components/ChannelForm/StepOne.js

@ -5,7 +5,7 @@ import styles from './StepOne.scss'
class StepOne extends Component { class StepOne extends Component {
constructor(props) { constructor(props) {
super(props); super(props)
this.state = { this.state = {
peers: props.peers, peers: props.peers,
searchQuery: '' searchQuery: ''

4
app/components/Channels/Channel.scss

@ -2,15 +2,17 @@
.channel { .channel {
position: relative; position: relative;
background: $lightgrey; background: $white;
margin: 5px 0; margin: 5px 0;
padding: 10px; padding: 10px;
border-top: 1px solid $white; border-top: 1px solid $white;
cursor: pointer; cursor: pointer;
transition: all 0.25s; transition: all 0.25s;
box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2);
&:hover { &:hover {
opacity: 0.75; opacity: 0.75;
box-shadow: 0 8px 16px 0 rgba(0,0,0,0.2);
} }
&:first-child { &:first-child {

25
app/components/Channels/OpenPendingChannel.js

@ -4,17 +4,20 @@ import PropTypes from 'prop-types'
import { btc } from 'utils' import { btc } from 'utils'
import styles from './OpenPendingChannel.scss' import styles from './OpenPendingChannel.scss'
const OpenPendingChannel = ({ ticker, channel: { channel }, currentTicker, explorerLinkBase }) => ( const OpenPendingChannel = ({ ticker, channel, currentTicker, explorerLinkBase }) => (
<li className={styles.channel} onClick={() => shell.openExternal(`${explorerLinkBase}/tx/${channel.channel_point.split(':')[0]}`)}> <li className={styles.channel} onClick={() => shell.openExternal(`${explorerLinkBase}/tx/${channel.channel.channel_point.split(':')[0]}`)}>
<h1 className={styles.pending}>Opening Channel...</h1> <div className={styles.pending}>
<h1>Opening Channel...</h1>
<span>Blocks till open: {channel.blocks_till_open}</span>
</div>
<div className={styles.left}> <div className={styles.left}>
<section className={styles.remotePubkey}> <section className={styles.remotePubkey}>
<span>Remote Pubkey</span> <span>Remote Pubkey</span>
<h4>{channel.remote_node_pub}</h4> <h4>{channel.channel.remote_node_pub}</h4>
</section> </section>
<section className={styles.channelPoint}> <section className={styles.channelPoint}>
<span>Channel Point</span> <span>Channel Point</span>
<h4>{channel.channel_point}</h4> <h4>{channel.channel.channel_point}</h4>
</section> </section>
</div> </div>
<div className={styles.right}> <div className={styles.right}>
@ -23,9 +26,9 @@ const OpenPendingChannel = ({ ticker, channel: { channel }, currentTicker, explo
<h2> <h2>
{ {
ticker.currency === 'btc' ? ticker.currency === 'btc' ?
btc.satoshisToBtc(channel.capacity) btc.satoshisToBtc(channel.channel.capacity)
: :
btc.satoshisToUsd(channel.capacity, currentTicker.price_usd) btc.satoshisToUsd(channel.channel.capacity, currentTicker.price_usd)
} }
</h2> </h2>
</section> </section>
@ -34,9 +37,9 @@ const OpenPendingChannel = ({ ticker, channel: { channel }, currentTicker, explo
<h4> <h4>
{ {
ticker.currency === 'btc' ? ticker.currency === 'btc' ?
btc.satoshisToBtc(channel.local_balance) btc.satoshisToBtc(channel.channel.local_balance)
: :
btc.satoshisToUsd(channel.local_balance, currentTicker.price_usd) btc.satoshisToUsd(channel.channel.local_balance, currentTicker.price_usd)
} }
</h4> </h4>
<span>Local</span> <span>Local</span>
@ -45,9 +48,9 @@ const OpenPendingChannel = ({ ticker, channel: { channel }, currentTicker, explo
<h4> <h4>
{ {
ticker.currency === 'btc' ? ticker.currency === 'btc' ?
btc.satoshisToBtc(channel.remote_balance) btc.satoshisToBtc(channel.channel.remote_balance)
: :
btc.satoshisToUsd(channel.remote_balance, currentTicker.price_usd) btc.satoshisToUsd(channel.channel.remote_balance, currentTicker.price_usd)
} }
</h4> </h4>
<span>Remote</span> <span>Remote</span>

13
app/components/Channels/OpenPendingChannel.scss

@ -13,14 +13,21 @@
opacity: 0.5; opacity: 0.5;
.pending { .pending {
color: $main;
position: absolute; position: absolute;
top: 0; top: 0;
left: 10px; left: 10px;
padding: 10px; padding: 10px;
text-transform: uppercase; text-transform: uppercase;
font-weight: bold; font-weight: bold;
font-size: 10px;
h1 {
color: $main;
font-size: 10px;
}
span {
font-size: 8px;
}
} }
&:first-child { &:first-child {
@ -30,7 +37,7 @@
.left, .right { .left, .right {
padding: 0 10px; padding: 0 10px;
margin-bottom: 5; margin-bottom: 5;
margin-top: 25px; margin-top: 40px;
section { section {
margin-bottom: 20px; margin-bottom: 20px;

2
app/components/LndSyncing/LndSyncing.js

@ -4,7 +4,7 @@ import styles from './LndSyncing.scss'
class LndSyncing extends Component { class LndSyncing extends Component {
constructor(props) { constructor(props) {
super(props); super(props)
this.state = { this.state = {
facts: [ facts: [
{ {

55
app/components/Peers/PeerModal.js

@ -1,6 +1,9 @@
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 { MdClose } from 'react-icons/lib/md'
import styles from './PeerModal.scss' import styles from './PeerModal.scss'
const PeerModal = ({ isOpen, resetPeer, peer, disconnect }) => { const PeerModal = ({ isOpen, resetPeer, peer, disconnect }) => {
@ -16,7 +19,8 @@ const PeerModal = ({ isOpen, resetPeer, peer, disconnect }) => {
bottom: 'auto', bottom: 'auto',
width: '40%', width: '40%',
margin: '50px auto', margin: '50px auto',
padding: '40px' borderRadius: 'none',
padding: '0'
} }
} }
@ -30,32 +34,35 @@ const PeerModal = ({ isOpen, resetPeer, peer, disconnect }) => {
parentSelector={() => document.body} parentSelector={() => document.body}
style={customStyles} style={customStyles}
> >
<div className={styles.closeContainer}>
<span onClick={() => resetPeer(null)}>
<MdClose />
</span>
</div>
{ {
peer ? peer &&
<div className={styles.peer}> <div className={styles.peer}>
<header className={styles.header}> <header className={styles.header}>
<h1 data-hint='Peer address' className='hint--top-left'>{peer.address}</h1> <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> <h2 data-hint='Peer public key' className='hint--top-left'>{peer.pub_key}</h2>
</header> </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>
<div className={styles.close} onClick={() => disconnect({ pubkey: peer.pub_key })}> <div className={styles.close} onClick={() => disconnect({ pubkey: peer.pub_key })}>
<div>Disconnect peer</div> <div>Disconnect peer</div>
</div>
</div> </div>
: </div>
null
} }
</ReactModal> </ReactModal>
) )

42
app/components/Peers/PeerModal.scss

@ -1,29 +1,39 @@
@import '../../variables.scss'; @import '../../variables.scss';
.peer { .closeContainer {
padding: 40px; background: $lightgrey;
text-align: right;
padding: 10px;
span {
color: $darkestgrey;
font-size: 20px;
cursor: pointer;
}
} }
.header { .header {
margin-bottom: 50px; background: $lightgrey;
padding: 20px;
h1 { h1 {
color: $black; color: $black;
text-align: center; text-align: center;
margin-bottom: 5px; margin-bottom: 20px;
font-weight: bold; font-weight: bold;
} }
h2 { h2 {
color: $darkestgrey; color: $darkestgrey;
font-size: 14px; font-size: 12px;
text-align: center; text-align: center;
} }
} }
.details { .details {
width: 75%; dl {
margin: 20px auto; padding: 40px 40px 40px 40px;
}
dt { dt {
text-align: left; text-align: left;
@ -38,36 +48,28 @@
dd { dd {
text-align: right; text-align: right;
font-weight: 400; font-weight: 400;
padding: 19px 0; padding: 30px 0 10px 0;
margin-left: 0; margin-left: 0;
border-top: 1px solid $darkgrey; border-bottom: 1px solid $darkgrey;
} }
} }
.close { .close {
text-align: center; text-align: center;
padding-bottom: 40px;
div { div {
width: 35%;
margin: 0 auto; margin: 0 auto;
cursor: pointer; cursor: pointer;
height: 55px;
min-height: 55px;
text-transform: none;
font-size: 18px; font-size: 18px;
transition: opacity .2s ease-out; color: $red;
background: $red;
color: $white;
border: none; border: none;
font-weight: 500;
padding: 0; padding: 0;
text-align: center; text-align: center;
line-height: 55px;
transition: all 0.25s; transition: all 0.25s;
border-radius: 5px;
&:hover { &:hover {
background: darken($red, 10%); color: lighten($red, 10%);
} }
} }
} }

56
app/components/Wallet/ReceiveModal.js

@ -4,9 +4,11 @@ import ReactModal from 'react-modal'
import copy from 'copy-to-clipboard' import copy from 'copy-to-clipboard'
import QRCode from 'qrcode.react' import QRCode from 'qrcode.react'
import { showNotification } from 'notifications' import { showNotification } from 'notifications'
import { MdClose } from 'react-icons/lib/md'
import { FaCopy } from 'react-icons/lib/fa'
import styles from './ReceiveModal.scss' import styles from './ReceiveModal.scss'
const ReceiveModal = ({ isOpen, hideActivityModal, pubkey, address, newAddress }) => { const ReceiveModal = ({ isOpen, hideActivityModal, pubkey, address, newAddress, qrCodeType, changeQrCode }) => {
const customStyles = { const customStyles = {
overlay: { overlay: {
cursor: 'pointer' cursor: 'pointer'
@ -16,8 +18,10 @@ const ReceiveModal = ({ isOpen, hideActivityModal, pubkey, address, newAddress }
left: '20%', left: '20%',
right: '0', right: '0',
bottom: 'auto', bottom: 'auto',
width: '60%', width: '40%',
margin: '50px auto' margin: '50px auto',
borderRadius: 'none',
padding: '0'
} }
} }
@ -36,22 +40,48 @@ const ReceiveModal = ({ isOpen, hideActivityModal, pubkey, address, newAddress }
parentSelector={() => document.body} parentSelector={() => document.body}
style={customStyles} style={customStyles}
> >
<div className={styles.closeContainer}>
<span onClick={() => hideActivityModal()}>
<MdClose />
</span>
</div>
<div className={styles.container}> <div className={styles.container}>
<section> <header>
<h4>Node Public Key (<span onClick={() => copyOnClick(pubkey)}>Copy</span>)</h4> <div className={styles.qrcodes}>
<p>{pubkey}</p> <QRCode value={qrCodeType === 1 ? address : pubkey} />
</section> </div>
<ul className={styles.tabs}>
<li className={qrCodeType === 1 && styles.active} onClick={changeQrCode}>
Wallet address
</li>
<li className={qrCodeType === 2 && styles.active} onClick={changeQrCode}>
Node pubkey
</li>
</ul>
</header>
<section> <section>
<div className={styles.addressHeader}> <div className={styles.addressHeader}>
<h4>Deposit Address (<span onClick={() => copyOnClick(address)}>Copy</span>)</h4> <h4>Deposit Address</h4>
<span className={styles.newAddress} onClick={() => newAddress('p2pkh')}>New Address</span> <span className={styles.newAddress} onClick={() => newAddress('np2wkh')}>New Address</span>
</div> </div>
<p>{address}</p> <p>
<span>{address}</span>
<span onClick={() => copyOnClick(address)} className='hint--left' data-hint='Copy address'>
<FaCopy />
</span>
</p>
</section>
<div className={styles.qrcode}> <section>
<QRCode value={address} /> <h4>Node Public Key</h4>
</div> <p>
<span>{pubkey}</span>
<span onClick={() => copyOnClick(pubkey)} className='hint--left' data-hint='Copy pubkey'>
<FaCopy />
</span>
</p>
</section> </section>
</div> </div>
</ReactModal> </ReactModal>

79
app/components/Wallet/ReceiveModal.scss

@ -1,15 +1,59 @@
@import '../../variables.scss'; @import '../../variables.scss';
.closeContainer {
background: $lightgrey;
text-align: right;
padding: 10px;
span {
color: $darkestgrey;
font-size: 20px;
cursor: pointer;
}
}
.container { .container {
header {
background: $lightgrey;
padding: 10px 40px 40px;
text-align: center;
.qrcodes {
text-align: center;
margin-top: 20px;
}
.tabs {
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
margin-top: 20px;
li {
margin: 0 20px;
color: $darkestgrey;
transition: all 0.25s;
&:hover {
color: $black;
}
&.active {
color: $black;
font-weight: bold;
}
}
}
}
section { section {
margin: 25px 0; margin: 25px 0;
padding: 25px; padding: 25px;
border-bottom: 1px solid $darkestgrey;
h4 { h4 {
font-size: 14px; font-size: 14px;
font-weight: bold; font-weight: bold;
text-transform: uppercase;
letter-spacing: 1.5px; letter-spacing: 1.5px;
margin-bottom: 10px; margin-bottom: 10px;
@ -19,20 +63,33 @@
} }
} }
.qrcode {
text-align: center;
margin-top: 20px;
}
p { p {
display: flex;
flex-direction: row;
font-family: 'Roboto'; font-family: 'Roboto';
text-align: center;
font-size: 14px; font-size: 14px;
font-weight: 200; font-weight: 200;
border-radius: 7px;
background: $lightgrey; background: $lightgrey;
border: 1px solid $main;
padding: 10px; span {
padding: 15px;
}
span:nth-child(1) {
flex: 9;
overflow-x: scroll;
}
span:nth-child(2) {
background: $darkgrey;
color: $black;
cursor: pointer;
transition: all 0.25s;
&:hover {
background: $darkestgrey;
}
}
} }
} }
} }

21
app/components/Wallet/Wallet.js

@ -13,7 +13,8 @@ class Wallet extends Component {
super(props) super(props)
this.state = { this.state = {
modalOpen: false modalOpen: false,
qrCodeType: 1
} }
} }
@ -25,19 +26,29 @@ class Wallet extends Component {
newAddress newAddress
} = this.props } = this.props
const { modalOpen } = this.state const { modalOpen, qrCodeType } = this.state
const changeQrCode = () => {
const qrCodeType = this.state.qrCodeType === 1 ? 2 : 1
this.setState({ qrCodeType })
}
return ( return (
<div className={styles.wallet}> <div className={styles.wallet}>
{ {
(modalOpen && (
modalOpen &&
<ReceiveModal <ReceiveModal
isOpen={modalOpen} isOpen={modalOpen}
hideActivityModal={() => this.setState({ modalOpen: false })} hideActivityModal={() => this.setState({ modalOpen: false })}
pubkey={info.data.identity_pubkey} pubkey={info.data.identity_pubkey}
address={address} address={address}
newAddress={newAddress} newAddress={newAddress}
/>) qrCodeType={qrCodeType}
changeQrCode={changeQrCode}
/>
)
} }
<div className={styles.content}> <div className={styles.content}>
<div className={styles.left}> <div className={styles.left}>
@ -52,7 +63,7 @@ class Wallet extends Component {
</div> </div>
<div className={styles.right}> <div className={styles.right}>
<div className={styles.rightContent}> <div className={styles.rightContent}>
<div onClick={() => this.setState({ modalOpen: true })}> <div className={'buttonPrimary'} onClick={() => this.setState({ modalOpen: true })}>
<FaQrcode /> <FaQrcode />
Address Address
</div> </div>

4
app/components/Wallet/Wallet.scss

@ -58,10 +58,10 @@
height: calc(100% - 50px); height: calc(100% - 50px);
div { div {
font-size: 20px; padding: 7px 20px;
padding: 10px 25px;
background: $main; background: $main;
transition: background 0.25s; transition: background 0.25s;
color: $black;
&:hover { &:hover {
background: darken($main, 10%); background: darken($main, 10%);

14
app/containers/Root.js

@ -3,9 +3,10 @@ import React from 'react'
import { Provider, connect } from 'react-redux' import { Provider, connect } from 'react-redux'
import { ConnectedRouter } from 'react-router-redux' import { ConnectedRouter } from 'react-router-redux'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import { fetchBlockHeight, lndSelectors } from 'reducers/lnd'
import LoadingBolt from 'components/LoadingBolt' import LoadingBolt from '../components/LoadingBolt'
import LndSyncing from 'components/LndSyncing' import LndSyncing from '../components/LndSyncing'
import { fetchBlockHeight, lndSelectors } from '../reducers/lnd'
import Routes from '../routes' import Routes from '../routes'
const mapDispatchToProps = { const mapDispatchToProps = {
@ -18,11 +19,6 @@ const mapStateToProps = state => ({
syncPercentage: lndSelectors.syncPercentage(state) syncPercentage: lndSelectors.syncPercentage(state)
}) })
type RootType = {
store: {},
history: {}
};
const Root = ({ const Root = ({
store, store,
history, history,
@ -40,7 +36,7 @@ const Root = ({
/> />
) )
} }
// Don't launch the app without gRPC connection // Don't launch the app without gRPC connection
if (!lnd.grpcStarted) { return <LoadingBolt /> } if (!lnd.grpcStarted) { return <LoadingBolt /> }

22
app/index.js

@ -1,27 +1,27 @@
import React from 'react'; import React from 'react'
import { render } from 'react-dom'; import { render } from 'react-dom'
import { AppContainer } from 'react-hot-loader'; import { AppContainer } from 'react-hot-loader'
import Root from './containers/Root'; import Root from './containers/Root'
import { configureStore, history } from './store/configureStore'; import { configureStore, history } from './store/configureStore'
import './app.global.scss'; import './app.global.scss'
const store = configureStore(); const store = configureStore()
render( render(
<AppContainer> <AppContainer>
<Root store={store} history={history} /> <Root store={store} history={history} />
</AppContainer>, </AppContainer>,
document.getElementById('root') document.getElementById('root')
); )
if (module.hot) { if (module.hot) {
module.hot.accept('./containers/Root', () => { module.hot.accept('./containers/Root', () => {
const NextRoot = require('./containers/Root'); // eslint-disable-line global-require const NextRoot = require('./containers/Root') // eslint-disable-line global-require
render( render(
<AppContainer> <AppContainer>
<NextRoot store={store} history={history} /> <NextRoot store={store} history={history} />
</AppContainer>, </AppContainer>,
document.getElementById('root') document.getElementById('root')
); )
}); })
} }

2
app/lnd/config/index.js

@ -8,7 +8,7 @@ import { join } from 'path'
let loc let loc
switch (platform()) { switch (platform()) {
case 'darwin': case 'darwin':
loc = 'Library/Application\ Support/Lnd/tls.cert' loc = 'Library/Application Support/Lnd/tls.cert'
break break
case 'linux': case 'linux':
loc = '.lnd/tls.cert' loc = '.lnd/tls.cert'

2
app/lnd/lib/lightning.js

@ -6,7 +6,7 @@ import config from '../config'
module.exports = (rpcpath, host) => { module.exports = (rpcpath, host) => {
const lndCert = fs.readFileSync(config.cert) const lndCert = fs.readFileSync(config.cert)
const credentials = grpc.credentials.createSsl(lndCert) const credentials = grpc.credentials.createSsl(lndCert)
const rpc = grpc.load(path.join(__dirname, 'rpc.proto')) const rpc = grpc.load(path.join(__dirname, 'rpc.proto'))
return new rpc.lnrpc.Lightning(host, credentials) return new rpc.lnrpc.Lightning(host, credentials)

2
app/lnd/methods/paymentsController.js

@ -12,7 +12,7 @@ export function sendPaymentSync(lnd, { paymentRequest }) {
return return
} }
if (!data.payment_route) { reject({ error: data.payment_error }) } if (!data || !data.payment_route) { reject({ error: data.payment_error }) }
resolve(data) resolve(data)
}) })

2
app/lnd/subscribe/transactions.js

@ -9,5 +9,5 @@ export default function subscribeToTransactions(mainWindow, lnd) {
}) })
call.on('end', () => console.log('end')) call.on('end', () => console.log('end'))
call.on('error', error => console.log('error: ', error)) call.on('error', error => console.log('error: ', error))
call.on('status', status => console.log('status: ', status)) call.on('status', status => console.log('TRANSACTION STATUS: ', status))
} }

42
app/lnd/utils/index.js

@ -0,0 +1,42 @@
import zbase32 from 'zbase32'
function convertBigEndianBufferToLong(longBuffer) {
let longValue = 0
const byteArray = Buffer.from(longBuffer).swap64()
for (let i = byteArray.length - 1; i >= 0; i -= 1) {
longValue = (longValue * 256) + byteArray[i]
}
return longValue
}
export function decodeInvoice(payreq) {
const payreqBase32 = zbase32.decode(payreq)
const bufferHexRotated = Buffer.from(payreqBase32).toString('hex')
const bufferHex = bufferHexRotated.substr(bufferHexRotated.length - 1, bufferHexRotated.length)
+ bufferHexRotated.substr(0, bufferHexRotated.length - 1)
const buffer = Buffer.from(bufferHex, 'hex')
const pubkeyBuffer = buffer.slice(0, 33)
const pubkey = pubkeyBuffer.toString('hex')
const paymentHashBuffer = buffer.slice(33, 65)
const paymentHashHex = paymentHashBuffer.toString('hex')
const valueBuffer = buffer.slice(65, 73)
const amount = convertBigEndianBufferToLong(valueBuffer)
return {
payreq,
pubkey,
amount,
r_hash: paymentHashHex
}
}
export default {
decodeInvoice
}

1
app/main.dev.js

@ -165,6 +165,7 @@ export const startLnd = () => {
'--bitcoin.active', '--bitcoin.active',
'--bitcoin.testnet', '--bitcoin.testnet',
'--neutrino.active', '--neutrino.active',
'--neutrino.connect=btcd0.lightning.computer:18333',
'--neutrino.connect=faucet.lightning.community:18333', '--neutrino.connect=faucet.lightning.community:18333',
'--autopilot.active', '--autopilot.active',
'--debuglevel=debug', '--debuglevel=debug',

2
app/package.json

@ -15,7 +15,7 @@
}, },
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"grpc": "^1.6.6", "grpc": "^1.7.3",
"ps-node": "^0.1.6", "ps-node": "^0.1.6",
"react-icons": "^2.2.5" "react-icons": "^2.2.5"
} }

2
app/reducers/address.js

@ -5,7 +5,7 @@ import { ipcRenderer } from 'electron'
export const GET_ADDRESS = 'GET_ADDRESS' export const GET_ADDRESS = 'GET_ADDRESS'
export const RECEIVE_ADDRESS = 'RECEIVE_ADDRESS' export const RECEIVE_ADDRESS = 'RECEIVE_ADDRESS'
// LND expects types to be sent as int, so this object will allow mapping from string to int // LND expects types to be sent as int, so this object will allow mapping from string to int
const addressTypes = { const addressTypes = {
p2wkh: 0, p2wkh: 0,
np2wkh: 1, np2wkh: 1,

19
app/reducers/channels.js

@ -165,27 +165,32 @@ export const closeChannel = ({ channel_point }) => (dispatch) => {
// TODO: Decide how to handle streamed updates for closing channels // TODO: Decide how to handle streamed updates for closing channels
// Receive IPC event for closeChannel // Receive IPC event for closeChannel
export const closeChannelSuccessful = () => (dispatch) => { export const closeChannelSuccessful = (event, data) => (dispatch) => {
console.log('PUSH CLOSE CHANNEL SUCCESSFUL: ', data)
dispatch(fetchChannels()) dispatch(fetchChannels())
} }
// Receive IPC event for updated closing channel // Receive IPC event for updated closing channel
export const pushclosechannelupdated = () => (dispatch) => { export const pushclosechannelupdated = (event, data) => (dispatch) => {
console.log('PUSH CLOSE CHANNEL UPDATED: ', data)
dispatch(fetchChannels()) dispatch(fetchChannels())
} }
// Receive IPC event for closing channel end // Receive IPC event for closing channel end
export const pushclosechannelend = () => (dispatch) => { export const pushclosechannelend = (event, data) => (dispatch) => {
console.log('PUSH CLOSE CHANNEL END: ', data)
dispatch(fetchChannels()) dispatch(fetchChannels())
} }
// Receive IPC event for closing channel error // Receive IPC event for closing channel error
export const pushclosechannelerror = () => (dispatch) => { export const pushclosechannelerror = (event, data) => (dispatch) => {
console.log('PUSH CLOSE CHANNEL END: ', data)
dispatch(fetchChannels()) dispatch(fetchChannels())
} }
// Receive IPC event for closing channel status // Receive IPC event for closing channel status
export const pushclosechannelstatus = () => (dispatch) => { export const pushclosechannelstatus = (event, data) => (dispatch) => {
console.log('PUSH CLOSE CHANNEL STATUS: ', data)
dispatch(fetchChannels()) dispatch(fetchChannels())
} }
@ -201,13 +206,13 @@ export const channelGraphData = (event, data) => (dispatch, getState) => {
// dispatch(fetchDescribeNetwork()) // dispatch(fetchDescribeNetwork())
// loop through the channel updates // loop through the channel updates
for (let i = 0; i < channel_updates.length; i++) { for (let i = 0; i < channel_updates.length; i += 1) {
const channel_update = channel_updates[i] const channel_update = channel_updates[i]
const { advertising_node, connecting_node } = channel_update const { advertising_node, connecting_node } = channel_update
// if our node is involved in this update we wanna show a notification // if our node is involved in this update we wanna show a notification
if (info.data.identity_pubkey === advertising_node || info.data.identity_pubkey === connecting_node) { if (info.data.identity_pubkey === advertising_node || info.data.identity_pubkey === connecting_node) {
// this channel has to do with the user, lets fetch a new channel list for them // this channel has to do with the user, lets fetch a new channel list for them
// TODO: full fetch is probably not necessary // TODO: full fetch is probably not necessary
dispatch(fetchChannels()) dispatch(fetchChannels())

5
app/reducers/info.js

@ -1,7 +1,6 @@
import { createSelector } from 'reselect' import { createSelector } from 'reselect'
import { ipcRenderer } from 'electron' import { ipcRenderer } from 'electron'
import { fetchBalance } from './balance'
import { newAddress } from './address'
// ------------------------------------ // ------------------------------------
// Constants // Constants
// ------------------------------------ // ------------------------------------
@ -25,8 +24,6 @@ export const fetchInfo = () => async (dispatch) => {
// Receive IPC event for info // Receive IPC event for info
export const receiveInfo = (event, data) => (dispatch) => { export const receiveInfo = (event, data) => (dispatch) => {
dispatch(fetchBalance())
dispatch(newAddress('p2pkh'))
dispatch({ type: RECEIVE_INFO, data }) dispatch({ type: RECEIVE_INFO, data })
} }

4
app/reducers/lnd.js

@ -59,7 +59,7 @@ export const lndStdout = (event, line) => (dispatch) => {
trimmed = line.slice(line.indexOf('Catching up block hashes to height') + 'Catching up block hashes to height'.length).trim() trimmed = line.slice(line.indexOf('Catching up block hashes to height') + 'Catching up block hashes to height'.length).trim()
height = trimmed.match(/[-]{0,1}[\d.]*[\d]+/g)[0] height = trimmed.match(/[-]{0,1}[\d.]*[\d]+/g)[0]
} }
dispatch({ type: RECEIVE_LINE, lndBlockHeight: height }) dispatch({ type: RECEIVE_LINE, lndBlockHeight: height })
} }
@ -95,7 +95,7 @@ const ACTION_HANDLERS = {
[GET_BLOCK_HEIGHT]: state => ({ ...state, fetchingBlockHeight: true }), [GET_BLOCK_HEIGHT]: state => ({ ...state, fetchingBlockHeight: true }),
[RECEIVE_BLOCK_HEIGHT]: (state, { blockHeight }) => ({ ...state, blockHeight, fetchingBlockHeight: false }), [RECEIVE_BLOCK_HEIGHT]: (state, { blockHeight }) => ({ ...state, blockHeight, fetchingBlockHeight: false }),
[GRPC_DISCONNECTED]: state => ({ ...state, grpcStarted: false }), [GRPC_DISCONNECTED]: state => ({ ...state, grpcStarted: false }),
[GRPC_CONNECTED]: state => ({ ...state, grpcStarted: true }) [GRPC_CONNECTED]: state => ({ ...state, grpcStarted: true })
} }

6
app/reducers/network.js

@ -172,9 +172,9 @@ const ACTION_HANDLERS = {
[SET_CURRENT_ROUTE]: (state, { route }) => ({ ...state, currentRoute: route }), [SET_CURRENT_ROUTE]: (state, { route }) => ({ ...state, currentRoute: route }),
[SET_CURRENT_CHANNEL]: (state, { selectedChannel }) => ({ ...state, selectedChannel }), [SET_CURRENT_CHANNEL]: (state, { selectedChannel }) => ({ ...state, selectedChannel }),
[SET_CURRENT_TAB]: (state, { currentTab }) => ({ ...state, currentTab }), [SET_CURRENT_TAB]: (state, { currentTab }) => ({ ...state, currentTab }),
[SET_CURRENT_PEER]: (state, { currentPeer }) => ({ ...state, currentPeer }), [SET_CURRENT_PEER]: (state, { currentPeer }) => ({ ...state, currentPeer }),
[UPDATE_PAY_REQ]: (state, { pay_req }) => ({ ...state, pay_req }), [UPDATE_PAY_REQ]: (state, { pay_req }) => ({ ...state, pay_req }),
@ -280,7 +280,7 @@ const initialState = {
nodes: [], nodes: [],
edges: [], edges: [],
selectedChannel: {}, selectedChannel: {},
currentTab: 1, currentTab: 1,
currentPeer: {}, currentPeer: {},

2
app/reducers/peers.js

@ -124,7 +124,7 @@ const ACTION_HANDLERS = {
[GET_PEERS]: state => ({ ...state, peersLoading: true }), [GET_PEERS]: state => ({ ...state, peersLoading: true }),
[RECEIVE_PEERS]: (state, { peers }) => ({ ...state, peersLoading: false, peers }), [RECEIVE_PEERS]: (state, { peers }) => ({ ...state, peersLoading: false, peers }),
[UPDATE_SEARCH_QUERY]: (state, { searchQuery }) => ({ ...state, searchQuery }) [UPDATE_SEARCH_QUERY]: (state, { searchQuery }) => ({ ...state, searchQuery })
} }

49
app/routes/activity/components/components/Modal/Invoice/Invoice.js

@ -6,7 +6,7 @@ import 'moment-timezone'
import QRCode from 'qrcode.react' import QRCode from 'qrcode.react'
import { MdCheck } from 'react-icons/lib/md' import { FaCircle } from 'react-icons/lib/fa'
import CurrencyIcon from 'components/CurrencyIcon' import CurrencyIcon from 'components/CurrencyIcon'
import { btc } from 'utils' import { btc } from 'utils'
@ -16,20 +16,33 @@ import styles from './Invoice.scss'
const Invoice = ({ invoice, ticker, currentTicker }) => ( const Invoice = ({ invoice, ticker, currentTicker }) => (
<div className={styles.container}> <div className={styles.container}>
<h3>{invoice.memo}</h3> <div className={styles.settled}>
<h1> {
<CurrencyIcon currency={ticker.currency} crypto={ticker.crypto} styles={{ verticalAlign: 'top' }} /> !invoice.settled &&
<span className={styles.value}> <p>
{ <FaCircle />
ticker.currency === 'usd' ? <span>Not Paid</span>
btc.satoshisToUsd(invoice.value, currentTicker.price_usd) </p>
: }
btc.satoshisToBtc(invoice.value) </div>
} <header>
</span> <h3>{invoice.memo}</h3>
</h1> <h1>
<span className={styles.value}>
{
ticker.currency === 'usd' ?
btc.satoshisToUsd(invoice.value, currentTicker.price_usd)
:
btc.satoshisToBtc(invoice.value)
}
</span>
<i>BTC</i>
</h1>
</header>
<div className={styles.qrcode}> <div className={styles.qrcode}>
<QRCode value={invoice.payment_request} size={200} /> <QRCode value={invoice.payment_request} size={150} />
</div>
<div className={styles.input}>
<input <input
readOnly readOnly
className={styles.paymentRequest} className={styles.paymentRequest}
@ -37,14 +50,6 @@ const Invoice = ({ invoice, ticker, currentTicker }) => (
defaultValue={invoice.payment_request} defaultValue={invoice.payment_request}
/> />
</div> </div>
<div className={styles.settled}>
{
invoice.settled ?
<p><MdCheck style={{ verticalAlign: 'top' }} /> Paid</p>
:
<p>Not Paid</p>
}
</div>
<p className={styles.date}> <p className={styles.date}>
Created on Created on
<Moment format='MMM Do'>{invoice.creation_date * 1000}</Moment> <Moment format='MMM Do'>{invoice.creation_date * 1000}</Moment>

79
app/routes/activity/components/components/Modal/Invoice/Invoice.scss

@ -1,72 +1,75 @@
@import '../../../../../../variables.scss'; @import '../../../../../../variables.scss';
.container { .container {
padding: 40px; .settled {
position: absolute;
top: 0;
padding: 10px 0 10px 40px;
color: $darkestgrey;
svg {
line-height: 20px;
font-size: 10px;
vertical-align: middle;
}
span {
font-size: 12px;
margin-left: 5px;
}
}
header {
background: $lightgrey;
padding-bottom: 20px;
}
h3 { h3 {
font-size: 24px; font-size: 20px;
color: $black; color: $black;
font-weight: bold; font-weight: bold;
text-align: center; padding: 10px 40px;
margin-bottom: 10px;
} }
h1 { h1 {
text-align: center;
color: $main; color: $main;
margin: 20px 20px 60px 0; padding: 10px 40px;
svg { .value {
font-size: 30px; font-size: 30px;
vertical-align: top;
} }
span svg[data-icon='ltc'] { i {
width: 30px; margin-left: 2px;
height: 30px;
vertical-align: top; vertical-align: top;
g {
transform: scale(1.75) translate(-5px, -5px);
}
}
.value {
font-size: 60px;
} }
} }
.qrcode { .qrcode {
text-align: center; text-align: center;
margin-top: 40px;
}
.input {
padding: 10px 40px;
.paymentRequest { .paymentRequest {
text-align: center; text-align: center;
font-size: 0.5vw; font-size: 12px;
margin-top: 20px; padding: 15px;
padding: 5px;
border-radius: 5px;
background: $lightgrey; background: $lightgrey;
border: 1px solid $darkgrey; border: 1px solid transparent;
display: block; display: block;
width: 100%; width: 90%;
} margin: 20px auto 0 auto;
}
.settled {
text-align: center;
color: $main;
text-transform: uppercase;
font-size: 20px;
margin: 30px 0;
font-weight: bold;
svg {
line-height: 20px;
} }
} }
.date { .date {
text-align: center; text-align: center;
padding-bottom: 40px;
margin-top: 20px;
time { time {
margin-left: 3px; margin-left: 3px;

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

@ -6,6 +6,10 @@ import Transaction from './Transaction'
import Payment from './Payment' import Payment from './Payment'
import Invoice from './Invoice' import Invoice from './Invoice'
import { MdClose } from 'react-icons/lib/md'
import styles from './Modal.scss'
const Modal = ({ modalType, modalProps, hideActivityModal, ticker, currentTicker }) => { const Modal = ({ modalType, modalProps, hideActivityModal, ticker, currentTicker }) => {
const MODAL_COMPONENTS = { const MODAL_COMPONENTS = {
TRANSACTION: Transaction, TRANSACTION: Transaction,
@ -23,7 +27,9 @@ const Modal = ({ modalType, modalProps, hideActivityModal, ticker, currentTicker
right: '0', right: '0',
bottom: 'auto', bottom: 'auto',
width: '40%', width: '40%',
margin: '50px auto' margin: '50px auto',
borderRadius: 'none',
padding: '0'
} }
} }
@ -41,6 +47,11 @@ const Modal = ({ modalType, modalProps, hideActivityModal, ticker, currentTicker
parentSelector={() => document.body} parentSelector={() => document.body}
style={customStyles} style={customStyles}
> >
<div className={styles.closeContainer}>
<span onClick={() => hideActivityModal()}>
<MdClose />
</span>
</div>
<SpecificModal {...modalProps} ticker={ticker} currentTicker={currentTicker} /> <SpecificModal {...modalProps} ticker={ticker} currentTicker={currentTicker} />
</ReactModal> </ReactModal>
) )

13
app/routes/activity/components/components/Modal/Modal.scss

@ -0,0 +1,13 @@
@import '../../../../../variables.scss';
.closeContainer {
background: $lightgrey;
text-align: right;
padding: 10px;
span {
color: $darkestgrey;
font-size: 20px;
cursor: pointer;
}
}

33
app/routes/activity/components/components/Modal/Payment/Payment.js

@ -12,21 +12,30 @@ import styles from './Payment.scss'
const Payment = ({ payment, ticker, currentTicker }) => ( const Payment = ({ payment, ticker, currentTicker }) => (
<div className={styles.container}> <div className={styles.container}>
<h3>{payment.payment_hash}</h3> <header>
<h1> <div className={styles.title}>
<CurrencyIcon currency={ticker.currency} crypto={ticker.crypto} styles={{ verticalAlign: 'top' }} /> <h2>Sent</h2>
<span className={styles.value}> <h1>
{ <span className={styles.value}>
ticker.currency === 'usd' ? {
btc.satoshisToUsd(payment.value, currentTicker.price_usd) ticker.currency === 'usd' ?
: btc.satoshisToUsd(payment.value, currentTicker.price_usd)
btc.satoshisToBtc(payment.value) :
} btc.satoshisToBtc(payment.value)
</span> }
</h1> </span>
<i>
BTC
</i>
</h1>
</div>
<h3>{payment.payment_hash}</h3>
</header>
<dl> <dl>
<dt>Fee</dt> <dt>Fee</dt>
<dd>{payment.fee}</dd> <dd>{payment.fee}</dd>
<dt>Hops</dt>
<dd>{payment.path.length}</dd>
<dt>Date</dt> <dt>Date</dt>
<dd> <dd>
<Moment format='MMM Do'>{payment.creation_date * 1000}</Moment> <Moment format='MMM Do'>{payment.creation_date * 1000}</Moment>

48
app/routes/activity/components/components/Modal/Payment/Payment.scss

@ -1,38 +1,44 @@
@import '../../../../../../variables.scss'; @import '../../../../../../variables.scss';
.container { .container {
padding: 40px; header {
padding: 5px 40px 20px 40px;
background: $lightgrey;
.title {
display: flex;
flex-direction: row;
margin-bottom: 30px;
h2 {
text-transform: uppercase;
font-size: 24px;
margin-right: 10px;
}
}
}
h1 { h1 {
text-align: center;
color: $main; color: $main;
margin: 60px 30px 60px 0;
svg { .value {
font-size: 30px; font-size: 24px;
vertical-align: top;
} }
span svg[data-icon='ltc'] { i {
width: 30px; margin-left: 2px;
height: 30px;
vertical-align: top; vertical-align: top;
g {
transform: scale(1.75) translate(-5px, -5px);
}
}
.value {
font-size: 80px;
} }
} }
h3 { h3 {
font-size: 14px; font-size: 14px;
text-align: center; text-align: center;
color: $black; color: $darkestgrey;
font-weight: bold; }
dl {
padding: 40px 40px 40px 40px;
} }
dt { dt {
@ -48,8 +54,8 @@
dd { dd {
text-align: right; text-align: right;
font-weight: 400; font-weight: 400;
padding: 19px 0; padding: 30px 0 10px 0;
margin-left: 0; margin-left: 0;
border-top: 1px solid $darkgrey; border-bottom: 1px solid $darkgrey;
} }
} }

54
app/routes/activity/components/components/Modal/Transaction/Transaction.js

@ -1,3 +1,4 @@
import { shell } from 'electron'
import React from 'react' import React from 'react'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
@ -12,31 +13,42 @@ import styles from './Transaction.scss'
const Transaction = ({ transaction, ticker, currentTicker }) => ( const Transaction = ({ transaction, ticker, currentTicker }) => (
<div className={styles.container}> <div className={styles.container}>
<h2> <header>
{ <div className={styles.title}>
transaction.amount < 0 ? <h2>
'Sent' {
: transaction.amount < 0 ?
'Received' 'Sent'
} :
</h2> 'Received'
<h3>{transaction.tx_hash}</h3> }
<h1> </h2>
<CurrencyIcon currency={ticker.currency} crypto={ticker.crypto} styles={{ verticalAlign: 'top' }} /> <h1>
<span className={styles.value}> <span className={styles.value}>
{ {
ticker.currency === 'usd' ? ticker.currency === 'usd' ?
btc.satoshisToUsd(transaction.amount, currentTicker.price_usd) btc.satoshisToUsd(transaction.amount, currentTicker.price_usd)
: :
btc.satoshisToBtc(transaction.amount) btc.satoshisToBtc(transaction.amount)
} }
</span> </span>
</h1> <i>BTC</i>
</h1>
</div>
<h3 onClick={() => shell.openExternal(`https://testnet.smartbit.com.au/tx/${transaction.tx_hash}`)}>{transaction.tx_hash}</h3>
</header>
<dl> <dl>
<dt>Confirmations</dt> <dt>Confirmations</dt>
<dd>{transaction.num_confirmations}</dd> <dd>{transaction.num_confirmations}</dd>
<dt>Fee</dt> <dt>Fee</dt>
<dd>{transaction.total_fees}</dd> <dd>
{
ticker.currency === 'usd' ?
btc.satoshisToUsd(transaction.total_fees)
:
btc.satoshisToBtc(transaction.total_fees)
}
</dd>
<dt>Date</dt> <dt>Date</dt>
<dd> <dd>
<Moment format='MMM Do'>{transaction.time_stamp * 1000}</Moment> <Moment format='MMM Do'>{transaction.time_stamp * 1000}</Moment>

53
app/routes/activity/components/components/Modal/Transaction/Transaction.scss

@ -1,48 +1,57 @@
@import '../../../../../../variables.scss'; @import '../../../../../../variables.scss';
.container { .container {
padding: 40px; header {
padding: 5px 40px 20px 40px;
background: $lightgrey;
.title {
display: flex;
flex-direction: row;
h2 {
text-transform: uppercase;
}
}
}
h1 { h1 {
text-align: center; text-align: center;
color: $main; color: $main;
margin: 60px 30px 60px 0;
svg { .value {
font-size: 30px; font-size: 24px;
vertical-align: top;
} }
span svg[data-icon='ltc'] { i {
width: 30px; margin-left: 2px;
height: 30px;
vertical-align: top; vertical-align: top;
g {
transform: scale(1.75) translate(-5px, -5px);
}
}
.value {
font-size: 75px;
} }
} }
h3 { h3 {
font-size: 14px; font-size: 14px;
text-align: center; text-align: center;
color: $black; color: $darkestgrey;
font-weight: bold; cursor: pointer;
&:hover {
text-decoration: underline;
}
} }
h2 { h2 {
text-align: center; text-align: center;
margin-right: 10px;
margin-bottom: 30px; margin-bottom: 30px;
text-transform: uppercase; text-transform: uppercase;
letter-spacing: 1.5px;
font-size: 24px; font-size: 24px;
} }
dl {
padding: 40px 40px 40px 40px;
}
dt { dt {
text-align: left; text-align: left;
float: left; float: left;
@ -56,8 +65,8 @@
dd { dd {
text-align: right; text-align: right;
font-weight: 400; font-weight: 400;
padding: 19px 0; padding: 30px 0 10px 0;
margin-left: 0; margin-left: 0;
border-top: 1px solid $darkgrey; border-bottom: 1px solid $darkgrey;
} }
} }

2
app/routes/app/components/App.js

@ -13,7 +13,7 @@ class App extends Component {
fetchTicker() fetchTicker()
fetchInfo() fetchInfo()
newAddress('p2pkh') newAddress('np2wkh')
} }
render() { render() {

10
app/routes/channels/components/Channels.js

@ -22,7 +22,7 @@ class Channels extends Component {
componentWillMount() { componentWillMount() {
const { fetchChannels, fetchPeers } = this.props const { fetchChannels, fetchPeers } = this.props
fetchChannels() fetchChannels()
fetchPeers() fetchPeers()
} }
@ -64,7 +64,7 @@ class Channels extends Component {
fetchChannels() fetchChannels()
// wait for the svg to appear as child // wait for the svg to appear as child
const svgTimeout = setTimeout(() => { const svgTimeout = setTimeout(() => {
if (icon[0].tagName === 'svg') { if (icon[0].tagName === 'svg') {
// spin icon for 1 sec // spin icon for 1 sec
icon[0].style.animation = 'spin 1000ms linear 1' icon[0].style.animation = 'spin 1000ms linear 1'
@ -73,7 +73,7 @@ class Channels extends Component {
}, 1) }, 1)
// clear animation after the second so we can reuse it // clear animation after the second so we can reuse it
const refreshTimeout = setTimeout(() => { const refreshTimeout = setTimeout(() => {
icon[0].style.animation = '' icon[0].style.animation = ''
this.setState({ refreshing: false }) this.setState({ refreshing: false })
clearTimeout(refreshTimeout) clearTimeout(refreshTimeout)
@ -96,7 +96,7 @@ class Channels extends Component {
</div> </div>
</div> </div>
</header> </header>
<div className={styles.search}> <div className={styles.search}>
<label className={`${styles.label} ${styles.input}`} htmlFor='channelSearch'> <label className={`${styles.label} ${styles.input}`} htmlFor='channelSearch'>
<MdSearch /> <MdSearch />
@ -187,7 +187,7 @@ Channels.propTypes = {
channels: PropTypes.object.isRequired, channels: PropTypes.object.isRequired,
currentChannels: PropTypes.array.isRequired, currentChannels: PropTypes.array.isRequired,
nonActiveFilters: PropTypes.array.isRequired, nonActiveFilters: PropTypes.array.isRequired,
updateChannelSearchQuery: PropTypes.func.isRequired, updateChannelSearchQuery: PropTypes.func.isRequired,
setCurrentChannel: PropTypes.func.isRequired, setCurrentChannel: PropTypes.func.isRequired,
openChannelForm: PropTypes.func.isRequired, openChannelForm: PropTypes.func.isRequired,

2
app/routes/peers/components/Peers.js

@ -24,7 +24,7 @@ class Peers extends Component {
} }
render() { render() {
const { const {
fetchPeers, fetchPeers,
peerFormProps, peerFormProps,
setPeerForm, setPeerForm,

34
app/store/configureStore.dev.js

@ -6,31 +6,31 @@ import { createLogger } from 'redux-logger'
import rootReducer from '../reducers' import rootReducer from '../reducers'
import ipc from '../reducers/ipc' import ipc from '../reducers/ipc'
const history = createHashHistory(); const history = createHashHistory()
const configureStore = (initialState?: counterStateType) => { const configureStore = (initialState?: counterStateType) => {
// Redux Configuration // Redux Configuration
const middleware = []; const middleware = []
const enhancers = []; const enhancers = []
// Thunk Middleware // Thunk Middleware
middleware.push(thunk); middleware.push(thunk)
// Logging Middleware // Logging Middleware
const logger = createLogger({ const logger = createLogger({
level: 'info', level: 'info',
collapsed: true collapsed: true
}); })
middleware.push(logger); middleware.push(logger)
// Router Middleware // Router Middleware
const router = routerMiddleware(history); const router = routerMiddleware(history)
middleware.push(router); middleware.push(router)
// Redux DevTools Configuration // Redux DevTools Configuration
const actionCreators = { const actionCreators = {
...routerActions ...routerActions
}; }
// If Redux DevTools Extension is installed use it, otherwise use Redux compose // If Redux DevTools Extension is installed use it, otherwise use Redux compose
/* eslint-disable no-underscore-dangle */ /* eslint-disable no-underscore-dangle */
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__
@ -38,23 +38,23 @@ const configureStore = (initialState?: counterStateType) => {
// Options: http://zalmoxisus.github.io/redux-devtools-extension/API/Arguments.html // Options: http://zalmoxisus.github.io/redux-devtools-extension/API/Arguments.html
actionCreators actionCreators
}) })
: compose; : compose
/* eslint-enable no-underscore-dangle */ /* eslint-enable no-underscore-dangle */
// Apply Middleware & Compose Enhancers // Apply Middleware & Compose Enhancers
enhancers.push(applyMiddleware(...middleware, ipc)); enhancers.push(applyMiddleware(...middleware, ipc))
const enhancer = composeEnhancers(...enhancers); const enhancer = composeEnhancers(...enhancers)
// Create Store // Create Store
const store = createStore(rootReducer, initialState, enhancer); const store = createStore(rootReducer, initialState, enhancer)
if (module.hot) { if (module.hot) {
module.hot.accept('../reducers', () => module.hot.accept('../reducers', () =>
store.replaceReducer(require('../reducers')) // eslint-disable-line global-require store.replaceReducer(require('../reducers')) // eslint-disable-line global-require
); )
} }
return store; return store
}; }
export default { configureStore, history }; export default { configureStore, history }

4
app/store/configureStore.js

@ -1,6 +1,6 @@
// @flow // @flow
if (process.env.NODE_ENV === 'production') { if (process.env.NODE_ENV === 'production') {
module.exports = require('./configureStore.prod'); // eslint-disable-line global-require module.exports = require('./configureStore.prod') // eslint-disable-line global-require
} else { } else {
module.exports = require('./configureStore.dev'); // eslint-disable-line global-require module.exports = require('./configureStore.dev') // eslint-disable-line global-require
} }

35
app/yarn.lock

@ -190,6 +190,10 @@ delegates@^1.0.0:
version "1.0.0" version "1.0.0"
resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a"
detect-libc@^1.0.2:
version "1.0.3"
resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b"
ecc-jsbn@~0.1.1: ecc-jsbn@~0.1.1:
version "0.1.1" version "0.1.1"
resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz#0fc73a9ed5f0d53c38193398523ef7e543777505" resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz#0fc73a9ed5f0d53c38193398523ef7e543777505"
@ -289,15 +293,15 @@ graceful-fs@^4.1.2:
version "4.1.11" version "4.1.11"
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658"
grpc@^1.6.6: grpc@^1.7.3:
version "1.6.6" version "1.7.3"
resolved "https://registry.yarnpkg.com/grpc/-/grpc-1.6.6.tgz#2051784f6bd6134681fa2c4b5e75dc82c6c23ffa" resolved "https://registry.yarnpkg.com/grpc/-/grpc-1.7.3.tgz#c9d034324e2ec8a06cfaa577a044a116f96c8c90"
dependencies: dependencies:
arguejs "^0.2.3" arguejs "^0.2.3"
lodash "^4.17.4" lodash "^4.15.0"
nan "^2.7.0" nan "^2.0.0"
node-pre-gyp "^0.6.38" node-pre-gyp "^0.6.39"
protobufjs "^5.0.2" protobufjs "^5.0.0"
har-schema@^1.0.5: har-schema@^1.0.5:
version "1.0.5" version "1.0.5"
@ -428,7 +432,7 @@ lcid@^1.0.0:
dependencies: dependencies:
invert-kv "^1.0.0" invert-kv "^1.0.0"
lodash@^4.17.4: lodash@^4.15.0:
version "4.17.4" version "4.17.4"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae"
@ -476,9 +480,9 @@ ms@2.0.0:
version "2.0.0" version "2.0.0"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
nan@^2.7.0: nan@^2.0.0:
version "2.7.0" version "2.8.0"
resolved "https://registry.yarnpkg.com/nan/-/nan-2.7.0.tgz#d95bf721ec877e08db276ed3fc6eb78f9083ad46" resolved "https://registry.yarnpkg.com/nan/-/nan-2.8.0.tgz#ed715f3fe9de02b57a5e6252d90a96675e1f085a"
node-fetch@^1.0.1: node-fetch@^1.0.1:
version "1.7.2" version "1.7.2"
@ -487,10 +491,11 @@ node-fetch@^1.0.1:
encoding "^0.1.11" encoding "^0.1.11"
is-stream "^1.0.1" is-stream "^1.0.1"
node-pre-gyp@^0.6.38: node-pre-gyp@^0.6.39:
version "0.6.38" version "0.6.39"
resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.6.38.tgz#e92a20f83416415bb4086f6d1fb78b3da73d113d" resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.6.39.tgz#c00e96860b23c0e1420ac7befc5044e1d78d8649"
dependencies: dependencies:
detect-libc "^1.0.2"
hawk "3.1.3" hawk "3.1.3"
mkdirp "^0.5.1" mkdirp "^0.5.1"
nopt "^4.0.1" nopt "^4.0.1"
@ -585,7 +590,7 @@ prop-types@15.5.8:
dependencies: dependencies:
fbjs "^0.8.9" fbjs "^0.8.9"
protobufjs@^5.0.2: protobufjs@^5.0.0:
version "5.0.2" version "5.0.2"
resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-5.0.2.tgz#59748d7dcf03d2db22c13da9feb024e16ab80c91" resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-5.0.2.tgz#59748d7dcf03d2db22c13da9feb024e16ab80c91"
dependencies: dependencies:

2
internals/mocks/fileMock.js

@ -1 +1 @@
export default 'test-file-stub'; export default 'test-file-stub'

16
internals/scripts/CheckBuiltsExist.js

@ -1,24 +1,24 @@
// @flow // @flow
// Check if the renderer and main bundles are built // Check if the renderer and main bundles are built
import path from 'path'; import path from 'path'
import chalk from 'chalk'; import chalk from 'chalk'
import fs from 'fs'; import fs from 'fs'
function CheckBuildsExist() { function CheckBuildsExist() {
const mainPath = path.join(__dirname, '..', '..', 'app', 'main.prod.js'); const mainPath = path.join(__dirname, '..', '..', 'app', 'main.prod.js')
const rendererPath = path.join(__dirname, '..', '..', 'app', 'dist', 'renderer.prod.js'); const rendererPath = path.join(__dirname, '..', '..', 'app', 'dist', 'renderer.prod.js')
if (!fs.existsSync(mainPath)) { if (!fs.existsSync(mainPath)) {
throw new Error(chalk.whiteBright.bgRed.bold( throw new Error(chalk.whiteBright.bgRed.bold(
'The main process is not built yet. Build it by running "npm run build-main"' 'The main process is not built yet. Build it by running "npm run build-main"'
)); ))
} }
if (!fs.existsSync(rendererPath)) { if (!fs.existsSync(rendererPath)) {
throw new Error(chalk.whiteBright.bgRed.bold( throw new Error(chalk.whiteBright.bgRed.bold(
'The renderer process is not built yet. Build it by running "npm run build-renderer"' 'The renderer process is not built yet. Build it by running "npm run build-renderer"'
)); ))
} }
} }
CheckBuildsExist(); CheckBuildsExist()

8
internals/scripts/CheckNodeEnv.js

@ -1,17 +1,17 @@
// @flow // @flow
import chalk from 'chalk'; import chalk from 'chalk'
export default function CheckNodeEnv(expectedEnv: string) { export default function CheckNodeEnv(expectedEnv: string) {
if (!expectedEnv) { if (!expectedEnv) {
throw new Error('"expectedEnv" not set'); throw new Error('"expectedEnv" not set')
} }
if (process.env.NODE_ENV !== expectedEnv) { if (process.env.NODE_ENV !== expectedEnv) {
/* eslint-disable */ /* eslint-disable */
console.log(chalk.whiteBright.bgRed.bold( console.log(chalk.whiteBright.bgRed.bold(
`"process.env.NODE_ENV" must be "${expectedEnv}" to use this webpack config` `"process.env.NODE_ENV" must be "${expectedEnv}" to use this webpack config`
)); ))
/* eslint-enable */ /* eslint-enable */
process.exit(2); process.exit(2)
} }
} }

2
package.json

@ -143,7 +143,7 @@
"css-loader": "^0.28.3", "css-loader": "^0.28.3",
"electron": "^1.6.10", "electron": "^1.6.10",
"electron-builder": "^19.8.0", "electron-builder": "^19.8.0",
"electron-devtools-installer": "^2.2.0", "electron-devtools-installer": "^2.2.1",
"enzyme": "^2.9.1", "enzyme": "^2.9.1",
"enzyme-to-json": "^1.5.1", "enzyme-to-json": "^1.5.1",
"eslint": "^4.4.1", "eslint": "^4.4.1",

BIN
resources/bin/darwin/lnd

Binary file not shown.

3
test/components/Nav.spec.js

@ -21,9 +21,8 @@ describe('default elements', () => {
it('should render nav links', () => { it('should render nav links', () => {
expect(el.find(NavLink).at(0).props().to).toBe('/') expect(el.find(NavLink).at(0).props().to).toBe('/')
expect(el.find(NavLink).at(1).props().to).toBe('/wallet') expect(el.find(NavLink).at(1).props().to).toBe('/peers')
expect(el.find(NavLink).at(2).props().to).toBe('/channels') expect(el.find(NavLink).at(2).props().to).toBe('/channels')
expect(el.find(NavLink).at(3).props().to).toBe('/settings')
}) })
it('should render buttons', () => { it('should render buttons', () => {
expect(el.find('.button').at(0).text()).toContain('Pay') expect(el.find('.button').at(0).text()).toContain('Pay')

6
test/example.js

@ -1,5 +1,5 @@
describe('description', () => { describe('description', () => {
it('should have description', () => { it('should have description', () => {
expect(1 + 2).toBe(3); expect(1 + 2).toBe(3)
}); })
}); })

11
test/reducers/__snapshots__/peers.spec.js.snap

@ -12,6 +12,7 @@ Object {
}, },
"peers": Array [], "peers": Array [],
"peersLoading": false, "peersLoading": false,
"searchQuery": "",
} }
`; `;
@ -27,6 +28,7 @@ Object {
}, },
"peers": Array [], "peers": Array [],
"peersLoading": false, "peersLoading": false,
"searchQuery": "",
} }
`; `;
@ -44,6 +46,7 @@ Object {
"foo", "foo",
], ],
"peersLoading": false, "peersLoading": false,
"searchQuery": "",
} }
`; `;
@ -59,6 +62,7 @@ Object {
}, },
"peers": Array [], "peers": Array [],
"peersLoading": false, "peersLoading": false,
"searchQuery": "",
} }
`; `;
@ -74,6 +78,7 @@ Object {
}, },
"peers": Array [], "peers": Array [],
"peersLoading": false, "peersLoading": false,
"searchQuery": "",
} }
`; `;
@ -89,6 +94,7 @@ Object {
}, },
"peers": Array [], "peers": Array [],
"peersLoading": false, "peersLoading": false,
"searchQuery": "",
} }
`; `;
@ -104,6 +110,7 @@ Object {
}, },
"peers": Array [], "peers": Array [],
"peersLoading": true, "peersLoading": true,
"searchQuery": "",
} }
`; `;
@ -119,6 +126,7 @@ Object {
}, },
"peers": "foo", "peers": "foo",
"peersLoading": false, "peersLoading": false,
"searchQuery": "",
} }
`; `;
@ -134,6 +142,7 @@ Object {
}, },
"peers": Array [], "peers": Array [],
"peersLoading": false, "peersLoading": false,
"searchQuery": "",
} }
`; `;
@ -152,6 +161,7 @@ Object {
}, },
"peers": Array [], "peers": Array [],
"peersLoading": false, "peersLoading": false,
"searchQuery": "",
} }
`; `;
@ -167,5 +177,6 @@ Object {
}, },
"peers": Array [], "peers": Array [],
"peersLoading": false, "peersLoading": false,
"searchQuery": "",
} }
`; `;

12
test/runTests.js

@ -1,11 +1,11 @@
const spawn = require('cross-spawn'); const spawn = require('cross-spawn')
const path = require('path'); const path = require('path')
const s = `\\${path.sep}`; const s = `\\${path.sep}`
const pattern = process.argv[2] === 'e2e' const pattern = process.argv[2] === 'e2e'
? `test${s}e2e${s}.+\\.spec\\.js` ? `test${s}e2e${s}.+\\.spec\\.js`
: `test${s}(?!e2e${s})[^${s}]+${s}.+\\.spec\\.js$`; : `test${s}(?!e2e${s})[^${s}]+${s}.+\\.spec\\.js$`
const result = spawn.sync(path.normalize('./node_modules/.bin/jest'), [pattern], { stdio: 'inherit' }); const result = spawn.sync(path.normalize('./node_modules/.bin/jest'), [pattern], { stdio: 'inherit' })
process.exit(result.status); process.exit(result.status)

6
webpack.config.base.js

@ -2,9 +2,9 @@
* Base webpack config used across other specific configs * Base webpack config used across other specific configs
*/ */
import path from 'path'; import path from 'path'
import webpack from 'webpack'; import webpack from 'webpack'
import { dependencies as externals } from './app/package.json'; import { dependencies as externals } from './app/package.json'
export default { export default {
externals: Object.keys(externals || {}), externals: Object.keys(externals || {}),

4
webpack.config.eslint.js

@ -1,3 +1,3 @@
require('babel-register'); require('babel-register')
module.exports = require('./webpack.config.renderer.dev'); module.exports = require('./webpack.config.renderer.dev')

16
webpack.config.main.prod.js

@ -2,14 +2,14 @@
* Webpack config for production electron main process * Webpack config for production electron main process
*/ */
import webpack from 'webpack'; import webpack from 'webpack'
import merge from 'webpack-merge'; import merge from 'webpack-merge'
import BabiliPlugin from 'babili-webpack-plugin'; import BabiliPlugin from 'babili-webpack-plugin'
import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer'; import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer'
import baseConfig from './webpack.config.base'; import baseConfig from './webpack.config.base'
import CheckNodeEnv from './internals/scripts/CheckNodeEnv'; import CheckNodeEnv from './internals/scripts/CheckNodeEnv'
CheckNodeEnv('production'); CheckNodeEnv('production')
export default merge.smart(baseConfig, { export default merge.smart(baseConfig, {
devtool: 'source-map', devtool: 'source-map',
@ -59,4 +59,4 @@ export default merge.smart(baseConfig, {
__dirname: false, __dirname: false,
__filename: false __filename: false
} }
}); })

18
webpack.config.renderer.dev.dll.js

@ -2,16 +2,16 @@
* Builds the DLL for development electron renderer process * Builds the DLL for development electron renderer process
*/ */
import webpack from 'webpack'; import webpack from 'webpack'
import path from 'path'; import path from 'path'
import merge from 'webpack-merge'; import merge from 'webpack-merge'
import baseConfig from './webpack.config.base'; import baseConfig from './webpack.config.base'
import { dependencies } from './package.json'; import { dependencies } from './package.json'
import CheckNodeEnv from './internals/scripts/CheckNodeEnv'; import CheckNodeEnv from './internals/scripts/CheckNodeEnv'
CheckNodeEnv('development'); CheckNodeEnv('development')
const dist = path.resolve(process.cwd(), 'dll'); const dist = path.resolve(process.cwd(), 'dll')
export default merge.smart(baseConfig, { export default merge.smart(baseConfig, {
context: process.cwd(), context: process.cwd(),
@ -205,4 +205,4 @@ export default merge.smart(baseConfig, {
} }
}) })
] ]
}); })

20
webpack.config.renderer.prod.js

@ -2,16 +2,16 @@
* Build config for electron renderer process * Build config for electron renderer process
*/ */
import path from 'path'; import path from 'path'
import webpack from 'webpack'; import webpack from 'webpack'
import ExtractTextPlugin from 'extract-text-webpack-plugin'; import ExtractTextPlugin from 'extract-text-webpack-plugin'
import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer'; import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer'
import merge from 'webpack-merge'; import merge from 'webpack-merge'
import BabiliPlugin from 'babili-webpack-plugin'; import BabiliPlugin from 'babili-webpack-plugin'
import baseConfig from './webpack.config.base'; import baseConfig from './webpack.config.base'
import CheckNodeEnv from './internals/scripts/CheckNodeEnv'; import CheckNodeEnv from './internals/scripts/CheckNodeEnv'
CheckNodeEnv('production'); CheckNodeEnv('production')
export default merge.smart(baseConfig, { export default merge.smart(baseConfig, {
devtool: 'source-map', devtool: 'source-map',
@ -165,4 +165,4 @@ export default merge.smart(baseConfig, {
openAnalyzer: process.env.OPEN_ANALYZER === 'true' openAnalyzer: process.env.OPEN_ANALYZER === 'true'
}) })
] ]
}); })

6
yarn.lock

@ -3137,9 +3137,9 @@ electron-debug@^1.2.0:
electron-is-dev "^0.1.0" electron-is-dev "^0.1.0"
electron-localshortcut "^2.0.0" electron-localshortcut "^2.0.0"
electron-devtools-installer@^2.2.0: electron-devtools-installer@^2.2.1:
version "2.2.0" version "2.2.1"
resolved "https://registry.yarnpkg.com/electron-devtools-installer/-/electron-devtools-installer-2.2.0.tgz#9813e6811afcd69ddca3cae5416db72ea7ecfb6a" resolved "https://registry.yarnpkg.com/electron-devtools-installer/-/electron-devtools-installer-2.2.1.tgz#0beb73ccbf65cbc4d09e706cebda638f839b8c55"
dependencies: dependencies:
"7zip" "0.0.6" "7zip" "0.0.6"
cross-unzip "0.0.2" cross-unzip "0.0.2"

Loading…
Cancel
Save