From 31e178a1fc250335687b2c76a3e5853e04147fdc Mon Sep 17 00:00:00 2001 From: jamaljsr Date: Fri, 31 Aug 2018 12:44:07 -0400 Subject: [PATCH] feat(channels): warn when opening multiple channels to the same node --- app/components/Contacts/SubmitChannelForm.js | 26 ++++++++++++++ .../Contacts/SubmitChannelForm.scss | 26 ++++++++++++++ app/reducers/contactsform.js | 36 +++++++++++++++++++ app/routes/app/containers/AppContainer.js | 2 ++ 4 files changed, 90 insertions(+) diff --git a/app/components/Contacts/SubmitChannelForm.js b/app/components/Contacts/SubmitChannelForm.js index fc38db48..63095d63 100644 --- a/app/components/Contacts/SubmitChannelForm.js +++ b/app/components/Contacts/SubmitChannelForm.js @@ -2,6 +2,7 @@ import React from 'react' import PropTypes from 'prop-types' import FaAngleDown from 'react-icons/lib/fa/angle-down' +import FaExclamationCircle from 'react-icons/lib/fa/exclamation-circle' import AmountInput from 'components/AmountInput' import styles from './SubmitChannelForm.scss' @@ -17,6 +18,7 @@ class SubmitChannelForm extends React.Component { updateContactCapacity, openChannel, fiatTicker, + dupeChanInfo, ticker, @@ -40,6 +42,22 @@ class SubmitChannelForm extends React.Component { return node.pub_key } + const renderWarning = dupeChanInfo => { + const { alias, activeChannels, capacity, currencyName } = dupeChanInfo + + const chansMsg = + activeChannels === 1 ? ' an active channel ' : ` ${activeChannels} active channels ` + const aliasMsg = alias ? {alias} : ' this node ' + + return ( +

+ {`You currently have ${chansMsg} open to `} + {aliasMsg} + {` with a capacity of ${capacity} ${currencyName}.`} +

+ ) + } + const formSubmitted = () => { // dont submit to LND if they havent set channel capacity amount if (contactCapacity <= 0) { @@ -75,6 +93,13 @@ class SubmitChannelForm extends React.Component {

{renderTitle()}

+ {dupeChanInfo && ( +
+ + {renderWarning(dupeChanInfo)} +
+ )} +
state.contactsform.manualSearchQuery const contactCapacitySelector = state => state.contactsform.contactCapacity const currencySelector = state => state.ticker.currency const fiatTickerSelector = state => state.ticker.fiatTicker +const nodeSelector = state => state.contactsform.node +const channelsSelector = state => state.channels.channels const contactable = node => node.addresses.length > 0 @@ -285,6 +287,40 @@ contactFormSelectors.contactFormFiatAmount = createSelector( } ) +// compose warning info when a channel is being created with a node that +// already has one or more active channels open +contactFormSelectors.dupeChanInfo = createSelector( + channelsSelector, + nodeSelector, + networkNodesSelector, + currencySelector, + tickerSelectors.currencyName, + (activeChannels, newNode, allNodes, currency, currencyName) => { + const chans = activeChannels.filter( + chan => chan.active && chan.remote_pubkey === newNode.pub_key + ) + + if (!chans.length) { + return null + } + + const node = allNodes.filter(node => node.pub_key === newNode.pub_key)[0] + // use the alias unless its the first 20 chars of the pub_key + const alias = + node && node.alias !== node.pub_key.substring(0, node.alias.length) ? node.alias : null + + const totalSats = chans.reduce((agg, chan) => agg + parseInt(chan.capacity, 10), 0) + const capacity = parseFloat(btc.convert('sats', currency, totalSats)) + + return { + alias, + activeChannels: chans.length, + capacity, + currencyName + } + } +) + export { contactFormSelectors } // ------------------------------------ diff --git a/app/routes/app/containers/AppContainer.js b/app/routes/app/containers/AppContainer.js index aa0b0732..56b8ad74 100644 --- a/app/routes/app/containers/AppContainer.js +++ b/app/routes/app/containers/AppContainer.js @@ -183,6 +183,7 @@ const mapStateToProps = state => ({ showManualForm: contactFormSelectors.showManualForm(state), manualFormIsValid: contactFormSelectors.manualFormIsValid(state), contactFormFiatAmount: contactFormSelectors.contactFormFiatAmount(state), + dupeChanInfo: contactFormSelectors.dupeChanInfo(state), currentChannels: currentChannels(state), activeChannelPubkeys: channelsSelectors.activeChannelPubkeys(state), @@ -408,6 +409,7 @@ const mergeProps = (stateProps, dispatchProps, ownProps) => { node: stateProps.contactsform.node, contactCapacity: stateProps.contactsform.contactCapacity, fiatTicker: stateProps.ticker.fiatTicker, + dupeChanInfo: stateProps.dupeChanInfo, updateContactCapacity: dispatchProps.updateContactCapacity,