Browse Source

Merge branch 'master' of https://github.com/LN-Zap/zap-desktop

renovate/lint-staged-8.x
Jack Mallers 7 years ago
parent
commit
7893e6ec8b
  1. 7
      app/api/index.js
  2. 6
      app/app.global.scss
  3. 142
      app/components/Channels/Channels.js
  4. 24
      app/components/Channels/Channels.scss
  5. 30
      app/components/LndSyncing/LndSyncing.js
  6. 4
      app/components/ModalRoot/ModalRoot.js
  7. 42
      app/components/ModalRoot/WalletDetails.js
  8. 70
      app/components/ModalRoot/WalletDetails.scss
  9. 54
      app/components/Nav/Nav.js
  10. 1
      app/components/Nav/Nav.scss
  11. 73
      app/components/Peers/Peers.js
  12. 14
      app/components/Peers/Peers.scss
  13. 64
      app/components/Wallet/ReceiveModal.js
  14. 38
      app/components/Wallet/ReceiveModal.scss
  15. 71
      app/components/Wallet/Wallet.js
  16. 72
      app/components/Wallet/Wallet.scss
  17. 3
      app/components/Wallet/index.js
  18. 10
      app/keyframes.scss
  19. 4
      app/lnd/index.js
  20. 1
      app/lnd/lib/lightning.js
  21. 2
      app/lnd/subscribe/index.js
  22. 1
      app/main.dev.js
  23. 2
      app/reducers/balance.js
  24. 2
      app/reducers/ipc.js
  25. 12
      app/reducers/lnd.js
  26. 3
      app/reducers/transaction.js
  27. 2
      app/routes/activity/components/components/Modal/Modal.js
  28. 34
      app/routes/app/components/App.js
  29. 4
      app/routes/app/containers/AppContainer.js
  30. 26
      app/routes/wallet/components/Wallet.js
  31. 1
      app/variables.scss
  32. 1
      package.json
  33. 26
      yarn.lock

7
app/api/index.js

@ -15,13 +15,12 @@ export function requestTickers(ids) {
.then(axios.spread((btcTicker, ltcTicker) => ({ btcTicker: btcTicker[0], ltcTicker: ltcTicker[0] })))
}
export function requestBlockHeight(id) {
const BASE_URL = `https://testnet-api.smartbit.com.au/v1/blockchain/blocks?limit=1`
export function requestBlockHeight() {
const BASE_URL = 'https://testnet-api.smartbit.com.au/v1/blockchain/blocks?limit=1'
return axios({
method: 'get',
url: BASE_URL
})
.then(response => response.data)
.catch(error => error)
}
}

6
app/app.global.scss

@ -66,4 +66,10 @@ body {
opacity: 1;
stroke: darken($main, 10%);
}
}
@keyframes spin {
100% {
transform: rotate(360deg);
}
}

142
app/components/Channels/Channels.js

