Browse Source

feature(networkmap): working with some performance enhancements

renovate/lint-staged-8.x
Jack Mallers 7 years ago
parent
commit
bf0227ec96
  1. 82
      app/components/Network/NetworkGraph.js
  2. 15
      app/components/Network/NetworkGraph.scss
  3. 50
      app/components/Network/TransactionForm.js
  4. 125
      app/components/Network/TransactionForm.scss
  5. 19
      app/lnd/methods/index.js
  6. 7
      app/lnd/methods/paymentsController.js
  7. 3
      app/reducers/channels.js
  8. 5
      app/reducers/ipc.js
  9. 103
      app/reducers/network.js
  10. 5
      app/routes/activity/components/Activity.js
  11. 4
      app/routes/activity/containers/ActivityContainer.js
  12. 5
      app/routes/app/components/App.js
  13. 36
      app/routes/network/components/Network.js
  14. 1
      app/routes/network/components/Network.scss
  15. 14
      app/routes/network/containers/NetworkContainer.js

82
app/components/Network/NetworkGraph.js

@ -1,7 +1,10 @@
import { findDOMNode } from 'react-dom'
import React, { Component } from 'react' import React, { Component } from 'react'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import { ForceGraph, ForceGraphNode, ForceGraphLink } from 'react-vis-force' import { ForceGraph, ForceGraphNode, ForceGraphLink } from 'react-vis-force'
import { FaCircle } from 'react-icons/lib/fa' import { FaCircle } from 'react-icons/lib/fa'
import Isvg from 'react-inlinesvg'
import bitcoinIcon from 'icons/skinny_bitcoin.svg'
import styles from './NetworkGraph.scss' import styles from './NetworkGraph.scss'
class NetworkGraph extends Component { class NetworkGraph extends Component {
@ -15,7 +18,7 @@ class NetworkGraph extends Component {
componentWillMount() { componentWillMount() {
setTimeout(() => { setTimeout(() => {
this.setState({ ready: true }) this.setState({ ready: true })
}, 1000) }, 10000)
} }
render() { render() {
@ -24,10 +27,12 @@ class NetworkGraph extends Component {
network: { nodes, edges, selectedChannel, networkLoading }, network: { nodes, edges, selectedChannel, networkLoading },
selectedPeerPubkeys, selectedPeerPubkeys,
selectedChannelIds, selectedChannelIds,
identity_pubkey, currentRouteChanIds,
identity_pubkey
} = this.props } = this.props
if (!ready || networkLoading) { if (!ready || networkLoading) {
console.log('hi!')
return ( return (
<section className={styles.network}> <section className={styles.network}>
<div className={styles.networkLoading}> <div className={styles.networkLoading}>
@ -40,6 +45,7 @@ class NetworkGraph extends Component {
return ( return (
<section className={styles.network}> <section className={styles.network}>
<ForceGraph <ForceGraph
id='map'
simulationOptions={ simulationOptions={
{ {
height: 800, height: 800,
@ -58,19 +64,21 @@ class NetworkGraph extends Component {
{ {
nodes.map(node => nodes.map(node =>
<ForceGraphNode <ForceGraphNode
id={node.pub_key}
r={25} r={25}
label={node.pub_key} label={node.pub_key}
key={node.pub_key} key={node.pub_key}
node={{ id: node.pub_key }} node={{ id: node.pub_key }}
fill={selectedPeerPubkeys.includes(node.pub_key) ? '#5589F3' : '#353535'}
strokeWidth={2.5} strokeWidth={2.5}
className={styles.node} className={`${styles.node} ${identity_pubkey === node.pub_key && styles.owner} ${selectedPeerPubkeys.includes(node.pub_key) && styles.peer}`}
/> />
) )
} }
{ {
edges.map(edge => edges.map(edge => {
return (
<ForceGraphLink <ForceGraphLink
id={edge.channel_id}
className={selectedChannelIds.includes(edge.channel_id) && styles.activeEdge} className={selectedChannelIds.includes(edge.channel_id) && styles.activeEdge}
key={edge.channel_id} key={edge.channel_id}
link={{ source: edge.node1_pub, target: edge.node2_pub }} link={{ source: edge.node1_pub, target: edge.node2_pub }}
@ -78,6 +86,70 @@ class NetworkGraph extends Component {
strokeWidth='5' strokeWidth='5'
/> />
) )
})
}
{
currentRouteChanIds.map((chan_id) => {
const line = document.getElementById(chan_id)
if (!line) { return }
const x1 = line.x1.baseVal.value
const x2 = line.x2.baseVal.value
const y1 = line.y1.baseVal.value
const y2 = line.y2.baseVal.value
return (
<circle id={`circle-${chan_id}`} r="10" cx={x1} cy={y1} fill="#FFDC53" zoomable />
)
})
}
{
currentRouteChanIds.map((chan_id) => {
const line = document.getElementById(chan_id)
if (!line) { return }
const x1 = line.x1.baseVal.value
const x2 = line.x2.baseVal.value
const y1 = line.y1.baseVal.value
const y2 = line.y2.baseVal.value
return (
<animate
xlinkHref={`#circle-${chan_id}`}
attributeName="cx"
from={x1}
to={x2}
dur="1s"
fill="freeze"
repeatCount="indefinite"
/>
)
})
}
{
currentRouteChanIds.map((chan_id) => {
const line = document.getElementById(chan_id)
if (!line) { return }
const x1 = line.x1.baseVal.value
const x2 = line.x2.baseVal.value
const y1 = line.y1.baseVal.value
const y2 = line.y2.baseVal.value
return (
<animate
xlinkHref={`#circle-${chan_id}`}
attributeName="cy"
from={y1}
to={y2}
dur="1s"
fill="freeze"
repeatCount="indefinite"
/>
)
})
} }
</ForceGraph> </ForceGraph>
</section> </section>

15
app/components/Network/NetworkGraph.scss

@ -18,6 +18,10 @@
left: 0; left: 0;
width: 70%; width: 70%;
height: 100vh; height: 100vh;
animation: fadein 0.5s;
animation-timing-function:linear;
animation-fill-mode: forwards;
animation-iteration-count: infinite;
h1 { h1 {
font-size: 22px; font-size: 22px;
@ -32,13 +36,22 @@
height: 100vh; height: 100vh;
animation: fadein 0.5s; animation: fadein 0.5s;
animation-timing-function:linear; animation-timing-function:linear;
animation-fill-mode:forwards; animation-fill-mode: forwards;
animation-iteration-count: 1; animation-iteration-count: 1;
} }
.node { .node {
stroke-width: 2 !important; stroke-width: 2 !important;
animation: color-change 1s infinite; animation: color-change 1s infinite;
fill: #353535;
&.owner {
fill: #FFFFFF;
}
&.peer {
fill: #5589F3;
}
} }
.activeEdge { .activeEdge {

50
app/components/Network/TransactionForm.js

@ -1,14 +1,60 @@
import React from 'react' import React from 'react'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import { btc } from 'utils'
import styles from './TransactionForm.scss' import styles from './TransactionForm.scss'
const TransactionForm = ({}) => ( const TransactionForm = ({ updatePayReq, pay_req, loadingRoutes, payReqRoutes, setCurrentRoute, currentRoute }) => (
<div className={styles.transactionForm}> <div className={styles.transactionForm}>
tx form <div className={styles.form}>
<input
className={styles.transactionInput}
placeholder='Payment request...'
value={pay_req}
onChange={event => updatePayReq(event.target.value)}
/>
</div>
{
loadingRoutes &&
<div className={styles.loading}>
<div className={styles.spinner} />
<h1>calculating all routes...</h1>
</div>
}
<ul className={styles.routes}>
{
payReqRoutes.map((route, index) =>
<li className={`${styles.route} ${currentRoute == route && styles.active}`} key={index} onClick={() => setCurrentRoute(route)}>
<header>
<h1>Route #{index + 1}</h1>
<span>Hops: {route.hops.length}</span>
</header>
<div className={styles.data}>
<section>
<h4>Amount</h4>
<span>{btc.satoshisToBtc(route.total_amt)} BTC</span>
</section>
<section>
<h4>Fees</h4>
<span>{btc.satoshisToBtc(route.total_fees)} BTC</span>
</section>
</div>
</li>
)
}
</ul>
</div> </div>
) )
TransactionForm.propTypes = { TransactionForm.propTypes = {
updatePayReq: PropTypes.func.isRequired,
pay_req: PropTypes.string.isRequired,
loadingRoutes: PropTypes.bool.isRequired,
payReqRoutes: PropTypes.array.isRequired,
setCurrentRoute: PropTypes.func.isRequired
} }
export default TransactionForm export default TransactionForm

125
app/components/Network/TransactionForm.scss

@ -0,0 +1,125 @@
@import '../../variables.scss';
@-webkit-keyframes animation-rotate {
100% {
-webkit-transform: rotate(360deg);
}
}
@-moz-keyframes animation-rotate {
100% {
-moz-transform: rotate(360deg);
}
}
@-o-keyframes animation-rotate {
100% {
-o-transform: rotate(360deg);
}
}
@keyframes animation-rotate {
100% {
transform: rotate(360deg);
}
}
.spinner {
border: 1px solid rgba(255, 220, 83, 0.1);
border-left-color: rgba(255, 220, 83, 0.4);
-webkit-border-radius: 999px;
-moz-border-radius: 999px;
border-radius: 999px;
}
.spinner {
margin: 0 auto;
height: 100px;
width: 100px;
-webkit-animation: animation-rotate 1000ms linear infinite;
-moz-animation: animation-rotate 1000ms linear infinite;
-o-animation: animation-rotate 1000ms linear infinite;
animation: animation-rotate 1000ms linear infinite;
}
.loading {
margin-top: 40px;
h1 {
text-align: center;
margin-top: 25px;
}
}
.transactionForm {
color: $white;
margin-top: 50px;
.form {
padding: 0 20px;
}
.transactionInput {
outline: 0;
border: 0;
border-bottom: 1px solid $secondary;
color: $secondary;
background: transparent;
padding: 5px;
width: 100%;
font-size: 14px;
color: $white;
}
}
.routes {
margin-top: 40px;
}
.route {
margin: 20px 0;
padding: 20px;
cursor: pointer;
&:hover {
background: darken(#353535, 10%);
}
&.active {
background: darken(#353535, 10%);
}
header {
display: flex;
flex-direction: row;
justify-content: space-between;
margin-bottom: 20px;
h1 {
font-size: 16px;
font-weight: bold;
}
span {
font-weight: bold;
text-transform: uppercase;
font-size: 12px;
letter-spacing: 1.2px;
}
}
.data {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
section {
h4 {
font-size: 12px;
font-weight: bold;
margin-bottom: 5px;
}
}
}
}

19
app/lnd/methods/index.js

@ -44,6 +44,20 @@ export default function (lnd, event, msg, data) {
.then(routes => event.sender.send('receiveQueryRoutes', routes)) .then(routes => event.sender.send('receiveQueryRoutes', routes))
.catch(error => console.log('queryRoutes error: ', error)) .catch(error => console.log('queryRoutes error: ', error))
break break
case 'getInvoiceAndQueryRoutes':
// Data looks like { pubkey: String, amount: Number }
invoicesController.getInvoice(lnd, { pay_req: data.payreq })
.then(invoiceData => {
console.log('invoiceData: ', invoiceData)
networkController.queryRoutes(lnd, { pubkey: invoiceData.destination , amount: invoiceData.num_satoshis })
.then(routes => {
console.log('routes: ', routes)
event.sender.send('receiveInvoiceAndQueryRoutes', routes)
})
.catch(error => console.log('getInvoiceAndQueryRoutes queryRoutes error: ', error))
})
.catch(error => console.log('getInvoiceAndQueryRoutes invoice error: ', error))
break
case 'newaddress': case 'newaddress':
// Data looks like { address: '' } // Data looks like { address: '' }
walletController.newAddress(lnd, data.type) walletController.newAddress(lnd, data.type)
@ -129,7 +143,10 @@ export default function (lnd, event, msg, data) {
console.log('payinvoice success: ', payment_route) console.log('payinvoice success: ', payment_route)
event.sender.send('paymentSuccessful', Object.assign(data, { payment_route })) event.sender.send('paymentSuccessful', Object.assign(data, { payment_route }))
}) })
.catch(({ error }) => event.sender.send('paymentFailed', { error: error.toString() })) .catch(({ error }) => {
console.log('error: ', error)
event.sender.send('paymentFailed', { error: error.toString() })
})
break break
case 'sendCoins': case 'sendCoins':
// Transaction looks like { txid: String } // Transaction looks like { txid: String }

7
app/lnd/methods/paymentsController.js

@ -6,8 +6,11 @@
*/ */
export function sendPaymentSync(lnd, { paymentRequest }) { export function sendPaymentSync(lnd, { paymentRequest }) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
lnd.sendPaymentSync({ payment_request: paymentRequest }, (err, data) => { lnd.sendPaymentSync({ payment_request: paymentRequest }, (error, data) => {
if (err) { reject(err) } if (error) {
reject({ error })
return
}
if (!data.payment_route) { reject({ error: data.payment_error }) } if (!data.payment_route) { reject({ error: data.payment_error }) }

3
app/reducers/channels.js

@ -197,7 +197,8 @@ export const channelGraphData = (event, data) => (dispatch, getState) => {
// if there are any new channel updates // if there are any new channel updates
if (channel_updates.length) { if (channel_updates.length) {
// The network has updated, so fetch a new result // The network has updated, so fetch a new result
dispatch(fetchDescribeNetwork()) // TODO: can't do this now because of the SVG performance issues, after we fix this we can uncomment the line below
// 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++) {

5
app/reducers/ipc.js

@ -33,7 +33,7 @@ import {
newTransaction newTransaction
} from './transaction' } from './transaction'
import { receiveDescribeNetwork, receiveQueryRoutes } from './network' import { receiveDescribeNetwork, receiveQueryRoutes, receiveInvoiceAndQueryRoutes } from './network'
// Import all receiving IPC event handlers and pass them into createIpc // Import all receiving IPC event handlers and pass them into createIpc
const ipc = createIpc({ const ipc = createIpc({
@ -90,7 +90,8 @@ const ipc = createIpc({
newTransaction, newTransaction,
receiveDescribeNetwork, receiveDescribeNetwork,
receiveQueryRoutes receiveQueryRoutes,
receiveInvoiceAndQueryRoutes
}) })
export default ipc export default ipc

103
app/reducers/network.js

@ -1,5 +1,6 @@
import { createSelector } from 'reselect' import { createSelector } from 'reselect'
import { ipcRenderer } from 'electron' import { ipcRenderer } from 'electron'
import { bech32 } from '../utils'
// ------------------------------------ // ------------------------------------
// Constants // Constants
@ -19,11 +20,16 @@ export const SET_CURRENT_TAB = 'SET_CURRENT_TAB'
export const SET_CURRENT_PEER = 'SET_CURRENT_PEER' export const SET_CURRENT_PEER = 'SET_CURRENT_PEER'
export const UPDATE_PAY_REQ = 'UPDATE_PAY_REQ' export const UPDATE_PAY_REQ = 'UPDATE_PAY_REQ'
export const RESET_PAY_REQ = 'RESET_PAY_REQ'
export const UPDATE_SELECTED_PEERS = 'UPDATE_SELECTED_PEERS' export const UPDATE_SELECTED_PEERS = 'UPDATE_SELECTED_PEERS'
export const UPDATE_SELECTED_CHANNELS = 'UPDATE_SELECTED_CHANNELS' export const UPDATE_SELECTED_CHANNELS = 'UPDATE_SELECTED_CHANNELS'
export const GET_INFO_AND_QUERY_ROUTES = 'GET_INFO_AND_QUERY_ROUTES'
export const RECEIVE_INFO_AND_QUERY_ROUTES = 'RECEIVE_INFO_AND_QUERY_ROUTES'
export const CLEAR_QUERY_ROUTES = 'CLEAR_QUERY_ROUTES'
// ------------------------------------ // ------------------------------------
// Actions // Actions
// ------------------------------------ // ------------------------------------
@ -75,6 +81,12 @@ export function updatePayReq(pay_req) {
} }
} }
export function resetPayReq() {
return {
type: RESET_PAY_REQ
}
}
export function updateSelectedPeers(peer) { export function updateSelectedPeers(peer) {
return { return {
type: UPDATE_SELECTED_PEERS, type: UPDATE_SELECTED_PEERS,
@ -89,6 +101,18 @@ export function updateSelectedChannels(channel) {
} }
} }
export function getInvoiceAndQueryRoutes() {
return {
type: GET_INFO_AND_QUERY_ROUTES
}
}
export function clearQueryRoutes() {
return {
type: CLEAR_QUERY_ROUTES
}
}
// Send IPC event for describeNetwork // Send IPC event for describeNetwork
export const fetchDescribeNetwork = () => (dispatch) => { export const fetchDescribeNetwork = () => (dispatch) => {
dispatch(getDescribeNetwork()) dispatch(getDescribeNetwork())
@ -105,6 +129,16 @@ export const queryRoutes = (pubkey, amount) => (dispatch) => {
export const receiveQueryRoutes = (event, { routes }) => dispatch => dispatch({ type: RECEIVE_QUERY_ROUTES, routes }) export const receiveQueryRoutes = (event, { routes }) => dispatch => dispatch({ type: RECEIVE_QUERY_ROUTES, routes })
// take a payreq and query routes for it
export const fetchInvoiceAndQueryRoutes = (payreq) => (dispatch) => {
dispatch(getInvoiceAndQueryRoutes())
ipcRenderer.send('lnd', { msg: 'getInvoiceAndQueryRoutes', data: { payreq } })
}
export const receiveInvoiceAndQueryRoutes = (event, { routes }) => dispatch => {
console.log('routes: ', routes)
dispatch({ type: RECEIVE_INFO_AND_QUERY_ROUTES, routes })
}
// ------------------------------------ // ------------------------------------
// Action Handlers // Action Handlers
// ------------------------------------ // ------------------------------------
@ -121,12 +155,7 @@ const ACTION_HANDLERS = {
} }
), ),
[SET_CURRENT_ROUTE]: (state, { route }) => ( [SET_CURRENT_ROUTE]: (state, { route }) => ({ ...state, currentRoute: route }),
{
...state,
selectedNode: { pubkey: state.selectedNode.pubkey, routes: state.selectedNode.routes, currentRoute: route }
}
),
[SET_CURRENT_CHANNEL]: (state, { selectedChannel }) => ({ ...state, selectedChannel }), [SET_CURRENT_CHANNEL]: (state, { selectedChannel }) => ({ ...state, selectedChannel }),
@ -135,6 +164,11 @@ const ACTION_HANDLERS = {
[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 }),
[RESET_PAY_REQ]: state => ({ ...state, pay_req: '' }),
[GET_INFO_AND_QUERY_ROUTES]: state => ({ ...state, fetchingInvoiceAndQueryingRoutes: true }),
[RECEIVE_INFO_AND_QUERY_ROUTES]: (state, { routes }) => ({ ...state, fetchingInvoiceAndQueryingRoutes: false, payReqRoutes: routes }),
[CLEAR_QUERY_ROUTES]: state => ({ ...state, payReqRoutes: [], currentRoute: {} }),
[UPDATE_SELECTED_PEERS]: (state, { peer }) => { [UPDATE_SELECTED_PEERS]: (state, { peer }) => {
let selectedPeers let selectedPeers
@ -173,29 +207,53 @@ const ACTION_HANDLERS = {
// Selectors // Selectors
// ------------------------------------ // ------------------------------------
const networkSelectors = {} const networkSelectors = {}
const currentRouteSelector = state => state.network.selectedNode.currentRoute const selectedPeersSelector = state => state.network.selectedPeers
const selectedPeers = state => state.network.selectedPeers const selectedChannelsSelector = state => state.network.selectedChannels
const selectedChannels = state => state.network.selectedChannels const payReqSelector = state => state.network.pay_req
const currentRouteSelector = state => state.network.currentRoute
networkSelectors.currentRouteHopChanIds = createSelector( // networkSelectors.currentRouteHopChanIds = createSelector(
currentRouteSelector, // currentRouteSelector,
(currentRoute) => { // (currentRoute) => {
if (!currentRoute.hops) { return [] } // if (!currentRoute.hops) { return [] }
return currentRoute.hops.map(hop => hop.chan_id) // return currentRoute.hops.map(hop => hop.chan_id)
} // }
) // )
networkSelectors.selectedPeerPubkeys = createSelector( networkSelectors.selectedPeerPubkeys = createSelector(
selectedPeers, selectedPeersSelector,
peers => peers.map(peer => peer.pub_key) peers => peers.map(peer => peer.pub_key)
) )
networkSelectors.selectedChannelIds = createSelector( networkSelectors.selectedChannelIds = createSelector(
selectedChannels, selectedChannelsSelector,
channels => channels.map(channel => channel.chan_id) channels => channels.map(channel => channel.chan_id)
) )
networkSelectors.payReqIsLn = createSelector(
payReqSelector,
(input) => {
if (!input.startsWith('ln')) { return false }
try {
bech32.decode(input)
return true
} catch (e) {
return false
}
}
)
networkSelectors.currentRouteChanIds = createSelector(
currentRouteSelector,
(route) => {
if (!route.hops || !route.hops.length) { return [] }
return route.hops.map(hop => hop.chan_id)
}
)
export { networkSelectors } export { networkSelectors }
// ------------------------------------ // ------------------------------------
@ -205,19 +263,16 @@ const initialState = {
networkLoading: false, networkLoading: false,
nodes: [], nodes: [],
edges: [], edges: [],
selectedNode: {
pubkey: '',
routes: [],
currentRoute: {}
},
selectedChannel: {}, selectedChannel: {},
currentTab: 1, currentTab: 1,
currentPeer: {}, currentPeer: {},
currentRoute: {},
fetchingInvoiceAndQueryingRoutes: false,
pay_req: '', pay_req: '',
payReqRoutes: [],
selectedPeers: [], selectedPeers: [],
selectedChannels: [] selectedChannels: []
} }

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

@ -4,6 +4,7 @@ import { MdSearch } from 'react-icons/lib/md'
import { FaAngleDown } from 'react-icons/lib/fa' import { FaAngleDown } from 'react-icons/lib/fa'
import Wallet from 'components/Wallet' import Wallet from 'components/Wallet'
import LoadingBolt from 'components/LoadingBolt'
import Invoice from './components/Invoice' import Invoice from './components/Invoice'
import Payment from './components/Payment' import Payment from './components/Payment'
import Transaction from './components/Transaction' import Transaction from './components/Transaction'
@ -19,8 +20,9 @@ class Activity extends Component {
} }
componentWillMount() { componentWillMount() {
const { fetchPayments, fetchInvoices, fetchTransactions } = this.props const { fetchPayments, fetchInvoices, fetchTransactions, fetchBalance } = this.props
fetchBalance()
fetchPayments() fetchPayments()
fetchInvoices() fetchInvoices()
fetchTransactions() fetchTransactions()
@ -60,6 +62,7 @@ class Activity extends Component {
} = this.props } = this.props
if (invoiceLoading || paymentLoading) { return <div>Loading...</div> } if (invoiceLoading || paymentLoading) { return <div>Loading...</div> }
if (balance.balanceLoading) { return <LoadingBolt /> }
return ( return (
<div> <div>

4
app/routes/activity/containers/ActivityContainer.js

@ -1,5 +1,6 @@
import { connect } from 'react-redux' import { connect } from 'react-redux'
import { tickerSelectors } from 'reducers/ticker' import { tickerSelectors } from 'reducers/ticker'
import { fetchBalance } from 'reducers/balance'
import { import {
fetchInvoices, fetchInvoices,
searchInvoices, searchInvoices,
@ -34,7 +35,8 @@ const mapDispatchToProps = {
hideActivityModal, hideActivityModal,
changeFilter, changeFilter,
toggleFilterPulldown, toggleFilterPulldown,
newAddress newAddress,
fetchBalance
} }
const mapStateToProps = state => ({ const mapStateToProps = state => ({

5
app/routes/app/components/App.js

@ -9,10 +9,9 @@ import styles from './App.scss'
class App extends Component { class App extends Component {
componentWillMount() { componentWillMount() {
const { fetchTicker, fetchBalance, fetchInfo, newAddress } = this.props const { fetchTicker, fetchInfo, newAddress } = this.props
fetchTicker() fetchTicker()
fetchBalance()
fetchInfo() fetchInfo()
newAddress('p2pkh') newAddress('p2pkh')
} }
@ -37,7 +36,7 @@ class App extends Component {
children children
} = this.props } = this.props
if (!currentTicker || balance.balanceLoading) { return <LoadingBolt /> } if (!currentTicker) { return <LoadingBolt /> }
return ( return (
<div> <div>

36
app/routes/network/components/Network.js

@ -19,13 +19,35 @@ class Network extends Component {
fetchDescribeNetwork() fetchDescribeNetwork()
} }
componentDidUpdate(prevProps) {
const { payReqIsLn, network: { pay_req }, fetchInvoiceAndQueryRoutes, clearQueryRoutes } = this.props
// If LN go retrieve invoice details
if ((prevProps.network.pay_req !== pay_req) && payReqIsLn) {
fetchInvoiceAndQueryRoutes(pay_req)
}
if (prevProps.payReqIsLn && !payReqIsLn) {
clearQueryRoutes()
}
}
componentWillUnmount() {
const { clearQueryRoutes, resetPayReq } = this.props
clearQueryRoutes()
resetPayReq()
}
render() { render() {
const { const {
setCurrentTab, setCurrentTab,
updateSelectedPeers, updateSelectedPeers,
setCurrentRoute,
network, network,
selectedPeerPubkeys, selectedPeerPubkeys,
currentRouteChanIds,
peers: { peers }, peers: { peers },
@ -33,6 +55,8 @@ class Network extends Component {
selectedChannelIds, selectedChannelIds,
updateSelectedChannels, updateSelectedChannels,
updatePayReq,
identity_pubkey identity_pubkey
} = this.props } = this.props
@ -45,7 +69,16 @@ class Network extends Component {
return <ChannelsList channels={activeChannels} updateSelectedChannels={updateSelectedChannels} selectedChannelIds={selectedChannelIds} /> return <ChannelsList channels={activeChannels} updateSelectedChannels={updateSelectedChannels} selectedChannelIds={selectedChannelIds} />
break break
case 3: case 3:
return <TransactionForm /> return (
<TransactionForm
updatePayReq={updatePayReq}
pay_req={network.pay_req}
loadingRoutes={network.fetchingInvoiceAndQueryingRoutes}
payReqRoutes={network.payReqRoutes}
setCurrentRoute={setCurrentRoute}
currentRoute={network.currentRoute}
/>
)
break break
} }
} }
@ -58,6 +91,7 @@ class Network extends Component {
identity_pubkey={identity_pubkey} identity_pubkey={identity_pubkey}
selectedPeerPubkeys={selectedPeerPubkeys} selectedPeerPubkeys={selectedPeerPubkeys}
selectedChannelIds={selectedChannelIds} selectedChannelIds={selectedChannelIds}
currentRouteChanIds={currentRouteChanIds}
/> />
<section className={styles.toolbox}> <section className={styles.toolbox}>

1
app/routes/network/components/Network.scss

@ -47,6 +47,7 @@
width: 30%; width: 30%;
height: 100%; height: 100%;
background: #353535; background: #353535;
overflow-y: scroll;
} }
.tabs { .tabs {

14
app/routes/network/containers/NetworkContainer.js

@ -7,6 +7,13 @@ import {
setCurrentTab, setCurrentTab,
updateSelectedPeers, updateSelectedPeers,
updateSelectedChannels, updateSelectedChannels,
setCurrentRoute,
updatePayReq,
resetPayReq,
fetchInvoiceAndQueryRoutes,
clearQueryRoutes,
networkSelectors networkSelectors
} from '../../../reducers/network' } from '../../../reducers/network'
@ -19,6 +26,11 @@ const mapDispatchToProps = {
fetchDescribeNetwork, fetchDescribeNetwork,
setCurrentTab, setCurrentTab,
updateSelectedPeers, updateSelectedPeers,
updatePayReq,
fetchInvoiceAndQueryRoutes,
setCurrentRoute,
clearQueryRoutes,
resetPayReq,
fetchPeers, fetchPeers,
@ -33,6 +45,8 @@ const mapStateToProps = state => ({
selectedPeerPubkeys: networkSelectors.selectedPeerPubkeys(state), selectedPeerPubkeys: networkSelectors.selectedPeerPubkeys(state),
selectedChannelIds: networkSelectors.selectedChannelIds(state), selectedChannelIds: networkSelectors.selectedChannelIds(state),
payReqIsLn: networkSelectors.payReqIsLn(state),
currentRouteChanIds: networkSelectors.currentRouteChanIds(state),
activeChannels: channelsSelectors.activeChannels(state) activeChannels: channelsSelectors.activeChannels(state)
}) })

Loading…
Cancel
Save