From 6e2dde1dfe71c025872107871a5969c058f8e122 Mon Sep 17 00:00:00 2001 From: Jack Mallers Date: Fri, 20 Oct 2017 21:22:22 -0500 Subject: [PATCH 1/3] feature(refresh channels): ability to refresh channels --- app/app.global.scss | 6 ++ app/components/Channels/Channels.js | 136 +++++++++++++++---------- app/components/Channels/Channels.scss | 24 +++++ app/keyframes.scss | 10 ++ app/routes/wallet/components/Wallet.js | 2 + 5 files changed, 124 insertions(+), 54 deletions(-) diff --git a/app/app.global.scss b/app/app.global.scss index d55b7f23..0a946033 100644 --- a/app/app.global.scss +++ b/app/app.global.scss @@ -66,4 +66,10 @@ body { opacity: 1; stroke: darken($main, 10%); } +} + +@keyframes spin { + 100% { + transform: rotate(360deg); + } } \ No newline at end of file diff --git a/app/components/Channels/Channels.js b/app/components/Channels/Channels.js index 18c73cee..4ad0929e 100644 --- a/app/components/Channels/Channels.js +++ b/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,67 +24,93 @@ const Channels = ({ closeChannel, currentTicker, explorerLinkBase -}) => ( -
- - -
-

Channels

-
setChannelForm({ isOpen: true })} - > - +}) => { + const refreshClicked = (event) => { + // store event in icon so we dont get an error when react clears it + let 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 ( +
+ + +
+

Channels

+ + + +
setChannelForm({ isOpen: true })} + > + +
-
-
    - { - !channelsLoading ? - allChannels.map((channel, index) => { - if (Object.prototype.hasOwnProperty.call(channel, 'blocks_till_open')) { +
      + { + !channelsLoading ? + allChannels.map((channel, index) => { + if (Object.prototype.hasOwnProperty.call(channel, 'blocks_till_open')) { + return ( + + ) + } else if (Object.prototype.hasOwnProperty.call(channel, 'closing_txid')) { + return ( + + ) + } return ( - - ) - } else if (Object.prototype.hasOwnProperty.call(channel, 'closing_txid')) { - return ( - ) - } - return ( - - ) - }) - : - 'Loading...' - } -
    -
-) + }) + : + 'Loading...' + } + +
+ ) +} Channels.propTypes = { ticker: PropTypes.object.isRequired, diff --git a/app/components/Channels/Channels.scss b/app/components/Channels/Channels.scss index 8d73c905..df5f7b38 100644 --- a/app/components/Channels/Channels.scss +++ b/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; diff --git a/app/keyframes.scss b/app/keyframes.scss index a5cc3fe8..c5317b88 100644 --- a/app/keyframes.scss +++ b/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); + } } \ No newline at end of file diff --git a/app/routes/wallet/components/Wallet.js b/app/routes/wallet/components/Wallet.js index e21cbe02..62081b61 100644 --- a/app/routes/wallet/components/Wallet.js +++ b/app/routes/wallet/components/Wallet.js @@ -21,6 +21,7 @@ class Wallet extends Component { ticker, peers: { peersLoading, peers, peer, peerForm }, channels: { channelsLoading, channels, channel, channelForm, pendingChannels }, + fetchChannels, setPeer, setChannel, peerModalOpen, @@ -64,6 +65,7 @@ class Wallet extends Component { disconnect={disconnectRequest} /> Date: Fri, 20 Oct 2017 21:55:49 -0500 Subject: [PATCH 2/3] feature(refresh peers): ability to refresh peers --- app/components/Peers/Peers.js | 72 ++++++++++++++++++-------- app/components/Peers/Peers.scss | 14 +++++ app/routes/wallet/components/Wallet.js | 2 + 3 files changed, 66 insertions(+), 22 deletions(-) diff --git a/app/components/Peers/Peers.js b/app/components/Peers/Peers.js index 5df2b11e..e90a0cbd 100644 --- a/app/components/Peers/Peers.js +++ b/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,30 +18,56 @@ const Peers = ({ setPeerForm, connect, disconnect -}) => ( -
- - -
-

Peers

-
setPeerForm({ isOpen: true })} - > - +}) => { + const refreshClicked = (event) => { + // store event in icon so we dont get an error when react clears it + let 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 ( +
+ + +
+

Peers

+ + + +
setPeerForm({ isOpen: true })} + > + +
+
    + { + !peersLoading ? + peers.map(peer => ) + : + 'Loading...' + } +
-
    - { - !peersLoading ? - peers.map(peer => ) - : - 'Loading...' - } -
-
-) + ) +} Peers.propTypes = { peersLoading: PropTypes.bool.isRequired, diff --git a/app/components/Peers/Peers.scss b/app/components/Peers/Peers.scss index f24f6f70..613ce641 100644 --- a/app/components/Peers/Peers.scss +++ b/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; diff --git a/app/routes/wallet/components/Wallet.js b/app/routes/wallet/components/Wallet.js index 62081b61..07bc1a09 100644 --- a/app/routes/wallet/components/Wallet.js +++ b/app/routes/wallet/components/Wallet.js @@ -21,6 +21,7 @@ class Wallet extends Component { ticker, peers: { peersLoading, peers, peer, peerForm }, channels: { channelsLoading, channels, channel, channelForm, pendingChannels }, + fetchPeers, fetchChannels, setPeer, setChannel, @@ -54,6 +55,7 @@ class Wallet extends Component {
Date: Sat, 21 Oct 2017 00:02:47 -0500 Subject: [PATCH 3/3] fix(lint): fix linting errors --- app/api/index.js | 6 ++--- app/components/Channels/Channels.js | 20 ++++++++++++----- app/components/LndSyncing/LndSyncing.js | 30 ++++++++++++++----------- app/components/Peers/Peers.js | 11 ++++----- app/lnd/index.js | 4 ++-- app/lnd/lib/lightning.js | 1 - app/lnd/subscribe/index.js | 2 -- app/reducers/balance.js | 2 +- app/reducers/ipc.js | 2 +- app/reducers/lnd.js | 12 +++++----- app/reducers/transaction.js | 3 +-- app/routes/app/components/App.js | 11 ++++----- 12 files changed, 58 insertions(+), 46 deletions(-) diff --git a/app/api/index.js b/app/api/index.js index e71c69df..d394fe60 100644 --- a/app/api/index.js +++ b/app/api/index.js @@ -16,12 +16,12 @@ export function requestTickers(ids) { } -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) -} \ No newline at end of file +} diff --git a/app/components/Channels/Channels.js b/app/components/Channels/Channels.js index 4ad0929e..012190e4 100644 --- a/app/components/Channels/Channels.js +++ b/app/components/Channels/Channels.js @@ -27,15 +27,15 @@ const Channels = ({ }) => { const refreshClicked = (event) => { // store event in icon so we dont get an error when react clears it - let icon = event.currentTarget + const icon = event.currentTarget // fetch channels fetchChannels() - + // clear animation after the second so we can reuse it - setTimeout(() => icon.style.animation = '', 1000) + setTimeout(() => { icon.style.animation = '' }, 1000) - // spin icon for 1 sec + // spin icon for 1 sec icon.style.animation = 'spin 1000ms linear 1' } @@ -48,13 +48,20 @@ const Channels = ({ explorerLinkBase={explorerLinkBase} closeChannel={closeChannel} /> - +

Channels

zap
{!fetchingBlockHeight &&

{syncPercentage}%

} -
-
+

syncing your lightning node to the blockchain

@@ -52,15 +52,13 @@ class LndSyncing extends Component {
    { - facts.map((facts, index) => { - return ( -
  • this.setState({ currentFact: index })} - /> - ) - }) + facts.map((fact, index) => ( +
  • this.setState({ currentFact: index })} + /> + )) }
@@ -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 diff --git a/app/components/Peers/Peers.js b/app/components/Peers/Peers.js index e90a0cbd..45115cec 100644 --- a/app/components/Peers/Peers.js +++ b/app/components/Peers/Peers.js @@ -21,15 +21,15 @@ const Peers = ({ }) => { const refreshClicked = (event) => { // store event in icon so we dont get an error when react clears it - let icon = event.currentTarget + const icon = event.currentTarget // fetch peers fetchPeers() - + // clear animation after the second so we can reuse it - setTimeout(() => icon.style.animation = '', 1000) + setTimeout(() => { icon.style.animation = '' }, 1000) - // spin icon for 1 sec + // spin icon for 1 sec icon.style.animation = 'spin 1000ms linear 1' } @@ -42,7 +42,7 @@ const Peers = ({ { 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) -} \ No newline at end of file +} diff --git a/app/lnd/lib/lightning.js b/app/lnd/lib/lightning.js index 3c3a30f8..5af4443a 100644 --- a/app/lnd/lib/lightning.js +++ b/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) diff --git a/app/lnd/subscribe/index.js b/app/lnd/subscribe/index.js index ae1f08f5..170adf60 100644 --- a/app/lnd/subscribe/index.js +++ b/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) } diff --git a/app/reducers/balance.js b/app/reducers/balance.js index 4b1b458e..4da402fe 100644 --- a/app/reducers/balance.js +++ b/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 }) } diff --git a/app/reducers/ipc.js b/app/reducers/ipc.js index d8329d1b..a0789e30 100644 --- a/app/reducers/ipc.js +++ b/app/reducers/ipc.js @@ -36,7 +36,7 @@ const ipc = createIpc({ lndSyncing, lndSynced, lndStdout, - + receiveInfo, receivePeers, diff --git a/app/reducers/lnd.js b/app/reducers/lnd.js index 613db848..0c237775 100644 --- a/app/reducers/lnd.js +++ b/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 }) } // ------------------------------------ diff --git a/app/reducers/transaction.js b/app/reducers/transaction.js index cd305ffc..33821551 100644 --- a/app/reducers/transaction.js +++ b/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 diff --git a/app/routes/app/components/App.js b/app/routes/app/components/App.js index 837bba83..43df072d 100644 --- a/app/routes/app/components/App.js +++ b/app/routes/app/components/App.js @@ -11,10 +11,6 @@ class App extends Component { componentWillMount() { const { fetchTicker, fetchBalance, fetchInfo, lnd: { syncing } } = this.props - if (syncing) { - fetchBlockHeight() - } - if (!syncing) { fetchTicker() fetchBalance() @@ -51,7 +47,7 @@ class App extends Component { fetchingBlockHeight={lnd.fetchingBlockHeight} syncPercentage={syncPercentage} /> - ) + ) } if (!currentTicker) { return } @@ -86,6 +82,11 @@ 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, balance: PropTypes.object.isRequired,