@ -1,6 +1,7 @@
import React from 'react'
import PropTypes from 'prop-types'
import { TiPlus } from 'react-icons/lib/ti'
import { FaRepeat } from 'react-icons/lib/fa'
import ChannelModal from './ChannelModal'
import ChannelForm from './ChannelForm'
import Channel from './Channel'
@ -9,6 +10,7 @@ import ClosedPendingChannel from './ClosedPendingChannel'
import styles from './Channels.scss'
const Channels = ({
fetchChannels,
ticker,
peers,
channelsLoading,
@ -22,69 +24,103 @@ const Channels = ({
closeChannel,
currentTicker,
explorerLinkBase
}) => (
<div className={styles.channels}>
<ChannelModal
isOpen={channelModalOpen}
resetChannel={setChannel}
channel={modalChannel}
explorerLinkBase={explorerLinkBase}
closeChannel={closeChannel}
/>
<ChannelForm form={channelForm} setForm={setChannelForm} ticker={ticker} peers={peers} openChannel={openChannel} currentTicker={currentTicker} />
<div className={styles.header}>
<h3>Channels</h3>
<div
className={`${styles.openChannel} hint--top`}
data-hint='Open a channel'
onClick={() => setChannelForm({ isOpen: true })}
>
<TiPlus />
}) => {
const refreshClicked = (event) => {
// store event in icon so we dont get an error when react clears it
const icon = event.currentTarget
// fetch channels
fetchChannels()
// clear animation after the second so we can reuse it
setTimeout(() => { icon.style.animation = '' }, 1000)
// spin icon for 1 sec
icon.style.animation = 'spin 1000ms linear 1'
}
return (
<div className={styles.channels}>
<ChannelModal
isOpen={channelModalOpen}
resetChannel={setChannel}
channel={modalChannel}
explorerLinkBase={explorerLinkBase}
closeChannel={closeChannel}
/>
<ChannelForm
form={channelForm}
setForm={setChannelForm}
ticker={ticker}
peers={peers}
openChannel={openChannel}
currentTicker={currentTicker}
/>
<div className={styles.header}>
<h3>Channels</h3>
<span
className={`${styles.refresh} hint--top`}
data-hint='Refresh your channels list'
>
<FaRepeat
style={{ verticalAlign: 'baseline' }}
onClick={refreshClicked}
/>
</span>
<div
className={`${styles.openChannel} hint--top`}
data-hint='Open a channel'
onClick={() => setChannelForm({ isOpen: true })}
>
<TiPlus />
</div>
</div>
</div>
<ul>
{
!channelsLoading ?
allChannels.map((channel, index) => {
if (Object.prototype.hasOwnProperty.call(channel, 'blocks_till_open')) {
<ul>
{
!channelsLoading ?
allChannels.map((channel, index) => {
if (Object.prototype.hasOwnProperty.call(channel, 'blocks_till_open')) {
return (
<OpenPendingChannel
key={index}
channel={channel}
ticker={ticker}
currentTicker={currentTicker}
explorerLinkBase={explorerLinkBase}
/>
)
} else if (Object.prototype.hasOwnProperty.call(channel, 'closing_txid')) {
return (
<ClosedPendingChannel
key={index}
channel={channel}
ticker={ticker}
currentTicker={currentTicker}
explorerLinkBase={explorerLinkBase}
/>
)
}
return (
<OpenPendingChannel
<Channel
key={index}
channel={channel}
ticker={ticker}
currentTicker={currentTicker}
explorerLinkBase={explorerLinkBase}
/>
)
} else if (Object.prototype.hasOwnProperty.call(channel, 'closing_txid')) {
return (
<ClosedPendingChannel
key={index}
channel={channel}
ticker={ticker}
setChannel={setChannel}
currentTicker={currentTicker}
explorerLinkBase={explorerLinkBase}
/>
)
}
return (
<Channel
key={channel.chan_id}
ticker={ticker}
channel={channel}
setChannel={setChannel}
currentTicker={currentTicker}
/>
)
})
:
'Loading...'
}
</ul>
</div>
)
})
:
'Loading...'
}
</ul>
</div>
)
}
Channels.propTypes = {
fetchChannels: PropTypes.func.isRequired,
ticker: PropTypes.object.isRequired,
peers: PropTypes.array.isRequired,
channelsLoading: PropTypes.bool.isRequired,

24
app/components/Channels/Channels.scss

@ -1,5 +1,15 @@
@import '../../variables.scss';
@keyframes spin {
from {
transform: rotate(0deg)
}
to {
transform: rotate(360deg);
}
}
.channels {
width: 75%;
margin: 50px auto;
@ -15,6 +25,20 @@
text-align: left;
}
.refresh {
cursor: pointer;
margin-left: 5px;
font-size: 12px;
vertical-align: top;
color: $darkestgrey;
line-height: 14px;
transition: color 0.25s;
&:hover {
color: $main;
}
}
.openChannel {
float: right;
cursor: pointer;

30
app/components/LndSyncing/LndSyncing.js

@ -1,14 +1,15 @@
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import styles from './LndSyncing.scss'
class LndSyncing extends Component {
constructor(props) {
super(props);
super(props);
this.state = {
facts: [
{
title: 'No2x',
description: 'Segwit2x is a hard fork proposal led by Barry Silbert and the NYA signers. The idea was drawn up and signed in a locked hotel room with select individuals and goes against everything that Bitcoin stands for. There is no favoritism in Bitcoin. There are no politicians. Hash power and business don\'t speak for us. Don\'t trust, verify.'
description: 'Segwit2x is a hard fork proposal led by Barry Silbert and the NYA signers. The idea was drawn up and signed in a locked hotel room with select individuals and goes against everything that Bitcoin stands for. There is no favoritism in Bitcoin. There are no politicians. Hash power and business don\'t speak for us. Don\'t trust, verify.' // eslint-disable-line
},
{
title: 'Gang',
@ -41,8 +42,7 @@ class LndSyncing extends Component {
<h3>zap</h3>
<div className={styles.loading}>
{!fetchingBlockHeight && <h4>{syncPercentage}%</h4>}
<div className={styles.spinner}>
</div>
<div className={styles.spinner} />
<h1>syncing your lightning node to the blockchain</h1>
</div>
<div className={styles.facts}>
@ -52,15 +52,13 @@ class LndSyncing extends Component {
</div>
<ul>
{
facts.map((facts, index) => {
return (
<li
className={`${styles.factButton} ${currentFact === index && styles.active}`}
key={index}
onClick={() => this.setState({ currentFact: index })}
/>
)
})
facts.map((fact, index) => (
<li
className={`${styles.factButton} ${currentFact === index && styles.active}`}
key={index}
onClick={() => this.setState({ currentFact: index })}
/>
))
}
</ul>
</div>
@ -69,4 +67,10 @@ class LndSyncing extends Component {
}
}
LndSyncing.propTypes = {
fetchBlockHeight: PropTypes.func.isRequired,
fetchingBlockHeight: PropTypes.bool.isRequired,
syncPercentage: PropTypes.number.isRequired
}
export default LndSyncing

4
app/components/ModalRoot/ModalRoot.js

@ -3,11 +3,13 @@ import PropTypes from 'prop-types'
import { MdClose } from 'react-icons/lib/md'
import SuccessfulSendCoins from './SuccessfulSendCoins'
import SuccessfulSendPayment from './SuccessfulSendPayment'
import WalletDetails from './WalletDetails'
import styles from './ModalRoot.scss'
const MODAL_COMPONENTS = {
SUCCESSFUL_SEND_COINS: SuccessfulSendCoins,
SUCCESSFUL_SEND_PAYMENT: SuccessfulSendPayment
SUCCESSFUL_SEND_PAYMENT: SuccessfulSendPayment,
WALLET_DETAILS: WalletDetails
/* other modals */
}

42
app/components/ModalRoot/WalletDetails.js

@ -0,0 +1,42 @@
import React from 'react'
import PropTypes from 'prop-types'
import QRCode from 'qrcode.react'
import styles from './WalletDetails.scss'
const WalletDetails = ({ info, address }) => (
<div className={styles.walletdetails}>
<div className={styles.inner}>
<div className={styles.left}>
<section>
<h4>Node Alias</h4>
<h1>Testing</h1>
</section>
<section>
<h4>Node Public Key</h4>
<p className={styles.copytext}>{info.data.identity_pubkey}</p>
</section>
<section>
<h4>Deposit Address</h4>
<div className={styles.qrcode}>
<QRCode value={address} />
</div>
<p className={styles.copytext}>{address}</p>
</section>
</div>
<div className={styles.right}>
<section>
<h2>
Network
</h2>
</section>
</div>
</div>
</div>
)
WalletDetails.propTypes = {
info: PropTypes.object.isRequired,
address: PropTypes.string.isRequired
}
export default WalletDetails

70
app/components/ModalRoot/WalletDetails.scss

@ -0,0 +1,70 @@
@import '../../variables.scss';
.walletdetails {
}
.inner {
width: 75%;
margin: 0 auto;
display: flex;
flex-direction: row;
}
.left, .right {
padding: 50px 0;
width: 100%;
section {
position: relative;
margin: 0 20px;
padding: 20px 0;
}
}
.left {
border-right: 1px solid $darkgrey;
section {
border-bottom: 1px solid $main;
h4 {
text-transform: uppercase;
letter-spacing: 1.5px;
font-size: 10px;
margin-bottom: 15px;
}
}
h1 {
font-family: 'Roboto';
font-weight: 300;
font-size: 24px;
}
.qrcode {
text-align: center;
margin: 20px 0;
}
.copytext {
font-family: 'Roboto';
text-align: center;
font-size: 14px;
font-weight: 200;
border-radius: 7px;
background: $lightgrey;
border: 1px solid $darkestgrey;
padding: 10px;
}
}
.right {
section {
h2 {
text-transform: uppercase;
font-family: 'Roboto';
font-weight: 300;
font-size: 24px;
}
}
}

54
app/components/Nav/Nav.js

@ -3,60 +3,14 @@ import PropTypes from 'prop-types'
import { NavLink } from 'react-router-dom'
import ReactSVG from 'react-svg'
import { MdAccountBalanceWallet } from 'react-icons/lib/md'
import { FaClockO, FaDollar } from 'react-icons/lib/fa'
import CryptoIcon from 'components/CryptoIcon'
import CurrencyIcon from 'components/CurrencyIcon'
import { btc, usd } from 'utils'
import { FaClockO } from 'react-icons/lib/fa'
import styles from './Nav.scss'
const Nav = ({ ticker, balance, setCurrency, currentTicker, openPayForm, openRequestForm }) => (
const Nav = ({ openPayForm, openRequestForm }) => (
<nav className={styles.nav}>
<ul className={styles.info}>
<li className={`${styles.currencies} ${styles.link}`}>
<span
data-hint={currentTicker ? usd.formatUsd(currentTicker.price_usd) : null}
className={`${styles.currency} ${ticker.currency === ticker.crypto ? styles.active : ''} hint--bottom`}
onClick={() => setCurrency(ticker.crypto)}
>
<CryptoIcon currency={ticker.crypto} />
</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><CurrencyIcon currency={ticker.currency} crypto={ticker.crypto} /></span>
<span>
{
ticker.currency === 'usd' ?
btc.satoshisToUsd(balance.walletBalance, currentTicker.price_usd)
:
btc.satoshisToBtc(balance.walletBalance)
}
</span>
</p>
<p data-hint='Channel balance' className='hint--bottom-left'>
<span><CurrencyIcon currency={ticker.currency} crypto={ticker.crypto} /></span>
<span>
{
ticker.currency === 'usd' ?
btc.satoshisToUsd(balance.channelBalance, currentTicker.price_usd)
:
btc.satoshisToBtc(balance.channelBalance)
}
</span>
</p>
</li>
</ul>
<div className={styles.logo}>
<ReactSVG path='../resources/zap_2.svg' />
</div>
<ul className={styles.links}>
<li>
<NavLink exact to='/' activeClassName={styles.active} className={styles.link}>
@ -83,10 +37,6 @@ const Nav = ({ ticker, balance, setCurrency, currentTicker, openPayForm, openReq
)
Nav.propTypes = {
ticker: PropTypes.object.isRequired,
balance: PropTypes.object.isRequired,
setCurrency: PropTypes.func.isRequired,
currentTicker: PropTypes.object.isRequired,
openPayForm: PropTypes.func.isRequired,
openRequestForm: PropTypes.func.isRequired
}

1
app/components/Nav/Nav.scss

@ -49,6 +49,7 @@
.logo {
text-align: center;
margin-top: 20px;
margin-bottom: 50%;
svg {

73
app/components/Peers/Peers.js

@ -1,12 +1,14 @@
import React from 'react'
import PropTypes from 'prop-types'
import { TiPlus } from 'react-icons/lib/ti'
import { FaRepeat } from 'react-icons/lib/fa'
import PeerModal from './PeerModal'
import PeerForm from './PeerForm'
import Peer from './Peer'
import styles from './Peers.scss'
const Peers = ({
fetchPeers,
peersLoading,
peers,
setPeer,
@ -16,32 +18,59 @@ const Peers = ({
setPeerForm,
connect,
disconnect
}) => (
<div className={styles.peers}>
<PeerModal isOpen={peerModalOpen} resetPeer={setPeer} peer={modalPeer} disconnect={disconnect} />
<PeerForm form={peerForm} setForm={setPeerForm} connect={connect} />
<div className={styles.header}>
<h3>Peers</h3>
<div
className={`${styles.connectPeer} hint--top`}
data-hint='Connect to a peer'
onClick={() => setPeerForm({ isOpen: true })}
>
<TiPlus />
}) => {
const refreshClicked = (event) => {
// store event in icon so we dont get an error when react clears it
const icon = event.currentTarget
// fetch peers
fetchPeers()
// clear animation after the second so we can reuse it
setTimeout(() => { icon.style.animation = '' }, 1000)
// spin icon for 1 sec
icon.style.animation = 'spin 1000ms linear 1'
}
return (
<div className={styles.peers}>
<PeerModal isOpen={peerModalOpen} resetPeer={setPeer} peer={modalPeer} disconnect={disconnect} />
<PeerForm form={peerForm} setForm={setPeerForm} connect={connect} />
<div className={styles.header}>
<h3>Peers</h3>
<span
className={`${styles.refresh} hint--top`}
data-hint='Refresh your peers list'
>
<FaRepeat
style={{ verticalAlign: 'baseline' }}
onClick={refreshClicked}
/>
</span>
<div
className={`${styles.connectPeer} hint--top`}
data-hint='Connect to a peer'
onClick={() => setPeerForm({ isOpen: true })}
>
<TiPlus />
</div>
</div>
<ul>
{
!peersLoading ?
peers.map(peer => <Peer key={peer.peer_id} peer={peer} setPeer={setPeer} />)
:
'Loading...'
}
</ul>
</div>
<ul>
{
!peersLoading ?
peers.map(peer => <Peer key={peer.peer_id} peer={peer} setPeer={setPeer} />)
:
'Loading...'
}
</ul>
</div>
)
)
}
Peers.propTypes = {
fetchPeers: PropTypes.func.isRequired,
peersLoading: PropTypes.bool.isRequired,
peers: PropTypes.array.isRequired,
setPeer: PropTypes.func.isRequired,

14
app/components/Peers/Peers.scss

@ -15,6 +15,20 @@
text-align: left;
}
.refresh {
cursor: pointer;
margin-left: 5px;
font-size: 12px;
vertical-align: top;
color: $darkestgrey;
line-height: 14px;
transition: color 0.25s;
&:hover {
color: $main;
}
}
.connectPeer {
float: right;
cursor: pointer;

64
app/components/Wallet/ReceiveModal.js

@ -0,0 +1,64 @@
import React from 'react'
import PropTypes from 'prop-types'
import ReactModal from 'react-modal'
import copy from 'copy-to-clipboard'
import QRCode from 'qrcode.react'
import { showNotification } from 'notifications'
import styles from './ReceiveModal.scss'
const ReceiveModal = ({ isOpen, hideActivityModal, pubkey, address }) => {
const customStyles = {
overlay: {
cursor: 'pointer'
},
content: {
top: 'auto',
left: '20%',
right: '0',
bottom: 'auto',
width: '40%',
margin: '50px auto'
}
}
const copyOnClick = (data) => {
copy(data)
showNotification('Noice', 'Successfully copied to clipboard')
}
return (
<ReactModal
isOpen={isOpen}
ariaHideApp
shouldCloseOnOverlayClick
contentLabel='No Overlay Click Modal'
onRequestClose={() => hideActivityModal()}
parentSelector={() => document.body}
style={customStyles}
>
<div className={styles.container}>
<section>
<h4>Node Public Key (<span onClick={() => copyOnClick(pubkey)}>Copy</span>)</h4>
<p>{pubkey}</p>
</section>
<section>
<h4>Deposit Address (<span onClick={() => copyOnClick(address)}>Copy</span>)</h4>
<p>{address}</p>
<div className={styles.qrcode}>
<QRCode value={address} />
</div>
</section>
</div>
</ReactModal>
)
}
ReceiveModal.propTypes = {
isOpen: PropTypes.bool.isRequired,
hideActivityModal: PropTypes.func.isRequired,
pubkey: PropTypes.string.isRequired,
address: PropTypes.string.isRequired
}
export default ReceiveModal

38
app/components/Wallet/ReceiveModal.scss

@ -0,0 +1,38 @@
@import '../../variables.scss';
.container {
section {
margin: 25px 0;
padding: 25px;
border-bottom: 1px solid $darkestgrey;
h4 {
font-size: 14px;
font-weight: bold;
text-transform: uppercase;
letter-spacing: 1.5px;
margin-bottom: 10px;
span {
color: $blue;
cursor: pointer;
}
}
.qrcode {
text-align: center;
margin-top: 20px;
}
p {
font-family: 'Roboto';
text-align: center;
font-size: 14px;
font-weight: 200;
border-radius: 7px;
background: $lightgrey;
border: 1px solid $main;
padding: 10px;
}
}
}

71
app/components/Wallet/Wallet.js

@ -0,0 +1,71 @@
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { FaQrcode } from 'react-icons/lib/fa'
import CryptoIcon from 'components/CryptoIcon'
import { btc } from 'utils'
import ReceiveModal from './ReceiveModal'
import styles from './Wallet.scss'
class Wallet extends Component {
constructor(props) {
super(props)
this.state = {
modalOpen: false
}
}
render() {
const {
ticker,
balance,
address,
info
} = this.props
const { modalOpen } = this.state
return (
<div className={styles.wallet}>
{
(modalOpen &&
<ReceiveModal
isOpen={modalOpen}
hideActivityModal={() => this.setState({ modalOpen: false })}
pubkey={info.data.identity_pubkey}
address={address}
/>)
}
<div className={styles.content}>
<div className={styles.left}>
<div className={styles.leftContent}>
<CryptoIcon currency={ticker.crypto} />
<div className={styles.details}>
<h1>{btc.satoshisToBtc(parseFloat(balance.walletBalance) + parseFloat(balance.channelBalance))} BTC</h1>
<span>{btc.satoshisToBtc(balance.walletBalance)} available</span>
<span>{btc.satoshisToBtc(balance.channelBalance)} in channels</span>
</div>
</div>
</div>
<div className={styles.right}>
<div className={styles.rightContent}>
<div onClick={() => this.setState({ modalOpen: true })}>
<FaQrcode />
Address
</div>
</div>
</div>
</div>
</div>
)
}
}
Wallet.propTypes = {
ticker: PropTypes.object.isRequired,
balance: PropTypes.object.isRequired,
address: PropTypes.string.isRequired,
info: PropTypes.object.isRequired
}
export default Wallet

72
app/components/Wallet/Wallet.scss

@ -0,0 +1,72 @@
@import '../../variables.scss';
.wallet {
cursor: pointer;
background: $lightgrey;
transition: background 0.25s;
height: 150px;
}
.left, .right {
display: inline-block;
vertical-align: top;
width: 50%;
height: 150px;
.leftContent, .rightContent {
padding: 25px;
}
}
.leftContent {
display: flex;
flex-direction: row;
.details {
display: flex;
flex-direction: column;
justify-content: center;
h1 {
font-size: 24px;
font-weight: bold;
margin-bottom: 10px;
letter-spacing: 1.5px;
}
span {
margin: 2.5px 0;
}
}
svg {
font-size: 100px;
color: $main;
}
}
.rightContent {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: calc(100% - 50px);
div {
font-size: 20px;
padding: 10px 25px;
background: $main;
transition: background 0.25s;
&:hover {
background: darken($main, 10%);
}
svg {
font-size: 35px;
margin-right: 10px;
}
}
}

3
app/components/Wallet/index.js

@ -0,0 +1,3 @@
import Wallet from './Wallet'
export default Wallet

10
app/keyframes.scss

@ -30,4 +30,14 @@
50% { color: $white; }
75% { color: $gold; }
100% { color: $white; }
}
@keyframes spin {
from {
transform:rotate(0deg)
}
to {
transform:rotate(360deg);
}
}

4
app/lnd/index.js

@ -5,9 +5,9 @@ import methods from './methods'
export default (callback) => {
const lnd = lightning(config.lightningRpc, config.lightningHost)
const lndSubscribe = mainWindow => subscribe(mainWindow, lnd)
const lndMethods = (event, msg, data) => methods(lnd, event, msg, data)
callback(lndSubscribe, lndMethods)
}
}

1
app/lnd/lib/lightning.js

@ -5,7 +5,6 @@ import config from '../config'
module.exports = (rpcpath, host) => {
process.env.GRPC_SSL_CIPHER_SUITES = 'HIGH+ECDSA'
console.log('RPC PATH: ', path.join(__dirname, 'rpc.proto'))
const rpc = grpc.load(path.join(__dirname, 'rpc.proto'))
const lndCert = fs.readFileSync(config.cert)

2
app/lnd/subscribe/index.js

@ -2,8 +2,6 @@ import subscribeToTransactions from './transactions'
import subscribeToInvoices from './invoices'
export default (mainWindow, lnd) => {
console.log('mainWindow: ', mainWindow)
console.log('lnd: ', lnd)
subscribeToTransactions(mainWindow, lnd)
subscribeToInvoices(mainWindow, lnd)
}

1
app/main.dev.js

@ -106,6 +106,7 @@ app.on('ready', async () => {
// There was an error checking for the LND process
if (err) { throw new Error( err ) }
console.log('results: ', results)
// No LND process was found
if (!results.length) {
// Let the front end know we have started syncing LND

2
app/reducers/balance.js

@ -21,7 +21,7 @@ export const fetchBalance = () => async (dispatch) => {
}
// Receive IPC event for balance
export const receiveBalance = (event, { walletBalance, channelBalance }) => dispatch => {
export const receiveBalance = (event, { walletBalance, channelBalance }) => (dispatch) => {
dispatch({ type: RECEIVE_BALANCE, walletBalance, channelBalance })
}

2
app/reducers/ipc.js

@ -36,7 +36,7 @@ const ipc = createIpc({
lndSyncing,
lndSynced,
lndStdout,
receiveInfo,
receivePeers,

12
app/reducers/lnd.js

@ -22,7 +22,7 @@ export const RECEIVE_BLOCK_HEIGHT = 'RECEIVE_BLOCK_HEIGHT'
export const lndSyncing = () => dispatch => dispatch({ type: START_SYNCING })
// Receive IPC event for LND stoping sync
export const lndSynced = () => dispatch => {
export const lndSynced = () => (dispatch) => {
// Fetch data now that we know LND is synced
dispatch(fetchTicker())
dispatch(fetchBalance())
@ -32,7 +32,9 @@ export const lndSynced = () => dispatch => {
}
// Receive IPC event for LND streaming a line
export const lndStdout = (event, lndBlockHeight) => dispatch => dispatch({ type: RECEIVE_LINE, lndBlockHeight: lndBlockHeight.split(' ')[0].split(/(\r\n|\n|\r)/gm)[0] })
export const lndStdout = (event, lndBlockHeight) => dispatch => (
dispatch({ type: RECEIVE_LINE, lndBlockHeight: lndBlockHeight.split(' ')[0].split(/(\r\n|\n|\r)/gm)[0] })
)
export function getBlockHeight() {
return {
@ -60,11 +62,11 @@ export const fetchBlockHeight = () => async (dispatch) => {
const ACTION_HANDLERS = {
[START_SYNCING]: state => ({ ...state, syncing: true }),
[STOP_SYNCING]: state => ({ ...state, syncing: false }),
[RECEIVE_LINE]: (state, { lndBlockHeight }) => ({ ...state, lndBlockHeight }),
[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 })
}
// ------------------------------------

3
app/reducers/transaction.js

@ -73,10 +73,9 @@ export const transactionError = () => (dispatch) => {
// Listener for when a new transaction is pushed from the subscriber
export const newTransaction = (event, { transaction }) => (dispatch) => {
console.log('transaction: ', transaction)
// Fetch new balance
dispatch(fetchBalance())
dispatch({ type: ADD_TRANSACTION, transaction })
// HTML 5 desktop notification for the new transaction

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

@ -11,8 +11,8 @@ const Modal = ({ modalType, modalProps, hideActivityModal, ticker, currentTicker
TRANSACTION: Transaction,
PAYMENT: Payment,
INVOICE: Invoice
}
const customStyles = {
overlay: {
cursor: 'pointer'

34
app/routes/app/components/App.js

@ -5,20 +5,18 @@ import LoadingBolt from 'components/LoadingBolt'
import Form from 'components/Form'
import ModalRoot from 'components/ModalRoot'
import Nav from 'components/Nav'
import Wallet from 'components/Wallet'
import styles from './App.scss'
class App extends Component {
componentWillMount() {
const { fetchTicker, fetchBalance, fetchInfo, lnd: { syncing } } = this.props
if (syncing) {
fetchBlockHeight()
}
const { fetchTicker, fetchBalance, fetchInfo, newAddress, lnd: { syncing } } = this.props
if (!syncing) {
fetchTicker()
fetchBalance()
fetchInfo()
newAddress('p2pkh')
}
}
@ -31,10 +29,11 @@ class App extends Component {
modal: { modalType, modalProps },
hideModal,
ticker,
currentTicker,
address: { address },
balance,
info,
form,
setCurrency,
currentTicker,
openPayForm,
openRequestForm,
@ -51,7 +50,7 @@ class App extends Component {
fetchingBlockHeight={lnd.fetchingBlockHeight}
syncPercentage={syncPercentage}
/>
)
)
}
if (!currentTicker) { return <LoadingBolt /> }
@ -69,15 +68,17 @@ class App extends Component {
<Form formType={form.formType} formProps={formProps} closeForm={closeForm} />
<Nav
ticker={ticker}
balance={balance}
setCurrency={setCurrency}
currentTicker={currentTicker}
openPayForm={openPayForm}
openRequestForm={openRequestForm}
/>
<div className={styles.content}>
<Wallet
ticker={ticker}
balance={balance}
address={address}
info={info}
/>
{children}
</div>
</div>
@ -86,18 +87,25 @@ class App extends Component {
}
App.propTypes = {
lnd: PropTypes.object.isRequired,
syncPercentage: PropTypes.number.isRequired,
fetchBlockHeight: PropTypes.func.isRequired,
modal: PropTypes.object.isRequired,
ticker: PropTypes.object.isRequired,
address: PropTypes.object.isRequired,
balance: PropTypes.object.isRequired,
info: PropTypes.object.isRequired,
form: PropTypes.object.isRequired,
formProps: PropTypes.object.isRequired,
closeForm: PropTypes.func.isRequired,
newAddress: PropTypes.func.isRequired,
fetchInfo: PropTypes.func.isRequired,
hideModal: PropTypes.func.isRequired,
fetchTicker: PropTypes.func.isRequired,
fetchBalance: PropTypes.func.isRequired,
setCurrency: PropTypes.func.isRequired,
openPayForm: PropTypes.func.isRequired,
openRequestForm: PropTypes.func.isRequired,

4
app/routes/app/containers/AppContainer.js

@ -1,6 +1,7 @@
import { withRouter } from 'react-router'
import { connect } from 'react-redux'
import { fetchTicker, setCurrency, tickerSelectors } from 'reducers/ticker'
import { newAddress } from 'reducers/address'
import { fetchBalance } from 'reducers/balance'
import { fetchInfo } from 'reducers/info'
@ -23,6 +24,7 @@ import App from '../components/App'
const mapDispatchToProps = {
fetchTicker,
setCurrency,
newAddress,
fetchBalance,
fetchInfo,
@ -52,7 +54,9 @@ const mapStateToProps = state => ({
lnd: state.lnd,
ticker: state.ticker,
address: state.address,
balance: state.balance,
info: state.info,
payment: state.payment,
transaction: state.transaction,

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

@ -1,26 +1,24 @@
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import ReactSVG from 'react-svg'
import Channels from 'components/Channels'
import Peers from 'components/Peers'
import styles from './Wallet.scss'
class Wallet extends Component {
componentWillMount() {
const { fetchPeers, fetchChannels, newAddress } = this.props
const { fetchPeers, fetchChannels } = this.props
fetchPeers()
fetchChannels()
newAddress('p2pkh')
}
render() {
const {
info,
address: { address },
ticker,
peers: { peersLoading, peers, peer, peerForm },
channels: { channelsLoading, channels, channel, channelForm, pendingChannels },
fetchPeers,
fetchChannels,
setPeer,
setChannel,
peerModalOpen,
@ -38,21 +36,9 @@ class Wallet extends Component {
return (
<div className={styles.wallet}>
<section className={styles.header}>
<section className={styles.walletInfo}>
<ReactSVG path='../resources/zap_2.svg' />
<h1 data-hint='Node identity public key' className='hint--top'>{info.data.identity_pubkey}</h1>
<h4 className={`${styles.address} hint--top`} data-hint='Wallet address'>
<input
type='text'
value={address}
readOnly
/>
</h4>
</section>
</section>
<section className={styles.walletData}>
<Peers
fetchPeers={fetchPeers}
peersLoading={peersLoading}
peers={peers}
modalPeer={peer}
@ -64,6 +50,7 @@ class Wallet extends Component {
disconnect={disconnectRequest}
/>
<Channels
fetchChannels={fetchChannels}
ticker={ticker}
peers={peers}
channelsLoading={channelsLoading}
@ -89,7 +76,6 @@ class Wallet extends Component {
Wallet.propTypes = {
fetchPeers: PropTypes.func.isRequired,
fetchChannels: PropTypes.func.isRequired,
info: PropTypes.object.isRequired,
ticker: PropTypes.object.isRequired,
peers: PropTypes.object.isRequired,
channels: PropTypes.object.isRequired,
@ -104,8 +90,6 @@ Wallet.propTypes = {
allChannels: PropTypes.array.isRequired,
openChannel: PropTypes.func.isRequired,
closeChannel: PropTypes.func.isRequired,
newAddress: PropTypes.func.isRequired,
address: PropTypes.object.isRequired,
currentTicker: PropTypes.object.isRequired,
explorerLinkBase: PropTypes.string.isRequired
}

1
app/variables.scss

@ -12,4 +12,5 @@ $bluegrey: #555459;
$green: #0bb634;
$red: #ff0b00;
$blue: #007bb6;
$curve: cubic-bezier(0.650, 0.000, 0.450, 1.000);

1
package.json

@ -199,6 +199,7 @@
"axios": "^0.16.2",
"bitcoinjs-lib": "^3.2.0",
"bitcore-lib": "^0.14.0",
"copy-to-clipboard": "^3.0.8",
"devtron": "^1.4.0",
"electron-debug": "^1.2.0",
"font-awesome": "^4.7.0",

26
yarn.lock

@ -2170,10 +2170,6 @@ connect-history-api-fallback@^1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/connect-history-api-fallback/-/connect-history-api-fallback-1.3.0.tgz#e51d17f8f0ef0db90a64fdb47de3051556e9f169"
connected-domain@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/connected-domain/-/connected-domain-1.0.0.tgz#bfe77238c74be453a79f0cb6058deeb4f2358e93"
console-browserify@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.1.0.tgz#f0241c45730a9fc6323b206dbf38edc741d0bb10"
@ -2216,6 +2212,12 @@ cookie@0.3.1:
version "0.3.1"
resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.3.1.tgz#e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb"
copy-to-clipboard@^3.0.8:
version "3.0.8"
resolved "https://registry.yarnpkg.com/copy-to-clipboard/-/copy-to-clipboard-3.0.8.tgz#f4e82f4a8830dce4666b7eb8ded0c9bcc313aba9"
dependencies:
toggle-selection "^1.0.3"
core-js@^1.0.0:
version "1.2.7"
resolved "https://registry.yarnpkg.com/core-js/-/core-js-1.2.7.tgz#652294c14651db28fa93bd2d5ff2983a4f08c636"
@ -6964,12 +6966,6 @@ prr@~0.0.0:
version "0.0.0"
resolved "https://registry.yarnpkg.com/prr/-/prr-0.0.0.tgz#1a84b85908325501411853d0081ee3fa86e2926a"
ps-node@^0.1.6:
version "0.1.6"
resolved "https://registry.yarnpkg.com/ps-node/-/ps-node-0.1.6.tgz#9af67a99d7b1d0132e51a503099d38a8d2ace2c3"
dependencies:
table-parser "^0.1.3"
pseudomap@^1.0.1, pseudomap@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3"
@ -8396,12 +8392,6 @@ synesthesia@^1.0.1:
dependencies:
css-color-names "0.0.3"
table-parser@^0.1.3:
version "0.1.3"
resolved "https://registry.yarnpkg.com/table-parser/-/table-parser-0.1.3.tgz#0441cfce16a59481684c27d1b5a67ff15a43c7b0"
dependencies:
connected-domain "^1.0.0"
table@^3.7.8:
version "3.8.3"
resolved "https://registry.yarnpkg.com/table/-/table-3.8.3.tgz#2bbc542f0fda9861a755d3947fefd8b3f513855f"
@ -8570,6 +8560,10 @@ to-fast-properties@^1.0.1:
version "1.0.3"
resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47"
toggle-selection@^1.0.3:
version "1.0.6"
resolved "https://registry.yarnpkg.com/toggle-selection/-/toggle-selection-1.0.6.tgz#6e45b1263f2017fa0acc7d89d78b15b8bf77da32"
toposort@^1.0.0:
version "1.0.3"
resolved "https://registry.yarnpkg.com/toposort/-/toposort-1.0.3.tgz#f02cd8a74bd8be2fc0e98611c3bacb95a171869c"

Loading…
Cancel
Save