Jack Mallers
7 years ago
63 changed files with 97 additions and 3454 deletions
@ -1,90 +0,0 @@ |
|||||
import React from 'react' |
|
||||
import PropTypes from 'prop-types' |
|
||||
import ReactModal from 'react-modal' |
|
||||
|
|
||||
import { FaClose } from 'react-icons/lib/fa' |
|
||||
|
|
||||
import StepOne from './StepOne' |
|
||||
import StepTwo from './StepTwo' |
|
||||
import StepThree from './StepThree' |
|
||||
import StepFour from './StepFour' |
|
||||
import Footer from './Footer' |
|
||||
|
|
||||
import styles from './ChannelForm.scss' |
|
||||
|
|
||||
const ChannelForm = ({ |
|
||||
channelform, |
|
||||
openChannel, |
|
||||
closeChannelForm, |
|
||||
changeStep, |
|
||||
setNodeKey, |
|
||||
setLocalAmount, |
|
||||
setPushAmount, |
|
||||
channelFormHeader, |
|
||||
channelFormProgress, |
|
||||
stepTwoIsValid, |
|
||||
peers |
|
||||
}) => { |
|
||||
const renderStep = () => { |
|
||||
const { step } = channelform |
|
||||
|
|
||||
switch (step) { |
|
||||
case 1: |
|
||||
return <StepOne peers={peers} changeStep={changeStep} setNodeKey={setNodeKey} /> |
|
||||
case 2: |
|
||||
return <StepTwo local_amt={channelform.local_amt} setLocalAmount={setLocalAmount} /> |
|
||||
case 3: |
|
||||
return <StepThree push_amt={channelform.push_amt} setPushAmount={setPushAmount} /> |
|
||||
default: |
|
||||
return <StepFour node_key={channelform.node_key} local_amt={channelform.local_amt} push_amt={channelform.push_amt} /> |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
return ( |
|
||||
<ReactModal |
|
||||
isOpen={channelform.isOpen} |
|
||||
ariaHideApp |
|
||||
shouldCloseOnOverlayClick |
|
||||
contentLabel='No Overlay Click Modal' |
|
||||
onRequestClose={closeChannelForm} |
|
||||
parentSelector={() => document.body} |
|
||||
className={styles.modal} |
|
||||
> |
|
||||
<div onClick={closeChannelForm} className={styles.modalClose}> |
|
||||
<FaClose /> |
|
||||
</div> |
|
||||
|
|
||||
<header className={styles.header}> |
|
||||
<h3>{channelFormHeader}</h3> |
|
||||
<div className={styles.progress} style={{ width: `${channelFormProgress}%` }} /> |
|
||||
</header> |
|
||||
|
|
||||
<div className={styles.content}> |
|
||||
{renderStep()} |
|
||||
</div> |
|
||||
|
|
||||
<Footer |
|
||||
step={channelform.step} |
|
||||
changeStep={changeStep} |
|
||||
stepTwoIsValid={stepTwoIsValid} |
|
||||
submit={() => openChannel({ pubkey: channelform.node_key, local_amt: channelform.local_amt, push_amt: channelform.push_amt })} |
|
||||
/> |
|
||||
</ReactModal> |
|
||||
) |
|
||||
} |
|
||||
|
|
||||
ChannelForm.propTypes = { |
|
||||
channelform: PropTypes.object.isRequired, |
|
||||
openChannel: PropTypes.func.isRequired, |
|
||||
closeChannelForm: PropTypes.func.isRequired, |
|
||||
changeStep: PropTypes.func.isRequired, |
|
||||
setNodeKey: PropTypes.func.isRequired, |
|
||||
setLocalAmount: PropTypes.func.isRequired, |
|
||||
setPushAmount: PropTypes.func.isRequired, |
|
||||
channelFormHeader: PropTypes.string.isRequired, |
|
||||
channelFormProgress: PropTypes.number.isRequired, |
|
||||
stepTwoIsValid: PropTypes.bool.isRequired, |
|
||||
peers: PropTypes.array.isRequired |
|
||||
} |
|
||||
|
|
||||
export default ChannelForm |
|
@ -1,57 +0,0 @@ |
|||||
@import '../../variables.scss'; |
|
||||
|
|
||||
.modal { |
|
||||
width: 40%; |
|
||||
margin: 50px auto; |
|
||||
position: absolute; |
|
||||
top: auto; |
|
||||
left: 20%; |
|
||||
right: 0; |
|
||||
bottom: auto; |
|
||||
background: $white; |
|
||||
outline: none; |
|
||||
z-index: -2; |
|
||||
border: 1px solid $darkgrey; |
|
||||
} |
|
||||
|
|
||||
.modalClose { |
|
||||
position: absolute; |
|
||||
top: -13px; |
|
||||
right: -13px; |
|
||||
display: block; |
|
||||
font-size: 16px; |
|
||||
line-height: 27px; |
|
||||
width: 32px; |
|
||||
height: 32px; |
|
||||
background: $white; |
|
||||
border-radius: 50%; |
|
||||
color: $darkestgrey; |
|
||||
cursor: pointer; |
|
||||
text-align: center; |
|
||||
z-index: 2; |
|
||||
transition: all 0.25s; |
|
||||
} |
|
||||
|
|
||||
.modalClose:hover { |
|
||||
background: $darkgrey; |
|
||||
} |
|
||||
|
|
||||
.header { |
|
||||
padding: 20px; |
|
||||
background: $lightgrey; |
|
||||
text-align: center; |
|
||||
font-family: 'Jigsaw Light'; |
|
||||
text-transform: uppercase; |
|
||||
position: relative; |
|
||||
z-index: -2; |
|
||||
} |
|
||||
|
|
||||
.progress { |
|
||||
transition: all 0.2s ease; |
|
||||
background: $main; |
|
||||
position: absolute; |
|
||||
height: 100%; |
|
||||
top: 0; |
|
||||
left: 0; |
|
||||
z-index: -1; |
|
||||
} |
|
@ -1,46 +0,0 @@ |
|||||
import React from 'react' |
|
||||
import PropTypes from 'prop-types' |
|
||||
import styles from './Footer.scss' |
|
||||
|
|
||||
const Footer = ({ |
|
||||
step, changeStep, stepTwoIsValid, submit |
|
||||
}) => { |
|
||||
if (step === 1) { return null } |
|
||||
|
|
||||
// See if the next button on step 2 should be active
|
|
||||
const nextIsInactive = step === 2 && !stepTwoIsValid |
|
||||
|
|
||||
// Function that's called when the user clicks "next" in the form
|
|
||||
const nextFunc = () => { |
|
||||
if (nextIsInactive) { return } |
|
||||
|
|
||||
changeStep(step + 1) |
|
||||
} |
|
||||
|
|
||||
const rightButtonText = step === 4 ? 'Submit' : 'Next' |
|
||||
const rightButtonOnClick = step === 4 ? () => submit() : nextFunc |
|
||||
|
|
||||
return ( |
|
||||
<div className={styles.footer}> |
|
||||
<div className='buttonContainer'> |
|
||||
<div className='buttonPrimary' onClick={() => changeStep(step - 1)}> |
|
||||
Back |
|
||||
</div> |
|
||||
</div> |
|
||||
<div className='buttonContainer' onClick={rightButtonOnClick}> |
|
||||
<div className={`buttonPrimary ${nextIsInactive && 'inactive'}`}> |
|
||||
{rightButtonText} |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
) |
|
||||
} |
|
||||
|
|
||||
Footer.propTypes = { |
|
||||
step: PropTypes.number.isRequired, |
|
||||
changeStep: PropTypes.func.isRequired, |
|
||||
stepTwoIsValid: PropTypes.bool.isRequired, |
|
||||
submit: PropTypes.func.isRequired |
|
||||
} |
|
||||
|
|
||||
export default Footer |
|
@ -1,17 +0,0 @@ |
|||||
@import '../../variables.scss'; |
|
||||
|
|
||||
.footer { |
|
||||
display: flex; |
|
||||
flex-direction: row; |
|
||||
justify-content: space-between; |
|
||||
padding-bottom: 30px; |
|
||||
|
|
||||
div { |
|
||||
margin: 0 20px; |
|
||||
|
|
||||
div { |
|
||||
padding: 18px 60px 15px 60px; |
|
||||
color: $black; |
|
||||
} |
|
||||
} |
|
||||
} |
|
@ -1,37 +0,0 @@ |
|||||
import React from 'react' |
|
||||
import PropTypes from 'prop-types' |
|
||||
import styles from './StepFour.scss' |
|
||||
|
|
||||
const StepFour = ({ node_key, local_amt, push_amt }) => ( |
|
||||
<div className={styles.container}> |
|
||||
<div className={styles.nodekey}> |
|
||||
<h4>Peer</h4> |
|
||||
<h2>{node_key}</h2> |
|
||||
</div> |
|
||||
|
|
||||
<div className={styles.amounts}> |
|
||||
<div className={styles.localamt}> |
|
||||
<h4>Local Amount</h4> |
|
||||
<h3>{local_amt}</h3> |
|
||||
</div> |
|
||||
<div className={styles.pushamt}> |
|
||||
<h4>Push Amount</h4> |
|
||||
<h3>{push_amt}</h3> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
) |
|
||||
|
|
||||
StepFour.propTypes = { |
|
||||
node_key: PropTypes.string.isRequired, |
|
||||
local_amt: PropTypes.oneOfType([ |
|
||||
PropTypes.number, |
|
||||
PropTypes.string |
|
||||
]), |
|
||||
push_amt: PropTypes.oneOfType([ |
|
||||
PropTypes.number, |
|
||||
PropTypes.string |
|
||||
]) |
|
||||
} |
|
||||
|
|
||||
export default StepFour |
|
@ -1,36 +0,0 @@ |
|||||
@import '../../variables.scss'; |
|
||||
|
|
||||
.container { |
|
||||
padding: 50px; |
|
||||
|
|
||||
h4 { |
|
||||
text-transform: uppercase; |
|
||||
font-size: 14px; |
|
||||
margin-bottom: 10px; |
|
||||
} |
|
||||
|
|
||||
h3 { |
|
||||
text-align: center; |
|
||||
color: $main; |
|
||||
font-size: 50px; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.nodekey { |
|
||||
margin-bottom: 50px; |
|
||||
padding: 20px; |
|
||||
border-bottom: 1px solid $main; |
|
||||
|
|
||||
h2 { |
|
||||
font-size: 12px; |
|
||||
font-weight: bold; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.amounts { |
|
||||
display: flex; |
|
||||
flex-direction: row; |
|
||||
justify-content: space-around; |
|
||||
margin-bottom: 50px; |
|
||||
padding: 20px; |
|
||||
} |
|
@ -1,74 +0,0 @@ |
|||||
import React, { Component } from 'react' |
|
||||
import PropTypes from 'prop-types' |
|
||||
import { MdSearch } from 'react-icons/lib/md' |
|
||||
import styles from './StepOne.scss' |
|
||||
|
|
||||
class StepOne extends Component { |
|
||||
constructor(props) { |
|
||||
super(props) |
|
||||
this.state = { |
|
||||
peers: props.peers, |
|
||||
searchQuery: '' |
|
||||
} |
|
||||
|
|
||||
this.onSearchQuery = this.onSearchQuery.bind(this) |
|
||||
this.peerClicked = this.peerClicked.bind(this) |
|
||||
} |
|
||||
|
|
||||
onSearchQuery(searchQuery) { |
|
||||
const peers = this.props.peers.filter(peer => peer.pub_key.includes(searchQuery)) |
|
||||
|
|
||||
this.setState({ peers, searchQuery }) |
|
||||
} |
|
||||
|
|
||||
peerClicked(peer) { |
|
||||
const { setNodeKey, changeStep } = this.props |
|
||||
|
|
||||
setNodeKey(peer.pub_key) |
|
||||
changeStep(2) |
|
||||
} |
|
||||
|
|
||||
render() { |
|
||||
const { peers, searchQuery } = this.state |
|
||||
|
|
||||
return ( |
|
||||
<div> |
|
||||
<div className={styles.search}> |
|
||||
<label className={`${styles.label} ${styles.input}`} htmlFor='peersSearch'> |
|
||||
<MdSearch /> |
|
||||
</label> |
|
||||
<input |
|
||||
value={searchQuery} |
|
||||
onChange={event => this.onSearchQuery(event.target.value)} |
|
||||
className={`${styles.text} ${styles.input}`} |
|
||||
placeholder='Search your peers by their public key' |
|
||||
type='text' |
|
||||
id='peersSearch' |
|
||||
/> |
|
||||
</div> |
|
||||
|
|
||||
<ul className={styles.peers}> |
|
||||
{peers.length > 0 && |
|
||||
peers.map(peer => ( |
|
||||
<li |
|
||||
key={peer.peer_id} |
|
||||
className={styles.peer} |
|
||||
onClick={() => this.peerClicked(peer)} |
|
||||
> |
|
||||
<h4>{peer.address}</h4> |
|
||||
<h1>{peer.pub_key}</h1> |
|
||||
</li> |
|
||||
))} |
|
||||
</ul> |
|
||||
</div> |
|
||||
) |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
StepOne.propTypes = { |
|
||||
peers: PropTypes.array.isRequired, |
|
||||
setNodeKey: PropTypes.func.isRequired, |
|
||||
changeStep: PropTypes.func.isRequired |
|
||||
} |
|
||||
|
|
||||
export default StepOne |
|
@ -1,74 +0,0 @@ |
|||||
@import '../../variables.scss'; |
|
||||
|
|
||||
.peers { |
|
||||
h2 { |
|
||||
text-transform: uppercase; |
|
||||
font-weight: 200; |
|
||||
padding: 10px 0; |
|
||||
border-bottom: 1px solid $grey; |
|
||||
color: $darkestgrey; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.search { |
|
||||
height: 50px; |
|
||||
padding: 2px; |
|
||||
border-bottom: 1px solid $darkgrey; |
|
||||
|
|
||||
.input { |
|
||||
display: inline-block; |
|
||||
vertical-align: top; |
|
||||
height: 100%; |
|
||||
} |
|
||||
|
|
||||
.label { |
|
||||
width: 5%; |
|
||||
line-height: 50px; |
|
||||
font-size: 16px; |
|
||||
text-align: center; |
|
||||
cursor: pointer; |
|
||||
} |
|
||||
|
|
||||
.text { |
|
||||
width: 95%; |
|
||||
outline: 0; |
|
||||
padding: 0; |
|
||||
border: 0; |
|
||||
border-radius: 0; |
|
||||
height: 50px; |
|
||||
font-size: 16px; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.peer { |
|
||||
position: relative; |
|
||||
background: $white; |
|
||||
padding: 10px; |
|
||||
border-top: 1px solid $grey; |
|
||||
cursor: pointer; |
|
||||
transition: all 0.25s; |
|
||||
|
|
||||
&:hover { |
|
||||
opacity: 0.5; |
|
||||
} |
|
||||
|
|
||||
&:first-child { |
|
||||
border: none; |
|
||||
} |
|
||||
|
|
||||
h4, h1 { |
|
||||
margin: 10px 0; |
|
||||
} |
|
||||
|
|
||||
h4 { |
|
||||
font-size: 12px; |
|
||||
font-weight: bold; |
|
||||
color: $black; |
|
||||
} |
|
||||
|
|
||||
h1 { |
|
||||
font-size: 14px; |
|
||||
font-weight: 200; |
|
||||
color: $main; |
|
||||
} |
|
||||
} |
|
@ -1,50 +0,0 @@ |
|||||
import React, { Component } from 'react' |
|
||||
import PropTypes from 'prop-types' |
|
||||
import CurrencyIcon from 'components/CurrencyIcon' |
|
||||
import styles from './StepThree.scss' |
|
||||
|
|
||||
class StepThree extends Component { |
|
||||
render() { |
|
||||
const { push_amt, setPushAmount } = this.props |
|
||||
|
|
||||
return ( |
|
||||
<div className={styles.container}> |
|
||||
<div className={styles.explainer}> |
|
||||
<h2>Push Amount</h2> |
|
||||
<p> |
|
||||
The push amount is the amount of bitcoin (if any at all) you'd like |
|
||||
to "push" to the other side of the channel when it opens. |
|
||||
This amount will be set on the remote side of the channel as part of the initial commitment state. |
|
||||
</p> |
|
||||
</div> |
|
||||
|
|
||||
<form> |
|
||||
<label htmlFor='amount'> |
|
||||
<CurrencyIcon currency='btc' crypto='btc' /> |
|
||||
</label> |
|
||||
<input |
|
||||
type='number' |
|
||||
min='0' |
|
||||
max='0.16' |
|
||||
ref={(input) => { this.input = input }} |
|
||||
size='' |
|
||||
value={push_amt} |
|
||||
onChange={event => setPushAmount(event.target.value)} |
|
||||
id='amount' |
|
||||
style={{ width: isNaN((push_amt.length + 1) * 55) ? 140 : (push_amt.length + 1) * 55 }} |
|
||||
/> |
|
||||
</form> |
|
||||
</div> |
|
||||
) |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
StepThree.propTypes = { |
|
||||
push_amt: PropTypes.oneOfType([ |
|
||||
PropTypes.number, |
|
||||
PropTypes.string |
|
||||
]).isRequired, |
|
||||
setPushAmount: PropTypes.func.isRequired |
|
||||
} |
|
||||
|
|
||||
export default StepThree |
|
@ -1,58 +0,0 @@ |
|||||
@import '../../variables.scss'; |
|
||||
|
|
||||
.container { |
|
||||
margin-bottom: 50px; |
|
||||
padding: 20px; |
|
||||
|
|
||||
.explainer { |
|
||||
margin: 0px 0 50px 0; |
|
||||
padding-bottom: 20px; |
|
||||
border-bottom: 1px solid $lightgrey; |
|
||||
|
|
||||
h2 { |
|
||||
margin: 0 0 20px 0; |
|
||||
font-size: 28px; |
|
||||
} |
|
||||
|
|
||||
p { |
|
||||
line-height: 1.5; |
|
||||
font-size: 16px; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
form { |
|
||||
display: flex; |
|
||||
flex-direction: row; |
|
||||
justify-content: center; |
|
||||
align-items: center; |
|
||||
} |
|
||||
|
|
||||
label { |
|
||||
height: 200px; |
|
||||
color: $main; |
|
||||
|
|
||||
svg { |
|
||||
width: 65px; |
|
||||
height: 65px; |
|
||||
} |
|
||||
|
|
||||
svg[data-icon='ltc'] { |
|
||||
margin-right: 10px; |
|
||||
|
|
||||
g { |
|
||||
transform: scale(1.75) translate(-5px, -5px); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
input[type=number] { |
|
||||
color: $main; |
|
||||
width: 30px; |
|
||||
height: 200px; |
|
||||
font-size: 100px; |
|
||||
font-weight: 200; |
|
||||
border: none; |
|
||||
outline: 0; |
|
||||
-webkit-appearance: none; |
|
||||
} |
|
||||
} |
|
@ -1,49 +0,0 @@ |
|||||
import React, { Component } from 'react' |
|
||||
import PropTypes from 'prop-types' |
|
||||
import CurrencyIcon from 'components/CurrencyIcon' |
|
||||
import styles from './StepTwo.scss' |
|
||||
|
|
||||
class StepTwo extends Component { |
|
||||
render() { |
|
||||
const { local_amt, setLocalAmount } = this.props |
|
||||
|
|
||||
return ( |
|
||||
<div className={styles.container}> |
|
||||
<div className={styles.explainer}> |
|
||||
<h2>Local Amount</h2> |
|
||||
<p> |
|
||||
Local amount is the amount of bitcoin that you would like to commit to the channel. |
|
||||
This is the amount that will be sent in an on-chain transaction to open your Lightning channel. |
|
||||
</p> |
|
||||
</div> |
|
||||
|
|
||||
<form> |
|
||||
<label htmlFor='amount'> |
|
||||
<CurrencyIcon currency='btc' crypto='btc' /> |
|
||||
</label> |
|
||||
<input |
|
||||
type='number' |
|
||||
min='0' |
|
||||
max='0.16' |
|
||||
ref={(input) => { this.input = input }} |
|
||||
size='' |
|
||||
value={local_amt} |
|
||||
onChange={event => setLocalAmount(event.target.value)} |
|
||||
id='amount' |
|
||||
style={{ width: isNaN((local_amt.length + 1) * 55) ? 140 : (local_amt.length + 1) * 55 }} |
|
||||
/> |
|
||||
</form> |
|
||||
</div> |
|
||||
) |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
StepTwo.propTypes = { |
|
||||
local_amt: PropTypes.oneOfType([ |
|
||||
PropTypes.string, |
|
||||
PropTypes.number |
|
||||
]).isRequired, |
|
||||
setLocalAmount: PropTypes.func.isRequired |
|
||||
} |
|
||||
|
|
||||
export default StepTwo |
|
@ -1,58 +0,0 @@ |
|||||
@import '../../variables.scss'; |
|
||||
|
|
||||
.container { |
|
||||
margin-bottom: 50px; |
|
||||
padding: 20px; |
|
||||
|
|
||||
.explainer { |
|
||||
margin: 0px 0 50px 0; |
|
||||
padding-bottom: 20px; |
|
||||
border-bottom: 1px solid $lightgrey; |
|
||||
|
|
||||
h2 { |
|
||||
margin: 0 0 20px 0; |
|
||||
font-size: 28px; |
|
||||
} |
|
||||
|
|
||||
p { |
|
||||
line-height: 1.5; |
|
||||
font-size: 16px; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
form { |
|
||||
display: flex; |
|
||||
flex-direction: row; |
|
||||
justify-content: center; |
|
||||
align-items: center; |
|
||||
} |
|
||||
|
|
||||
label { |
|
||||
height: 200px; |
|
||||
color: $main; |
|
||||
|
|
||||
svg { |
|
||||
width: 65px; |
|
||||
height: 65px; |
|
||||
} |
|
||||
|
|
||||
svg[data-icon='ltc'] { |
|
||||
margin-right: 10px; |
|
||||
|
|
||||
g { |
|
||||
transform: scale(1.75) translate(-5px, -5px); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
input[type=number] { |
|
||||
color: $main; |
|
||||
width: 30px; |
|
||||
height: 200px; |
|
||||
font-size: 100px; |
|
||||
font-weight: 200; |
|
||||
border: none; |
|
||||
outline: 0; |
|
||||
-webkit-appearance: none; |
|
||||
} |
|
||||
} |
|
@ -1,3 +0,0 @@ |
|||||
import ChannelForm from './ChannelForm' |
|
||||
|
|
||||
export default ChannelForm |
|
@ -1,95 +0,0 @@ |
|||||
import React from 'react' |
|
||||
import PropTypes from 'prop-types' |
|
||||
import { FaCircle } from 'react-icons/lib/fa' |
|
||||
import { btc } from 'utils' |
|
||||
import styles from './Channel.scss' |
|
||||
|
|
||||
const Channel = ({ |
|
||||
ticker, channel, closeChannel, currentTicker |
|
||||
}) => ( |
|
||||
<li className={styles.channel}> |
|
||||
<header className={styles.header}> |
|
||||
<div> |
|
||||
<span className={styles.status}>Open</span> |
|
||||
{ |
|
||||
channel.active ? |
|
||||
<span className={styles.active}> |
|
||||
<FaCircle /> |
|
||||
<i>Active</i> |
|
||||
</span> |
|
||||
: |
|
||||
<span className={styles.notactive}> |
|
||||
<FaCircle /> |
|
||||
<i>Not Active</i> |
|
||||
</span> |
|
||||
} |
|
||||
</div> |
|
||||
<div> |
|
||||
<p |
|
||||
className={styles.close} |
|
||||
onClick={() => closeChannel({ channel_point: channel.channel_point })} |
|
||||
> |
|
||||
Close channel |
|
||||
</p> |
|
||||
</div> |
|
||||
</header> |
|
||||
<div className={styles.content}> |
|
||||
<div className={styles.left}> |
|
||||
<section className={styles.remotePubkey}> |
|
||||
<span>Remote Pubkey</span> |
|
||||
<h4>{channel.remote_pubkey}</h4> |
|
||||
</section> |
|
||||
<section className={styles.channelPoint}> |
|
||||
<span>Channel Point</span> |
|
||||
<h4>{channel.channel_point}</h4> |
|
||||
</section> |
|
||||
</div> |
|
||||
<div className={styles.right}> |
|
||||
<section className={styles.capacity}> |
|
||||
<span>Capacity</span> |
|
||||
<h2> |
|
||||
{ |
|
||||
ticker.currency === 'btc' ? |
|
||||
btc.satoshisToBtc(channel.capacity) |
|
||||
: |
|
||||
btc.satoshisToUsd(channel.capacity, currentTicker.price_usd) |
|
||||
} |
|
||||
</h2> |
|
||||
</section> |
|
||||
<div className={styles.balances}> |
|
||||
<section> |
|
||||
<span>Local</span> |
|
||||
<h4> |
|
||||
{ |
|
||||
ticker.currency === 'btc' ? |
|
||||
btc.satoshisToBtc(channel.local_balance) |
|
||||
: |
|
||||
btc.satoshisToUsd(channel.local_balance, currentTicker.price_usd) |
|
||||
} |
|
||||
</h4> |
|
||||
</section> |
|
||||
<section> |
|
||||
<span>Remote</span> |
|
||||
<h4> |
|
||||
{ |
|
||||
ticker.currency === 'btc' ? |
|
||||
btc.satoshisToBtc(channel.remote_balance) |
|
||||
: |
|
||||
btc.satoshisToUsd(channel.remote_balance, currentTicker.price_usd) |
|
||||
} |
|
||||
</h4> |
|
||||
</section> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</li> |
|
||||
) |
|
||||
|
|
||||
Channel.propTypes = { |
|
||||
ticker: PropTypes.object.isRequired, |
|
||||
channel: PropTypes.object.isRequired, |
|
||||
closeChannel: PropTypes.func.isRequired, |
|
||||
currentTicker: PropTypes.object.isRequired |
|
||||
} |
|
||||
|
|
||||
export default Channel |
|
@ -1,125 +0,0 @@ |
|||||
@import '../../variables.scss'; |
|
||||
|
|
||||
.channel { |
|
||||
position: relative; |
|
||||
background: $white; |
|
||||
margin: 5px 0; |
|
||||
padding: 10px; |
|
||||
border-top: 1px solid $white; |
|
||||
cursor: pointer; |
|
||||
transition: all 0.25s; |
|
||||
box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2); |
|
||||
|
|
||||
&:hover { |
|
||||
opacity: 0.75; |
|
||||
box-shadow: 0 8px 16px 0 rgba(0,0,0,0.2); |
|
||||
} |
|
||||
|
|
||||
&:first-child { |
|
||||
border: none; |
|
||||
} |
|
||||
|
|
||||
.header { |
|
||||
display: flex; |
|
||||
flex-direction: row; |
|
||||
justify-content: space-between; |
|
||||
|
|
||||
.status, .active, .notactive { |
|
||||
padding: 10px; |
|
||||
text-transform: uppercase; |
|
||||
font-weight: bold; |
|
||||
font-size: 10px; |
|
||||
} |
|
||||
|
|
||||
.status { |
|
||||
color: $main; |
|
||||
} |
|
||||
|
|
||||
.active i, .notactive i { |
|
||||
margin-left: 5px; |
|
||||
} |
|
||||
|
|
||||
.active { |
|
||||
color: $green; |
|
||||
} |
|
||||
|
|
||||
.notactive { |
|
||||
color: $red; |
|
||||
} |
|
||||
|
|
||||
.close { |
|
||||
padding: 10px; |
|
||||
font-size: 10px; |
|
||||
text-transform: uppercase; |
|
||||
color: $red; |
|
||||
cursor: pointer; |
|
||||
|
|
||||
&:hover { |
|
||||
color: lighten($red, 10%); |
|
||||
text-decoration: underline; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.content { |
|
||||
display: flex; |
|
||||
flex-direction: row; |
|
||||
justify-content: space-between; |
|
||||
} |
|
||||
|
|
||||
|
|
||||
.left, .right { |
|
||||
padding: 0 10px; |
|
||||
margin-bottom: 5; |
|
||||
|
|
||||
section { |
|
||||
margin-bottom: 20px; |
|
||||
|
|
||||
span { |
|
||||
text-transform: uppercase; |
|
||||
letter-spacing: 1.6px; |
|
||||
color: $black; |
|
||||
font-size: 10px; |
|
||||
font-weight: bold; |
|
||||
} |
|
||||
|
|
||||
h2 { |
|
||||
font-size: 30px; |
|
||||
padding: 5px 0; |
|
||||
color: $main; |
|
||||
} |
|
||||
|
|
||||
h4 { |
|
||||
margin-top: 5px; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.left { |
|
||||
flex: 7; |
|
||||
} |
|
||||
|
|
||||
.right { |
|
||||
flex: 3; |
|
||||
|
|
||||
.capacity { |
|
||||
text-align: center; |
|
||||
margin-bottom: 10px; |
|
||||
} |
|
||||
|
|
||||
.balances { |
|
||||
display: flex; |
|
||||
justify-content: space-between; |
|
||||
|
|
||||
section { |
|
||||
flex: 5; |
|
||||
text-align: center; |
|
||||
|
|
||||
h4 { |
|
||||
color: $main; |
|
||||
font-size: 16px; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
@ -1,128 +0,0 @@ |
|||||
import React from 'react' |
|
||||
import PropTypes from 'prop-types' |
|
||||
import ReactModal from 'react-modal' |
|
||||
import { FaUser } from 'react-icons/lib/fa' |
|
||||
import CurrencyIcon from 'components/CurrencyIcon' |
|
||||
import { usd, btc } from 'utils' |
|
||||
import styles from './ChannelForm.scss' |
|
||||
|
|
||||
const ChannelForm = ({ |
|
||||
form, setForm, ticker, peers, openChannel, currentTicker |
|
||||
}) => { |
|
||||
const submitClicked = () => { |
|
||||
const { node_key, local_amt, push_amt } = form |
|
||||
|
|
||||
const localamt = ticker.currency === 'usd' ? btc.btcToSatoshis(usd.usdToBtc(local_amt, currentTicker.price_usd)) : btc.btcToSatoshis(local_amt) |
|
||||
const pushamt = ticker.currency === 'usd' ? btc.btcToSatoshis(usd.usdToBtc(push_amt, currentTicker.price_usd)) : btc.btcToSatoshis(push_amt) |
|
||||
|
|
||||
openChannel({ pubkey: node_key, localamt, pushamt }) |
|
||||
// setForm({ isOpen: false })
|
|
||||
} |
|
||||
|
|
||||
const customStyles = { |
|
||||
overlay: { |
|
||||
cursor: 'pointer', |
|
||||
overflowY: 'auto' |
|
||||
}, |
|
||||
content: { |
|
||||
top: 'auto', |
|
||||
left: '20%', |
|
||||
right: '0', |
|
||||
bottom: 'auto', |
|
||||
width: '40%', |
|
||||
margin: '50px auto', |
|
||||
padding: '40px' |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
return ( |
|
||||
<div> |
|
||||
<ReactModal |
|
||||
isOpen={form.isOpen} |
|
||||
contentLabel='No Overlay Click Modal' |
|
||||
ariaHideApp |
|
||||
shouldCloseOnOverlayClick |
|
||||
onRequestClose={() => setForm({ isOpen: false })} |
|
||||
parentSelector={() => document.body} |
|
||||
style={customStyles} |
|
||||
> |
|
||||
<div className={styles.form}> |
|
||||
<h1 className={styles.title}>Open a new channel</h1> |
|
||||
|
|
||||
<section className={styles.pubkey}> |
|
||||
<label htmlFor='nodekey'><FaUser /></label> |
|
||||
<input |
|
||||
type='text' |
|
||||
size='' |
|
||||
placeholder='Peer public key' |
|
||||
value={form.node_key} |
|
||||
onChange={event => setForm({ node_key: event.target.value })} |
|
||||
id='nodekey' |
|
||||
/> |
|
||||
</section> |
|
||||
<section className={styles.local}> |
|
||||
<label htmlFor='localamount'> |
|
||||
<CurrencyIcon currency={ticker.currency} crypto={ticker.crypto} /> |
|
||||
</label> |
|
||||
<input |
|
||||
type='text' |
|
||||
size='' |
|
||||
placeholder='Local amount' |
|
||||
value={form.local_amt} |
|
||||
onChange={event => setForm({ local_amt: event.target.value })} |
|
||||
id='localamount' |
|
||||
/> |
|
||||
</section> |
|
||||
<section className={styles.push}> |
|
||||
<label htmlFor='pushamount'> |
|
||||
<CurrencyIcon currency={ticker.currency} crypto={ticker.crypto} /> |
|
||||
</label> |
|
||||
<input |
|
||||
type='text' |
|
||||
size='' |
|
||||
placeholder='Push amount' |
|
||||
value={form.push_amt} |
|
||||
onChange={event => setForm({ push_amt: event.target.value })} |
|
||||
id='pushamount' |
|
||||
/> |
|
||||
</section> |
|
||||
|
|
||||
<ul className={styles.peers}> |
|
||||
<h2>Connected Peers</h2> |
|
||||
{ |
|
||||
peers.length ? |
|
||||
peers.map(peer => |
|
||||
( |
|
||||
<li |
|
||||
key={peer.peer_id} |
|
||||
className={styles.peer} |
|
||||
onClick={() => setForm({ node_key: peer.pub_key })} |
|
||||
> |
|
||||
<h4>{peer.address}</h4> |
|
||||
<h1>{peer.pub_key}</h1> |
|
||||
</li> |
|
||||
)) |
|
||||
: |
|
||||
null |
|
||||
} |
|
||||
</ul> |
|
||||
|
|
||||
<div className={styles.buttonGroup}> |
|
||||
<div className={styles.button} onClick={submitClicked}>Submit</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</ReactModal> |
|
||||
</div> |
|
||||
) |
|
||||
} |
|
||||
|
|
||||
ChannelForm.propTypes = { |
|
||||
form: PropTypes.object.isRequired, |
|
||||
setForm: PropTypes.func.isRequired, |
|
||||
ticker: PropTypes.object.isRequired, |
|
||||
peers: PropTypes.array.isRequired, |
|
||||
openChannel: PropTypes.func.isRequired, |
|
||||
currentTicker: PropTypes.object.isRequired |
|
||||
} |
|
||||
|
|
||||
export default ChannelForm |
|
@ -1,123 +0,0 @@ |
|||||
@import '../../variables.scss'; |
|
||||
|
|
||||
.title { |
|
||||
text-align: center; |
|
||||
font-size: 24px; |
|
||||
color: $black; |
|
||||
margin-bottom: 50px; |
|
||||
} |
|
||||
|
|
||||
.pubkey, .local, .push { |
|
||||
display: flex; |
|
||||
justify-content: center; |
|
||||
font-size: 18px; |
|
||||
height: auto; |
|
||||
min-height: 55px; |
|
||||
margin-bottom: 20px; |
|
||||
border: 1px solid $traditionalgrey; |
|
||||
border-radius: 6px; |
|
||||
position: relative; |
|
||||
padding: 0 20px; |
|
||||
|
|
||||
label, input[type=text] { |
|
||||
font-size: inherit; |
|
||||
} |
|
||||
|
|
||||
label { |
|
||||
padding-top: 19px; |
|
||||
padding-bottom: 12px; |
|
||||
color: $traditionalgrey; |
|
||||
|
|
||||
svg[data-icon='ltc'] { |
|
||||
width: 18px; |
|
||||
height: 16px; |
|
||||
|
|
||||
g { |
|
||||
transform: scale(1.75) translate(-5px, -5px); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
input[type=text] { |
|
||||
width: 100%; |
|
||||
border: none; |
|
||||
outline: 0; |
|
||||
-webkit-appearance: none; |
|
||||
height: 55px; |
|
||||
padding: 0 10px; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.peers { |
|
||||
margin-bottom: 50px; |
|
||||
|
|
||||
h2 { |
|
||||
text-transform: uppercase; |
|
||||
font-weight: 200; |
|
||||
padding: 10px 0; |
|
||||
border-bottom: 1px solid $grey; |
|
||||
color: $darkestgrey; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.peer { |
|
||||
position: relative; |
|
||||
background: $white; |
|
||||
padding: 10px; |
|
||||
border-top: 1px solid $grey; |
|
||||
cursor: pointer; |
|
||||
transition: all 0.25s; |
|
||||
|
|
||||
&:hover { |
|
||||
opacity: 0.5; |
|
||||
} |
|
||||
|
|
||||
&:first-child { |
|
||||
border: none; |
|
||||
} |
|
||||
|
|
||||
h4, h1 { |
|
||||
margin: 10px 0; |
|
||||
} |
|
||||
|
|
||||
h4 { |
|
||||
font-size: 12px; |
|
||||
font-weight: bold; |
|
||||
color: $black; |
|
||||
} |
|
||||
|
|
||||
h1 { |
|
||||
font-size: 14px; |
|
||||
font-weight: 200; |
|
||||
color: $main; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.buttonGroup { |
|
||||
width: 100%; |
|
||||
display: flex; |
|
||||
flex-direction: row; |
|
||||
border-radius: 6px; |
|
||||
overflow: hidden; |
|
||||
|
|
||||
.button { |
|
||||
cursor: pointer; |
|
||||
height: 55px; |
|
||||
min-height: 55px; |
|
||||
text-transform: none; |
|
||||
font-size: 18px; |
|
||||
transition: opacity .2s ease-out; |
|
||||
background: $main; |
|
||||
color: $white; |
|
||||
border: none; |
|
||||
font-weight: 500; |
|
||||
padding: 0; |
|
||||
width: 100%; |
|
||||
text-align: center; |
|
||||
line-height: 55px; |
|
||||
|
|
||||
&:first-child { |
|
||||
border-right: 1px solid lighten($main, 20%); |
|
||||
} |
|
||||
} |
|
||||
} |
|
@ -1,103 +0,0 @@ |
|||||
import { shell } from 'electron' |
|
||||
import React from 'react' |
|
||||
import PropTypes from 'prop-types' |
|
||||
import ReactModal from 'react-modal' |
|
||||
import styles from './ChannelModal.scss' |
|
||||
|
|
||||
const ChannelModal = ({ |
|
||||
isOpen, resetChannel, channel, explorerLinkBase, closeChannel |
|
||||
}) => { |
|
||||
const customStyles = { |
|
||||
overlay: { |
|
||||
cursor: 'pointer', |
|
||||
overflowY: 'auto' |
|
||||
}, |
|
||||
content: { |
|
||||
top: 'auto', |
|
||||
left: '20%', |
|
||||
right: '0', |
|
||||
bottom: 'auto', |
|
||||
width: '40%', |
|
||||
margin: '50px auto', |
|
||||
padding: '40px' |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
const closeChannelClicked = () => { |
|
||||
closeChannel({ channel_point: channel.channel_point }) |
|
||||
resetChannel(null) |
|
||||
} |
|
||||
|
|
||||
return ( |
|
||||
<ReactModal |
|
||||
isOpen={isOpen} |
|
||||
contentLabel='No Overlay Click Modal' |
|
||||
ariaHideApp |
|
||||
shouldCloseOnOverlayClick |
|
||||
onRequestClose={() => resetChannel(null)} |
|
||||
parentSelector={() => document.body} |
|
||||
style={customStyles} |
|
||||
> |
|
||||
{ |
|
||||
channel ? |
|
||||
<div className={styles.channel}> |
|
||||
<header className={styles.header}> |
|
||||
<h1 data-hint='Remote public key' className='hint--top-left'>{channel.remote_pubkey}</h1> |
|
||||
<h2 |
|
||||
data-hint='Channel point' |
|
||||
className='hint--top-left' |
|
||||
onClick={() => shell.openExternal(`${explorerLinkBase}/tx/${channel.channel_point.split(':')[0]}`)} |
|
||||
> |
|
||||
{channel.channel_point} |
|
||||
</h2> |
|
||||
</header> |
|
||||
|
|
||||
<div className={styles.balances}> |
|
||||
<section className={styles.capacity}> |
|
||||
<h3>{channel.capacity}</h3> |
|
||||
<span>Capacity</span> |
|
||||
</section> |
|
||||
<div className={styles.balance}> |
|
||||
<section className={styles.local}> |
|
||||
<h4>{channel.local_balance}</h4> |
|
||||
<span>Local</span> |
|
||||
</section> |
|
||||
<section className={styles.remote}> |
|
||||
<h4>{channel.remote_balance}</h4> |
|
||||
<span>Remote</span> |
|
||||
</section> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div className={styles.details}> |
|
||||
<dl> |
|
||||
<dt>Sent</dt> |
|
||||
<dd>{channel.total_satoshis_sent}</dd> |
|
||||
<dt>Received</dt> |
|
||||
<dd>{channel.total_satoshis_received}</dd> |
|
||||
<dt>Updates</dt> |
|
||||
<dd>{channel.num_updates}</dd> |
|
||||
</dl> |
|
||||
</div> |
|
||||
<div className={styles.close} onClick={closeChannelClicked}> |
|
||||
<div>Close channel</div> |
|
||||
</div> |
|
||||
<footer className={styles.active}> |
|
||||
<p>{channel.active ? 'Active' : 'Not active'}</p> |
|
||||
</footer> |
|
||||
</div> |
|
||||
: |
|
||||
null |
|
||||
} |
|
||||
</ReactModal> |
|
||||
) |
|
||||
} |
|
||||
|
|
||||
ChannelModal.propTypes = { |
|
||||
isOpen: PropTypes.bool.isRequired, |
|
||||
resetChannel: PropTypes.func.isRequired, |
|
||||
channel: PropTypes.object, |
|
||||
explorerLinkBase: PropTypes.string.isRequired, |
|
||||
closeChannel: PropTypes.func.isRequired |
|
||||
} |
|
||||
|
|
||||
export default ChannelModal |
|
@ -1,124 +0,0 @@ |
|||||
@import '../../variables.scss'; |
|
||||
|
|
||||
.modalChannel { |
|
||||
padding: 40px; |
|
||||
} |
|
||||
|
|
||||
.header { |
|
||||
margin-bottom: 50px; |
|
||||
|
|
||||
h1 { |
|
||||
color: $black; |
|
||||
text-align: center; |
|
||||
margin-bottom: 5px; |
|
||||
font-weight: bold; |
|
||||
} |
|
||||
|
|
||||
h2 { |
|
||||
color: $darkestgrey; |
|
||||
font-size: 14px; |
|
||||
text-align: center; |
|
||||
|
|
||||
&:hover { |
|
||||
color: $main; |
|
||||
text-decoration: underline; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.balances { |
|
||||
.capacity { |
|
||||
text-align: center; |
|
||||
align-items: center; |
|
||||
|
|
||||
h3 { |
|
||||
color: $main; |
|
||||
font-size: 40px; |
|
||||
} |
|
||||
|
|
||||
span { |
|
||||
color: $black; |
|
||||
font-size: 16px; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.balance { |
|
||||
display: flex; |
|
||||
flex-direction: row; |
|
||||
justify-content: space-between; |
|
||||
|
|
||||
.local, .remote { |
|
||||
flex: 5; |
|
||||
padding: 10px 30px; |
|
||||
text-align: center; |
|
||||
|
|
||||
h4 { |
|
||||
font-size: 20px; |
|
||||
color: $main; |
|
||||
} |
|
||||
|
|
||||
span { |
|
||||
color: $black; |
|
||||
font-size: 12px; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.details { |
|
||||
width: 75%; |
|
||||
margin: 20px auto; |
|
||||
|
|
||||
dt { |
|
||||
text-align: left; |
|
||||
float: left; |
|
||||
clear: left; |
|
||||
font-weight: 500; |
|
||||
padding: 20px 35px 19px 0; |
|
||||
color: $black; |
|
||||
font-weight: bold; |
|
||||
} |
|
||||
|
|
||||
dd { |
|
||||
text-align: right; |
|
||||
font-weight: 400; |
|
||||
padding: 19px 0; |
|
||||
margin-left: 0; |
|
||||
border-top: 1px solid $darkgrey; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.close { |
|
||||
text-align: center; |
|
||||
|
|
||||
div { |
|
||||
width: 35%; |
|
||||
margin: 0 auto; |
|
||||
cursor: pointer; |
|
||||
height: 55px; |
|
||||
min-height: 55px; |
|
||||
text-transform: none; |
|
||||
font-size: 18px; |
|
||||
transition: opacity .2s ease-out; |
|
||||
background: $red; |
|
||||
color: $white; |
|
||||
border: none; |
|
||||
font-weight: 500; |
|
||||
padding: 0; |
|
||||
text-align: center; |
|
||||
line-height: 55px; |
|
||||
transition: all 0.25s; |
|
||||
border-radius: 5px; |
|
||||
|
|
||||
&:hover { |
|
||||
background: darken($red, 10%); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.active { |
|
||||
color: $darkestgrey; |
|
||||
text-align: center; |
|
||||
margin-top: 50px; |
|
||||
text-transform: uppercase; |
|
||||
} |
|
@ -1,140 +0,0 @@ |
|||||
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' |
|
||||
import OpenPendingChannel from './OpenPendingChannel' |
|
||||
import ClosedPendingChannel from './ClosedPendingChannel' |
|
||||
import styles from './Channels.scss' |
|
||||
|
|
||||
const Channels = ({ |
|
||||
fetchChannels, |
|
||||
ticker, |
|
||||
peers, |
|
||||
channelsLoading, |
|
||||
modalChannel, |
|
||||
setChannel, |
|
||||
channelModalOpen, |
|
||||
channelForm, |
|
||||
setChannelForm, |
|
||||
allChannels, |
|
||||
openChannel, |
|
||||
closeChannel, |
|
||||
currentTicker, |
|
||||
explorerLinkBase |
|
||||
}) => { |
|
||||
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> |
|
||||
<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 ( |
|
||||
<Channel |
|
||||
key={index} |
|
||||
ticker={ticker} |
|
||||
channel={channel} |
|
||||
setChannel={setChannel} |
|
||||
currentTicker={currentTicker} |
|
||||
closeChannel={closeChannel} |
|
||||
/> |
|
||||
) |
|
||||
}) |
|
||||
: |
|
||||
'Loading...' |
|
||||
} |
|
||||
</ul> |
|
||||
</div> |
|
||||
) |
|
||||
} |
|
||||
|
|
||||
Channels.propTypes = { |
|
||||
fetchChannels: PropTypes.func.isRequired, |
|
||||
ticker: PropTypes.object.isRequired, |
|
||||
peers: PropTypes.array.isRequired, |
|
||||
channelsLoading: PropTypes.bool.isRequired, |
|
||||
modalChannel: PropTypes.object, |
|
||||
setChannel: PropTypes.func.isRequired, |
|
||||
channelModalOpen: PropTypes.bool.isRequired, |
|
||||
channelForm: PropTypes.object.isRequired, |
|
||||
setChannelForm: PropTypes.func.isRequired, |
|
||||
allChannels: PropTypes.array.isRequired, |
|
||||
openChannel: PropTypes.func.isRequired, |
|
||||
closeChannel: PropTypes.func.isRequired, |
|
||||
currentTicker: PropTypes.object.isRequired, |
|
||||
explorerLinkBase: PropTypes.string.isRequired |
|
||||
} |
|
||||
|
|
||||
export default Channels |
|
@ -1,69 +0,0 @@ |
|||||
@import '../../variables.scss'; |
|
||||
|
|
||||
@keyframes spin { |
|
||||
from { |
|
||||
transform: rotate(0deg) |
|
||||
} |
|
||||
|
|
||||
to { |
|
||||
transform: rotate(360deg); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.channels { |
|
||||
width: 75%; |
|
||||
margin: 50px auto; |
|
||||
|
|
||||
.header { |
|
||||
margin-bottom: 10px; |
|
||||
|
|
||||
h3, .openChannel { |
|
||||
display: inline-block; |
|
||||
} |
|
||||
|
|
||||
h3 { |
|
||||
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; |
|
||||
|
|
||||
svg { |
|
||||
padding: 3px; |
|
||||
border-radius: 50%; |
|
||||
border: 1px solid $main; |
|
||||
color: $main; |
|
||||
transition: all 0.25s; |
|
||||
|
|
||||
&:hover { |
|
||||
border-color: darken($main, 10%); |
|
||||
color: darken($main, 10%); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
h3 { |
|
||||
text-transform: uppercase; |
|
||||
color: $darkestgrey; |
|
||||
letter-spacing: 1.6px; |
|
||||
font-size: 14px; |
|
||||
font-weight: 400; |
|
||||
margin-bottom: 10px; |
|
||||
} |
|
||||
} |
|
@ -1,69 +0,0 @@ |
|||||
import { shell } from 'electron' |
|
||||
import React from 'react' |
|
||||
import PropTypes from 'prop-types' |
|
||||
import { btc } from 'utils' |
|
||||
import styles from './ClosedPendingChannel.scss' |
|
||||
|
|
||||
const ClosedPendingChannel = ({ |
|
||||
ticker, channel: { channel, closing_txid }, currentTicker, explorerLinkBase |
|
||||
}) => ( |
|
||||
<li className={styles.channel} onClick={() => shell.openExternal(`${explorerLinkBase}/tx/${closing_txid}`)}> |
|
||||
<h1 className={styles.closing}>Closing Channel...</h1> |
|
||||
<div className={styles.left}> |
|
||||
<section className={styles.remotePubkey}> |
|
||||
<span>Remote Pubkey</span> |
|
||||
<h4>{channel.remote_node_pub}</h4> |
|
||||
</section> |
|
||||
<section className={styles.channelPoint}> |
|
||||
<span>Channel Point</span> |
|
||||
<h4>{channel.channel_point}</h4> |
|
||||
</section> |
|
||||
</div> |
|
||||
<div className={styles.right}> |
|
||||
<section className={styles.capacity}> |
|
||||
<span>Capacity</span> |
|
||||
<h2> |
|
||||
{ |
|
||||
ticker.currency === 'btc' ? |
|
||||
btc.satoshisToBtc(channel.capacity) |
|
||||
: |
|
||||
btc.satoshisToUsd(channel.capacity, currentTicker.price_usd) |
|
||||
} |
|
||||
</h2> |
|
||||
</section> |
|
||||
<div className={styles.balances}> |
|
||||
<section> |
|
||||
<h4> |
|
||||
{ |
|
||||
ticker.currency === 'btc' ? |
|
||||
btc.satoshisToBtc(channel.local_balance) |
|
||||
: |
|
||||
btc.satoshisToUsd(channel.local_balance, currentTicker.price_usd) |
|
||||
} |
|
||||
</h4> |
|
||||
<span>Local</span> |
|
||||
</section> |
|
||||
<section> |
|
||||
<h4> |
|
||||
{ |
|
||||
ticker.currency === 'btc' ? |
|
||||
btc.satoshisToBtc(channel.remote_balance) |
|
||||
: |
|
||||
btc.satoshisToUsd(channel.remote_balance, currentTicker.price_usd) |
|
||||
} |
|
||||
</h4> |
|
||||
<span>Remote</span> |
|
||||
</section> |
|
||||
</div> |
|
||||
</div> |
|
||||
</li> |
|
||||
) |
|
||||
|
|
||||
ClosedPendingChannel.propTypes = { |
|
||||
ticker: PropTypes.object.isRequired, |
|
||||
channel: PropTypes.object.isRequired, |
|
||||
currentTicker: PropTypes.object.isRequired, |
|
||||
explorerLinkBase: PropTypes.string.isRequired |
|
||||
} |
|
||||
|
|
||||
export default ClosedPendingChannel |
|
@ -1,95 +0,0 @@ |
|||||
@import '../../variables.scss'; |
|
||||
|
|
||||
.channel { |
|
||||
position: relative; |
|
||||
background: $white; |
|
||||
padding: 10px; |
|
||||
display: flex; |
|
||||
flex-direction: row; |
|
||||
justify-content: space-between; |
|
||||
border-top: 1px solid $grey; |
|
||||
cursor: pointer; |
|
||||
transition: all 0.25s; |
|
||||
opacity: 0.5; |
|
||||
|
|
||||
&:hover { |
|
||||
opacity: 0.35; |
|
||||
} |
|
||||
|
|
||||
&:first-child { |
|
||||
border: none; |
|
||||
} |
|
||||
|
|
||||
.closing { |
|
||||
color: $red; |
|
||||
position: absolute; |
|
||||
top: 0; |
|
||||
left: 10px; |
|
||||
padding: 10px; |
|
||||
text-transform: uppercase; |
|
||||
font-weight: bold; |
|
||||
font-size: 10px; |
|
||||
} |
|
||||
|
|
||||
.left, .right { |
|
||||
padding: 0 10px; |
|
||||
margin-bottom: 5; |
|
||||
margin-top: 25px; |
|
||||
|
|
||||
section { |
|
||||
margin-bottom: 20px; |
|
||||
|
|
||||
span { |
|
||||
text-transform: uppercase; |
|
||||
letter-spacing: 1.6px; |
|
||||
color: $black; |
|
||||
font-size: 10px; |
|
||||
font-weight: bold; |
|
||||
} |
|
||||
|
|
||||
h2 { |
|
||||
font-size: 30px; |
|
||||
padding: 5px 0; |
|
||||
color: $main; |
|
||||
} |
|
||||
|
|
||||
h4 { |
|
||||
margin-top: 5px; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.left { |
|
||||
flex: 7; |
|
||||
border-right: 1px solid $grey; |
|
||||
} |
|
||||
|
|
||||
.right { |
|
||||
flex: 3; |
|
||||
|
|
||||
.capacity { |
|
||||
text-align: center; |
|
||||
border-bottom: 1px solid $grey; |
|
||||
margin-bottom: 10px; |
|
||||
} |
|
||||
|
|
||||
.balances { |
|
||||
display: flex; |
|
||||
justify-content: space-between; |
|
||||
|
|
||||
section { |
|
||||
flex: 5; |
|
||||
text-align: center; |
|
||||
|
|
||||
h4 { |
|
||||
color: $main; |
|
||||
font-size: 16px; |
|
||||
} |
|
||||
|
|
||||
&:first-child { |
|
||||
border-right: 1px solid $grey; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
@ -1,72 +0,0 @@ |
|||||
import { shell } from 'electron' |
|
||||
import React from 'react' |
|
||||
import PropTypes from 'prop-types' |
|
||||
import { btc } from 'utils' |
|
||||
import styles from './OpenPendingChannel.scss' |
|
||||
|
|
||||
const OpenPendingChannel = ({ |
|
||||
ticker, channel, currentTicker, explorerLinkBase |
|
||||
}) => ( |
|
||||
<li className={styles.channel} onClick={() => shell.openExternal(`${explorerLinkBase}/tx/${channel.channel.channel_point.split(':')[0]}`)}> |
|
||||
<div className={styles.pending}> |
|
||||
<h1>Opening Channel...</h1> |
|
||||
<span>Blocks till open: {channel.blocks_till_open}</span> |
|
||||
</div> |
|
||||
<div className={styles.left}> |
|
||||
<section className={styles.remotePubkey}> |
|
||||
<span>Remote Pubkey</span> |
|
||||
<h4>{channel.channel.remote_node_pub}</h4> |
|
||||
</section> |
|
||||
<section className={styles.channelPoint}> |
|
||||
<span>Channel Point</span> |
|
||||
<h4>{channel.channel.channel_point}</h4> |
|
||||
</section> |
|
||||
</div> |
|
||||
<div className={styles.right}> |
|
||||
<section className={styles.capacity}> |
|
||||
<span>Capacity</span> |
|
||||
<h2> |
|
||||
{ |
|
||||
ticker.currency === 'btc' ? |
|
||||
btc.satoshisToBtc(channel.channel.capacity) |
|
||||
: |
|
||||
btc.satoshisToUsd(channel.channel.capacity, currentTicker.price_usd) |
|
||||
} |
|
||||
</h2> |
|
||||
</section> |
|
||||
<div className={styles.balances}> |
|
||||
<section> |
|
||||
<h4> |
|
||||
{ |
|
||||
ticker.currency === 'btc' ? |
|
||||
btc.satoshisToBtc(channel.channel.local_balance) |
|
||||
: |
|
||||
btc.satoshisToUsd(channel.channel.local_balance, currentTicker.price_usd) |
|
||||
} |
|
||||
</h4> |
|
||||
<span>Local</span> |
|
||||
</section> |
|
||||
<section> |
|
||||
<h4> |
|
||||
{ |
|
||||
ticker.currency === 'btc' ? |
|
||||
btc.satoshisToBtc(channel.channel.remote_balance) |
|
||||
: |
|
||||
btc.satoshisToUsd(channel.channel.remote_balance, currentTicker.price_usd) |
|
||||
} |
|
||||
</h4> |
|
||||
<span>Remote</span> |
|
||||
</section> |
|
||||
</div> |
|
||||
</div> |
|
||||
</li> |
|
||||
) |
|
||||
|
|
||||
OpenPendingChannel.propTypes = { |
|
||||
ticker: PropTypes.object.isRequired, |
|
||||
channel: PropTypes.object.isRequired, |
|
||||
currentTicker: PropTypes.object.isRequired, |
|
||||
explorerLinkBase: PropTypes.string.isRequired |
|
||||
} |
|
||||
|
|
||||
export default OpenPendingChannel |
|
@ -1,98 +0,0 @@ |
|||||
@import '../../variables.scss'; |
|
||||
|
|
||||
.channel { |
|
||||
position: relative; |
|
||||
background: $lightgrey; |
|
||||
padding: 10px; |
|
||||
display: flex; |
|
||||
flex-direction: row; |
|
||||
justify-content: space-between; |
|
||||
border-top: 1px solid $grey; |
|
||||
cursor: pointer; |
|
||||
transition: all 0.25s; |
|
||||
opacity: 0.5; |
|
||||
|
|
||||
.pending { |
|
||||
position: absolute; |
|
||||
top: 0; |
|
||||
left: 10px; |
|
||||
padding: 10px; |
|
||||
text-transform: uppercase; |
|
||||
font-weight: bold; |
|
||||
|
|
||||
h1 { |
|
||||
color: $main; |
|
||||
font-size: 10px; |
|
||||
} |
|
||||
|
|
||||
span { |
|
||||
font-size: 8px; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
&:first-child { |
|
||||
border: none; |
|
||||
} |
|
||||
|
|
||||
.left, .right { |
|
||||
padding: 0 10px; |
|
||||
margin-bottom: 5; |
|
||||
margin-top: 40px; |
|
||||
|
|
||||
section { |
|
||||
margin-bottom: 20px; |
|
||||
|
|
||||
span { |
|
||||
text-transform: uppercase; |
|
||||
letter-spacing: 1.6px; |
|
||||
color: $black; |
|
||||
font-size: 10px; |
|
||||
font-weight: bold; |
|
||||
} |
|
||||
|
|
||||
h2 { |
|
||||
font-size: 30px; |
|
||||
padding: 5px 0; |
|
||||
color: $main; |
|
||||
} |
|
||||
|
|
||||
h4 { |
|
||||
margin-top: 5px; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.left { |
|
||||
flex: 7; |
|
||||
border-right: 1px solid $grey; |
|
||||
} |
|
||||
|
|
||||
.right { |
|
||||
flex: 3; |
|
||||
|
|
||||
.capacity { |
|
||||
text-align: center; |
|
||||
border-bottom: 1px solid $grey; |
|
||||
margin-bottom: 10px; |
|
||||
} |
|
||||
|
|
||||
.balances { |
|
||||
display: flex; |
|
||||
justify-content: space-between; |
|
||||
|
|
||||
section { |
|
||||
flex: 5; |
|
||||
text-align: center; |
|
||||
|
|
||||
h4 { |
|
||||
color: $main; |
|
||||
font-size: 16px; |
|
||||
} |
|
||||
|
|
||||
&:first-child { |
|
||||
border-right: 1px solid $grey; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
@ -1,3 +0,0 @@ |
|||||
import Channels from './Channels' |
|
||||
|
|
||||
export default Channels |
|
@ -1,31 +0,0 @@ |
|||||
import React, { Component } from 'react' |
|
||||
import PropTypes from 'prop-types' |
|
||||
import styles from './Donut.scss' |
|
||||
|
|
||||
const Donut = ({ value, size, strokewidth }) => { |
|
||||
console.log('value: ', value) |
|
||||
console.log('size: ', size) |
|
||||
console.log('strokewidth: ', strokewidth) |
|
||||
|
|
||||
const halfsize = (size * 0.5) |
|
||||
const radius = halfsize - (strokewidth * 0.5) |
|
||||
const circumference = 2 * Math.PI * radius |
|
||||
const strokeval = ((value * circumference) / 100) |
|
||||
const dashval = (`${strokeval} ${circumference}`) |
|
||||
|
|
||||
const trackstyle = { strokeWidth: 5 } |
|
||||
const indicatorstyle = { strokeWidth: strokewidth, strokeDasharray: dashval } |
|
||||
const rotateval = `rotate(-90 ${37.5},${37.5})` |
|
||||
|
|
||||
return ( |
|
||||
<svg width={75} height={75} className={styles.donutchart}> |
|
||||
<circle r={30} cx={37.5} cy={37.5} transform={rotateval} style={trackstyle} className={styles.donutchartTrack} /> |
|
||||
<circle r={30} cx={37.5} cy={37.5} transform={rotateval} style={indicatorstyle} className={styles.donutchartIndicator} /> |
|
||||
</svg> |
|
||||
) |
|
||||
} |
|
||||
|
|
||||
Donut.propTypes = { |
|
||||
} |
|
||||
|
|
||||
export default Donut |
|
@ -1,20 +0,0 @@ |
|||||
@import '../../variables.scss'; |
|
||||
|
|
||||
.donutchartTrack{ |
|
||||
fill: transparent; |
|
||||
stroke: $lightgrey; |
|
||||
stroke-width: 26; |
|
||||
} |
|
||||
.donutchartIndicator { |
|
||||
fill: transparent; |
|
||||
stroke: $main; |
|
||||
stroke-width: 26; |
|
||||
stroke-dasharray: 0 10000; |
|
||||
transition: stroke-dasharray .3s ease; |
|
||||
} |
|
||||
|
|
||||
.donutchart { |
|
||||
margin: 0 auto; |
|
||||
border-radius: 50%; |
|
||||
display: block; |
|
||||
} |
|
@ -1,20 +0,0 @@ |
|||||
import React from 'react' |
|
||||
import PropTypes from 'prop-types' |
|
||||
import styles from './Peer.scss' |
|
||||
|
|
||||
const Peer = ({ peer, setPeer }) => ( |
|
||||
<li className={styles.peer} onClick={() => setPeer(peer)}> |
|
||||
<h4>{peer.address}</h4> |
|
||||
<h1>{peer.pub_key}</h1> |
|
||||
</li> |
|
||||
) |
|
||||
|
|
||||
Peer.propTypes = { |
|
||||
peer: PropTypes.shape({ |
|
||||
address: PropTypes.string.isRequired, |
|
||||
pub_key: PropTypes.string.isRequired |
|
||||
}).isRequired, |
|
||||
setPeer: PropTypes.func.isRequired |
|
||||
} |
|
||||
|
|
||||
export default Peer |
|
@ -1,38 +0,0 @@ |
|||||
@import '../../variables.scss'; |
|
||||
|
|
||||
.peer { |
|
||||
position: relative; |
|
||||
margin: 5px 0; |
|
||||
padding: 10px; |
|
||||
border-top: 1px solid $white; |
|
||||
cursor: pointer; |
|
||||
transition: all 0.25s; |
|
||||
list-style: none; |
|
||||
box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2); |
|
||||
transition: 0.3s; |
|
||||
|
|
||||
&:hover { |
|
||||
opacity: 0.75; |
|
||||
box-shadow: 0 8px 16px 0 rgba(0,0,0,0.2); |
|
||||
} |
|
||||
|
|
||||
&:first-child { |
|
||||
border: none; |
|
||||
} |
|
||||
|
|
||||
h4, h1 { |
|
||||
margin: 10px 0; |
|
||||
} |
|
||||
|
|
||||
h4 { |
|
||||
font-size: 14px; |
|
||||
font-weight: bold; |
|
||||
color: $black; |
|
||||
} |
|
||||
|
|
||||
h1 { |
|
||||
font-size: 18px; |
|
||||
font-weight: 200; |
|
||||
color: $main; |
|
||||
} |
|
||||
} |
|
@ -1,71 +0,0 @@ |
|||||
import React from 'react' |
|
||||
import PropTypes from 'prop-types' |
|
||||
import ReactModal from 'react-modal' |
|
||||
import { FaClose } from 'react-icons/lib/fa' |
|
||||
import styles from './PeerForm.scss' |
|
||||
|
|
||||
const PeerForm = ({ form, setForm, connect }) => { |
|
||||
const submit = () => { |
|
||||
const { pubkey, host } = form |
|
||||
connect({ pubkey, host }) |
|
||||
} |
|
||||
|
|
||||
return ( |
|
||||
<div> |
|
||||
<ReactModal |
|
||||
isOpen={form.isOpen} |
|
||||
contentLabel='No Overlay Click Modal' |
|
||||
ariaHideApp |
|
||||
shouldCloseOnOverlayClick |
|
||||
onRequestClose={() => setForm({ isOpen: false })} |
|
||||
parentSelector={() => document.body} |
|
||||
className={styles.modal} |
|
||||
> |
|
||||
<div onClick={() => setForm({ isOpen: false })} className={styles.modalClose}> |
|
||||
<FaClose /> |
|
||||
</div> |
|
||||
|
|
||||
<div className={styles.form} onKeyPress={event => event.charCode === 13 && submit()}> |
|
||||
<h1 className={styles.title}>Connect to a peer</h1> |
|
||||
|
|
||||
<section className={styles.pubkey}> |
|
||||
<label htmlFor='pubkey'>Pubkey</label> |
|
||||
<input |
|
||||
type='text' |
|
||||
size='' |
|
||||
placeholder='Public key' |
|
||||
value={form.pubkey} |
|
||||
onChange={event => setForm({ pubkey: event.target.value })} |
|
||||
id='pubkey' |
|
||||
/> |
|
||||
</section> |
|
||||
<section className={styles.local}> |
|
||||
<label htmlFor='address'>Address</label> |
|
||||
<input |
|
||||
type='text' |
|
||||
size='' |
|
||||
placeholder='Host address' |
|
||||
value={form.host} |
|
||||
onChange={event => setForm({ host: event.target.value })} |
|
||||
id='address' |
|
||||
/> |
|
||||
</section> |
|
||||
|
|
||||
<div className='buttonContainer' onClick={submit}> |
|
||||
<div className='buttonPrimary'> |
|
||||
Submit |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</ReactModal> |
|
||||
</div> |
|
||||
) |
|
||||
} |
|
||||
|
|
||||
PeerForm.propTypes = { |
|
||||
form: PropTypes.object.isRequired, |
|
||||
setForm: PropTypes.func.isRequired, |
|
||||
connect: PropTypes.func.isRequired |
|
||||
} |
|
||||
|
|
||||
export default PeerForm |
|
@ -1,107 +0,0 @@ |
|||||
@import '../../variables.scss'; |
|
||||
|
|
||||
.modal { |
|
||||
position: relative; |
|
||||
width: 40%; |
|
||||
margin: 50px auto; |
|
||||
padding: 40px; |
|
||||
position: absolute; |
|
||||
top: auto; |
|
||||
left: 20%; |
|
||||
right: 0; |
|
||||
bottom: auto; |
|
||||
background: $white; |
|
||||
outline: none; |
|
||||
z-index: -2; |
|
||||
border: 1px solid $darkgrey; |
|
||||
} |
|
||||
|
|
||||
.modalClose { |
|
||||
position: absolute; |
|
||||
top: -13px; |
|
||||
right: -13px; |
|
||||
display: block; |
|
||||
font-size: 16px; |
|
||||
line-height: 27px; |
|
||||
width: 32px; |
|
||||
height: 32px; |
|
||||
background: $white; |
|
||||
border-radius: 50%; |
|
||||
color: $darkestgrey; |
|
||||
cursor: pointer; |
|
||||
text-align: center; |
|
||||
z-index: 2; |
|
||||
transition: all 0.25s; |
|
||||
} |
|
||||
|
|
||||
.modalClose:hover { |
|
||||
background: $darkgrey; |
|
||||
} |
|
||||
|
|
||||
.title { |
|
||||
text-align: center; |
|
||||
font-size: 24px; |
|
||||
color: $black; |
|
||||
margin-bottom: 50px; |
|
||||
} |
|
||||
|
|
||||
.pubkey, .local, .push { |
|
||||
display: flex; |
|
||||
justify-content: center; |
|
||||
font-size: 18px; |
|
||||
height: auto; |
|
||||
min-height: 55px; |
|
||||
margin-bottom: 20px; |
|
||||
border: 1px solid $traditionalgrey; |
|
||||
border-radius: 6px; |
|
||||
position: relative; |
|
||||
padding: 0 20px; |
|
||||
|
|
||||
label, input[type=text] { |
|
||||
font-size: inherit; |
|
||||
} |
|
||||
|
|
||||
label { |
|
||||
padding-top: 19px; |
|
||||
padding-bottom: 12px; |
|
||||
color: $traditionalgrey; |
|
||||
} |
|
||||
|
|
||||
input[type=text] { |
|
||||
width: 100%; |
|
||||
border: none; |
|
||||
outline: 0; |
|
||||
-webkit-appearance: none; |
|
||||
height: 55px; |
|
||||
padding: 0 10px; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.buttonGroup { |
|
||||
width: 100%; |
|
||||
display: flex; |
|
||||
flex-direction: row; |
|
||||
border-radius: 6px; |
|
||||
overflow: hidden; |
|
||||
|
|
||||
.button { |
|
||||
cursor: pointer; |
|
||||
height: 55px; |
|
||||
min-height: 55px; |
|
||||
text-transform: none; |
|
||||
font-size: 18px; |
|
||||
transition: opacity .2s ease-out; |
|
||||
background: $main; |
|
||||
color: $white; |
|
||||
border: none; |
|
||||
font-weight: 500; |
|
||||
padding: 0; |
|
||||
width: 100%; |
|
||||
text-align: center; |
|
||||
line-height: 55px; |
|
||||
|
|
||||
&:first-child { |
|
||||
border-right: 1px solid lighten($main, 20%); |
|
||||
} |
|
||||
} |
|
||||
} |
|
@ -1,80 +0,0 @@ |
|||||
import React from 'react' |
|
||||
import PropTypes from 'prop-types' |
|
||||
|
|
||||
import ReactModal from 'react-modal' |
|
||||
import { FaClose } from 'react-icons/lib/fa' |
|
||||
|
|
||||
import styles from './PeerModal.scss' |
|
||||
|
|
||||
const PeerModal = ({ |
|
||||
isOpen, resetPeer, peer, disconnect |
|
||||
}) => { |
|
||||
const customStyles = { |
|
||||
overlay: { |
|
||||
cursor: 'pointer', |
|
||||
overflowY: 'auto' |
|
||||
}, |
|
||||
content: { |
|
||||
top: 'auto', |
|
||||
left: '20%', |
|
||||
right: '0', |
|
||||
bottom: 'auto', |
|
||||
width: '40%', |
|
||||
margin: '50px auto', |
|
||||
borderRadius: 'none', |
|
||||
padding: '0' |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
return ( |
|
||||
<ReactModal |
|
||||
isOpen={isOpen} |
|
||||
contentLabel='No Overlay Click Modal' |
|
||||
ariaHideApp |
|
||||
shouldCloseOnOverlayClick |
|
||||
onRequestClose={() => resetPeer(null)} |
|
||||
parentSelector={() => document.body} |
|
||||
style={customStyles} |
|
||||
> |
|
||||
<div className={styles.closeContainer}> |
|
||||
<span onClick={() => resetPeer(null)}> |
|
||||
<FaClose /> |
|
||||
</span> |
|
||||
</div> |
|
||||
{ |
|
||||
peer && |
|
||||
<div className={styles.peer}> |
|
||||
<header className={styles.header}> |
|
||||
<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> |
|
||||
</header> |
|
||||
|
|
||||
<div className={styles.details}> |
|
||||
<dl> |
|
||||
<dt>Satoshis Received</dt> |
|
||||
<dd>{peer.sat_recv}</dd> |
|
||||
<dt>Satoshis Sent</dt> |
|
||||
<dd>{peer.sat_sent}</dd> |
|
||||
<dt>Bytes Received</dt> |
|
||||
<dd>{peer.bytes_recv}</dd> |
|
||||
<dt>Bytes Sent</dt> |
|
||||
<dd>{peer.bytes_sent}</dd> |
|
||||
</dl> |
|
||||
</div> |
|
||||
<div className={styles.close} onClick={() => disconnect({ pubkey: peer.pub_key })}> |
|
||||
<div>Disconnect peer</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
} |
|
||||
</ReactModal> |
|
||||
) |
|
||||
} |
|
||||
|
|
||||
PeerModal.propTypes = { |
|
||||
isOpen: PropTypes.bool.isRequired, |
|
||||
resetPeer: PropTypes.func.isRequired, |
|
||||
peer: PropTypes.object, |
|
||||
disconnect: PropTypes.func.isRequired |
|
||||
} |
|
||||
|
|
||||
export default PeerModal |
|
@ -1,75 +0,0 @@ |
|||||
@import '../../variables.scss'; |
|
||||
|
|
||||
.closeContainer { |
|
||||
background: $lightgrey; |
|
||||
text-align: right; |
|
||||
padding: 10px; |
|
||||
|
|
||||
span { |
|
||||
color: $darkestgrey; |
|
||||
font-size: 20px; |
|
||||
cursor: pointer; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.header { |
|
||||
background: $lightgrey; |
|
||||
padding: 20px; |
|
||||
|
|
||||
h1 { |
|
||||
color: $black; |
|
||||
text-align: center; |
|
||||
margin-bottom: 20px; |
|
||||
font-weight: bold; |
|
||||
} |
|
||||
|
|
||||
h2 { |
|
||||
color: $darkestgrey; |
|
||||
font-size: 12px; |
|
||||
text-align: center; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.details { |
|
||||
dl { |
|
||||
padding: 40px 40px 40px 40px; |
|
||||
} |
|
||||
|
|
||||
dt { |
|
||||
text-align: left; |
|
||||
float: left; |
|
||||
clear: left; |
|
||||
font-weight: 500; |
|
||||
padding: 20px 35px 19px 0; |
|
||||
color: $black; |
|
||||
font-weight: bold; |
|
||||
} |
|
||||
|
|
||||
dd { |
|
||||
text-align: right; |
|
||||
font-weight: 400; |
|
||||
padding: 30px 0 10px 0; |
|
||||
margin-left: 0; |
|
||||
border-bottom: 1px solid $darkgrey; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.close { |
|
||||
text-align: center; |
|
||||
padding-bottom: 40px; |
|
||||
|
|
||||
div { |
|
||||
margin: 0 auto; |
|
||||
cursor: pointer; |
|
||||
font-size: 18px; |
|
||||
color: $red; |
|
||||
border: none; |
|
||||
padding: 0; |
|
||||
text-align: center; |
|
||||
transition: all 0.25s; |
|
||||
|
|
||||
&:hover { |
|
||||
color: lighten($red, 10%); |
|
||||
} |
|
||||
} |
|
||||
} |
|
@ -1,11 +1,6 @@ |
|||||
export default function subscribeToChannelGraph(mainWindow, lnd, meta) { |
export default function subscribeToChannelGraph(mainWindow, lnd, meta) { |
||||
console.log('subscribeChannelGraph is happening') |
|
||||
|
|
||||
|
|
||||
const call = lnd.subscribeChannelGraph({}, meta) |
const call = lnd.subscribeChannelGraph({}, meta) |
||||
|
|
||||
call.on('data', channelGraphData => mainWindow.send('channelGraphData', { channelGraphData })) |
call.on('data', channelGraphData => mainWindow.send('channelGraphData', { channelGraphData })) |
||||
call.on('end', () => console.log('channel graph end')) |
|
||||
call.on('error', error => console.log('channelgraph error: ', error)) |
|
||||
call.on('status', channelGraphStatus => mainWindow.send('channelGraphStatus', { channelGraphStatus })) |
call.on('status', channelGraphStatus => mainWindow.send('channelGraphStatus', { channelGraphStatus })) |
||||
} |
} |
||||
|
@ -1,125 +0,0 @@ |
|||||
import React from 'react' |
|
||||
import { shallow } from 'enzyme' |
|
||||
|
|
||||
import { TiPlus } from 'react-icons/lib/ti' |
|
||||
import Channels from '../../app/components/Channels' |
|
||||
import ChannelModal from '../../app/components/Channels/ChannelModal' |
|
||||
import ChannelForm from '../../app/components/Channels/ChannelForm' |
|
||||
import Channel from '../../app/components/Channels/Channel' |
|
||||
import OpenPendingChannel from '../../app/components/Channels/OpenPendingChannel' |
|
||||
import ClosedPendingChannel from '../../app/components/Channels/ClosedPendingChannel' |
|
||||
|
|
||||
const defaultProps = { |
|
||||
ticker: {}, |
|
||||
peers: [], |
|
||||
channelsLoading: false, |
|
||||
modalChannel: {}, |
|
||||
setChannel: () => {}, |
|
||||
channelModalOpen: false, |
|
||||
channelForm: {}, |
|
||||
setChannelForm: () => {}, |
|
||||
allChannels: [], |
|
||||
openChannel: () => {}, |
|
||||
closeChannel: () => {}, |
|
||||
fetchChannels: () => {}, |
|
||||
currentTicker: {}, |
|
||||
explorerLinkBase: 'https://testnet.smartbit.com.au' |
|
||||
} |
|
||||
|
|
||||
const channel_open = { |
|
||||
active: true, |
|
||||
capacity: '10000000', |
|
||||
chan_id: '1322138543153545216', |
|
||||
channel_point: '7efb80bf568cf55eb43ba439fdafea99b43f53493ec9ae7c0eae88de2d2b4577:0', |
|
||||
commit_fee: '8688', |
|
||||
commit_weight: '600', |
|
||||
fee_per_kw: '12000', |
|
||||
local_balance: '9991312', |
|
||||
num_updates: '0', |
|
||||
pending_htlcs: [], |
|
||||
remote_balance: '0', |
|
||||
remote_pubkey: '020178567c0f881b579a7ddbcd8ce362a33ebba2b3c2d218e667f7e3b390e40d4e', |
|
||||
total_satoshis_received: '0', |
|
||||
total_satoshis_sent: '0', |
|
||||
unsettled_balance: '0' |
|
||||
} |
|
||||
|
|
||||
const channel_pending = { |
|
||||
capacity: '10000000', |
|
||||
channel_point: '7efb80bf568cf55eb43ba439fdafea99b43f53493ec9ae7c0eae88de2d2b4577:0', |
|
||||
local_balance: '9991312', |
|
||||
remote_balance: '0', |
|
||||
remote_node_pub: '020178567c0f881b579a7ddbcd8ce362a33ebba2b3c2d218e667f7e3b390e40d4e' |
|
||||
} |
|
||||
|
|
||||
const pending_open_channels = { |
|
||||
blocks_till_open: 0, |
|
||||
channel: channel_pending, |
|
||||
commit_fee: '8688', |
|
||||
commit_weight: '600', |
|
||||
confirmation_height: 0, |
|
||||
fee_per_kw: '12000' |
|
||||
} |
|
||||
|
|
||||
const pending_closing_channels = { |
|
||||
channel: channel_pending, |
|
||||
closing_txid: '8d623d1ddd32945cace3351d511df2b5be3e0f7c7e5622989d2fc0215e8a2a7e' |
|
||||
} |
|
||||
|
|
||||
describe('Channels', () => { |
|
||||
describe('should show default components', () => { |
|
||||
const props = { ...defaultProps, channelsLoading: true } |
|
||||
const el = shallow(<Channels {...props} />) |
|
||||
it('should contain Modal and Form', () => { |
|
||||
expect(el.find(ChannelModal)).toHaveLength(1) |
|
||||
expect(el.find(ChannelForm)).toHaveLength(1) |
|
||||
}) |
|
||||
it('should have Channels header, and plus button', () => { |
|
||||
expect(el.contains('Channels')).toBe(true) |
|
||||
expect(el.find(TiPlus)).toHaveLength(1) |
|
||||
}) |
|
||||
}) |
|
||||
|
|
||||
describe('channels are loading', () => { |
|
||||
const props = { ...defaultProps, channelsLoading: true } |
|
||||
const el = shallow(<Channels {...props} />) |
|
||||
it('should display loading msg', () => { |
|
||||
expect(el.contains('Loading...')).toBe(true) |
|
||||
}) |
|
||||
}) |
|
||||
|
|
||||
describe('channels are loaded', () => { |
|
||||
describe('no channels', () => { |
|
||||
const props = { ...defaultProps, allChannels: [] } |
|
||||
const el = shallow(<Channels {...props} />) |
|
||||
it('should not show channels or loading', () => { |
|
||||
expect(el.contains('Loading...')).toBe(false) |
|
||||
expect(el.find(Channel)).toHaveLength(0) |
|
||||
}) |
|
||||
}) |
|
||||
|
|
||||
describe('channel is open-pending', () => { |
|
||||
const props = { ...defaultProps, allChannels: [pending_open_channels] } |
|
||||
const el = shallow(<Channels {...props} />) |
|
||||
it('should display open-pending', () => { |
|
||||
expect(el.find(OpenPendingChannel)).toHaveLength(1) |
|
||||
}) |
|
||||
}) |
|
||||
|
|
||||
describe('channel is open', () => { |
|
||||
const props = { ...defaultProps, allChannels: [channel_open] } |
|
||||
const el = shallow(<Channels {...props} />) |
|
||||
it('should display open channel', () => { |
|
||||
expect(el.find(Channel)).toHaveLength(1) |
|
||||
}) |
|
||||
}) |
|
||||
|
|
||||
describe('channel is closed-pending', () => { |
|
||||
const props = { ...defaultProps, allChannels: [pending_closing_channels] } |
|
||||
const el = shallow(<Channels {...props} />) |
|
||||
it('should display closed-pending', () => { |
|
||||
expect(el.find(ClosedPendingChannel)).toHaveLength(1) |
|
||||
}) |
|
||||
}) |
|
||||
}) |
|
||||
}) |
|
@ -1,72 +0,0 @@ |
|||||
import React from 'react' |
|
||||
import { shallow } from 'enzyme' |
|
||||
|
|
||||
import Peers from '../../app/routes/peers/components/Peers' |
|
||||
import PeerModal from '../../app/components/Peers/PeerModal' |
|
||||
import PeerForm from '../../app/components/Peers/PeerForm' |
|
||||
import Peer from '../../app/components/Peers/Peer' |
|
||||
|
|
||||
const defaultProps = { |
|
||||
fetchPeers: () => {}, |
|
||||
peerFormProps: { |
|
||||
form: {}, |
|
||||
setForm: () => {}, |
|
||||
connect: () => {} |
|
||||
}, |
|
||||
setPeerForm: () => {}, |
|
||||
setPeer: () => {}, |
|
||||
updateSearchQuery: () => {}, |
|
||||
disconnectRequest: () => {}, |
|
||||
|
|
||||
peerModalOpen: false, |
|
||||
filteredPeers: [], |
|
||||
peers: { |
|
||||
peer: null, |
|
||||
searchQuery: '' |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
const peer = { |
|
||||
address: '45.77.115.33:9735', |
|
||||
bytes_recv: '63322', |
|
||||
bytes_sent: '68714', |
|
||||
inbound: true, |
|
||||
peer_id: 3, |
|
||||
ping_time: '261996', |
|
||||
pub_key: '0293cb97aac77eacjc5377d761640f1b51ebba350902801e1aa62853fa7bc3a1f30', |
|
||||
sat_recv: '0', |
|
||||
sat_sent: '0' |
|
||||
} |
|
||||
|
|
||||
describe('component.Peers', () => { |
|
||||
describe('default components', () => { |
|
||||
const props = { ...defaultProps } |
|
||||
const el = shallow(<Peers {...props} />) |
|
||||
it('should contain Modal and Form', () => { |
|
||||
expect(el.find(PeerModal)).toHaveLength(1) |
|
||||
expect(el.find(PeerForm)).toHaveLength(1) |
|
||||
}) |
|
||||
it('should have Peers header, and plus button', () => { |
|
||||
expect(el.contains('Peers')).toBe(true) |
|
||||
expect(el.contains('Add new peer')).toBe(true) |
|
||||
}) |
|
||||
}) |
|
||||
|
|
||||
describe('peers are loaded', () => { |
|
||||
describe('no peers', () => { |
|
||||
const props = { ...defaultProps } |
|
||||
const el = shallow(<Peers {...props} />) |
|
||||
it('should show no peers', () => { |
|
||||
expect(el.find(Peer)).toHaveLength(0) |
|
||||
}) |
|
||||
}) |
|
||||
|
|
||||
describe('peer connected', () => { |
|
||||
const props = { ...defaultProps, filteredPeers: [peer] } |
|
||||
const el = shallow(<Peers {...props} />) |
|
||||
it('should show peer information', () => { |
|
||||
expect(el.find(Peer)).toHaveLength(1) |
|
||||
}) |
|
||||
}) |
|
||||
}) |
|
||||
}) |
|
@ -1,33 +0,0 @@ |
|||||
// Jest Snapshot v1, https://goo.gl/fbAQLP |
|
||||
|
|
||||
exports[`reducers balanceReducer should handle DECREMENT_COUNTER 1`] = ` |
|
||||
Object { |
|
||||
"balanceLoading": false, |
|
||||
"channelBalance": undefined, |
|
||||
"walletBalance": undefined, |
|
||||
} |
|
||||
`; |
|
||||
|
|
||||
exports[`reducers balanceReducer should handle INCREMENT_COUNTER 1`] = ` |
|
||||
Object { |
|
||||
"balanceLoading": true, |
|
||||
"channelBalance": null, |
|
||||
"walletBalance": null, |
|
||||
} |
|
||||
`; |
|
||||
|
|
||||
exports[`reducers balanceReducer should handle initial state 1`] = ` |
|
||||
Object { |
|
||||
"balanceLoading": false, |
|
||||
"channelBalance": null, |
|
||||
"walletBalance": null, |
|
||||
} |
|
||||
`; |
|
||||
|
|
||||
exports[`reducers balanceReducer should handle unknown action type 1`] = ` |
|
||||
Object { |
|
||||
"balanceLoading": false, |
|
||||
"channelBalance": null, |
|
||||
"walletBalance": null, |
|
||||
} |
|
||||
`; |
|
@ -1,308 +0,0 @@ |
|||||
// Jest Snapshot v1, https://goo.gl/fbAQLP |
|
||||
|
|
||||
exports[`reducers channelsReducer should correctly getChannels 1`] = ` |
|
||||
Object { |
|
||||
"channel": null, |
|
||||
"channelForm": Object { |
|
||||
"isOpen": false, |
|
||||
"local_amt": "", |
|
||||
"node_key": "", |
|
||||
"push_amt": "", |
|
||||
}, |
|
||||
"channels": Array [], |
|
||||
"channelsLoading": true, |
|
||||
"closingChannel": false, |
|
||||
"filter": Object { |
|
||||
"key": "ALL_CHANNELS", |
|
||||
"name": "All Channels", |
|
||||
}, |
|
||||
"filterPulldown": false, |
|
||||
"filters": Array [ |
|
||||
Object { |
|
||||
"key": "ALL_CHANNELS", |
|
||||
"name": "All Channels", |
|
||||
}, |
|
||||
Object { |
|
||||
"key": "ACTIVE_CHANNELS", |
|
||||
"name": "Active Channels", |
|
||||
}, |
|
||||
Object { |
|
||||
"key": "OPEN_CHANNELS", |
|
||||
"name": "Open Channels", |
|
||||
}, |
|
||||
Object { |
|
||||
"key": "OPEN_PENDING_CHANNELS", |
|
||||
"name": "Open Pending Channels", |
|
||||
}, |
|
||||
Object { |
|
||||
"key": "CLOSING_PENDING_CHANNELS", |
|
||||
"name": "Closing Pending Channels", |
|
||||
}, |
|
||||
], |
|
||||
"openingChannel": false, |
|
||||
"pendingChannels": Object { |
|
||||
"pending_closing_channels": Array [], |
|
||||
"pending_force_closing_channels": Array [], |
|
||||
"pending_open_channels": Array [], |
|
||||
"total_limbo_balance": "", |
|
||||
}, |
|
||||
"searchQuery": "", |
|
||||
"viewType": 0, |
|
||||
} |
|
||||
`; |
|
||||
|
|
||||
exports[`reducers channelsReducer should correctly openingChannel 1`] = ` |
|
||||
Object { |
|
||||
"channel": null, |
|
||||
"channelForm": Object { |
|
||||
"isOpen": false, |
|
||||
"local_amt": "", |
|
||||
"node_key": "", |
|
||||
"push_amt": "", |
|
||||
}, |
|
||||
"channels": Array [], |
|
||||
"channelsLoading": false, |
|
||||
"closingChannel": false, |
|
||||
"filter": Object { |
|
||||
"key": "ALL_CHANNELS", |
|
||||
"name": "All Channels", |
|
||||
}, |
|
||||
"filterPulldown": false, |
|
||||
"filters": Array [ |
|
||||
Object { |
|
||||
"key": "ALL_CHANNELS", |
|
||||
"name": "All Channels", |
|
||||
}, |
|
||||
Object { |
|
||||
"key": "ACTIVE_CHANNELS", |
|
||||
"name": "Active Channels", |
|
||||
}, |
|
||||
Object { |
|
||||
"key": "OPEN_CHANNELS", |
|
||||
"name": "Open Channels", |
|
||||
}, |
|
||||
Object { |
|
||||
"key": "OPEN_PENDING_CHANNELS", |
|
||||
"name": "Open Pending Channels", |
|
||||
}, |
|
||||
Object { |
|
||||
"key": "CLOSING_PENDING_CHANNELS", |
|
||||
"name": "Closing Pending Channels", |
|
||||
}, |
|
||||
], |
|
||||
"openingChannel": true, |
|
||||
"pendingChannels": Object { |
|
||||
"pending_closing_channels": Array [], |
|
||||
"pending_force_closing_channels": Array [], |
|
||||
"pending_open_channels": Array [], |
|
||||
"total_limbo_balance": "", |
|
||||
}, |
|
||||
"searchQuery": "", |
|
||||
"viewType": 0, |
|
||||
} |
|
||||
`; |
|
||||
|
|
||||
exports[`reducers channelsReducer should correctly receiveChannel 1`] = ` |
|
||||
Object { |
|
||||
"channel": null, |
|
||||
"channelForm": Object { |
|
||||
"isOpen": false, |
|
||||
"local_amt": "", |
|
||||
"node_key": "", |
|
||||
"push_amt": "", |
|
||||
}, |
|
||||
"channels": Array [ |
|
||||
1, |
|
||||
2, |
|
||||
], |
|
||||
"channelsLoading": false, |
|
||||
"closingChannel": false, |
|
||||
"filter": Object { |
|
||||
"key": "ALL_CHANNELS", |
|
||||
"name": "All Channels", |
|
||||
}, |
|
||||
"filterPulldown": false, |
|
||||
"filters": Array [ |
|
||||
Object { |
|
||||
"key": "ALL_CHANNELS", |
|
||||
"name": "All Channels", |
|
||||
}, |
|
||||
Object { |
|
||||
"key": "ACTIVE_CHANNELS", |
|
||||
"name": "Active Channels", |
|
||||
}, |
|
||||
Object { |
|
||||
"key": "OPEN_CHANNELS", |
|
||||
"name": "Open Channels", |
|
||||
}, |
|
||||
Object { |
|
||||
"key": "OPEN_PENDING_CHANNELS", |
|
||||
"name": "Open Pending Channels", |
|
||||
}, |
|
||||
Object { |
|
||||
"key": "CLOSING_PENDING_CHANNELS", |
|
||||
"name": "Closing Pending Channels", |
|
||||
}, |
|
||||
], |
|
||||
"openingChannel": false, |
|
||||
"pendingChannels": Array [ |
|
||||
3, |
|
||||
4, |
|
||||
], |
|
||||
"searchQuery": "", |
|
||||
"viewType": 0, |
|
||||
} |
|
||||
`; |
|
||||
|
|
||||
exports[`reducers channelsReducer should correctly setChannel 1`] = ` |
|
||||
Object { |
|
||||
"channel": "channel", |
|
||||
"channelForm": Object { |
|
||||
"isOpen": false, |
|
||||
"local_amt": "", |
|
||||
"node_key": "", |
|
||||
"push_amt": "", |
|
||||
}, |
|
||||
"channels": Array [], |
|
||||
"channelsLoading": false, |
|
||||
"closingChannel": false, |
|
||||
"filter": Object { |
|
||||
"key": "ALL_CHANNELS", |
|
||||
"name": "All Channels", |
|
||||
}, |
|
||||
"filterPulldown": false, |
|
||||
"filters": Array [ |
|
||||
Object { |
|
||||
"key": "ALL_CHANNELS", |
|
||||
"name": "All Channels", |
|
||||
}, |
|
||||
Object { |
|
||||
"key": "ACTIVE_CHANNELS", |
|
||||
"name": "Active Channels", |
|
||||
}, |
|
||||
Object { |
|
||||
"key": "OPEN_CHANNELS", |
|
||||
"name": "Open Channels", |
|
||||
}, |
|
||||
Object { |
|
||||
"key": "OPEN_PENDING_CHANNELS", |
|
||||
"name": "Open Pending Channels", |
|
||||
}, |
|
||||
Object { |
|
||||
"key": "CLOSING_PENDING_CHANNELS", |
|
||||
"name": "Closing Pending Channels", |
|
||||
}, |
|
||||
], |
|
||||
"openingChannel": false, |
|
||||
"pendingChannels": Object { |
|
||||
"pending_closing_channels": Array [], |
|
||||
"pending_force_closing_channels": Array [], |
|
||||
"pending_open_channels": Array [], |
|
||||
"total_limbo_balance": "", |
|
||||
}, |
|
||||
"searchQuery": "", |
|
||||
"viewType": 0, |
|
||||
} |
|
||||
`; |
|
||||
|
|
||||
exports[`reducers channelsReducer should correctly setChannelForm 1`] = ` |
|
||||
Object { |
|
||||
"channel": null, |
|
||||
"channelForm": Object { |
|
||||
"isOpen": true, |
|
||||
"local_amt": "", |
|
||||
"node_key": "", |
|
||||
"push_amt": "", |
|
||||
}, |
|
||||
"channels": Array [], |
|
||||
"channelsLoading": false, |
|
||||
"closingChannel": false, |
|
||||
"filter": Object { |
|
||||
"key": "ALL_CHANNELS", |
|
||||
"name": "All Channels", |
|
||||
}, |
|
||||
"filterPulldown": false, |
|
||||
"filters": Array [ |
|
||||
Object { |
|
||||
"key": "ALL_CHANNELS", |
|
||||
"name": "All Channels", |
|
||||
}, |
|
||||
Object { |
|
||||
"key": "ACTIVE_CHANNELS", |
|
||||
"name": "Active Channels", |
|
||||
}, |
|
||||
Object { |
|
||||
"key": "OPEN_CHANNELS", |
|
||||
"name": "Open Channels", |
|
||||
}, |
|
||||
Object { |
|
||||
"key": "OPEN_PENDING_CHANNELS", |
|
||||
"name": "Open Pending Channels", |
|
||||
}, |
|
||||
Object { |
|
||||
"key": "CLOSING_PENDING_CHANNELS", |
|
||||
"name": "Closing Pending Channels", |
|
||||
}, |
|
||||
], |
|
||||
"openingChannel": false, |
|
||||
"pendingChannels": Object { |
|
||||
"pending_closing_channels": Array [], |
|
||||
"pending_force_closing_channels": Array [], |
|
||||
"pending_open_channels": Array [], |
|
||||
"total_limbo_balance": "", |
|
||||
}, |
|
||||
"searchQuery": "", |
|
||||
"viewType": 0, |
|
||||
} |
|
||||
`; |
|
||||
|
|
||||
exports[`reducers channelsReducer should handle initial state 1`] = ` |
|
||||
Object { |
|
||||
"channel": null, |
|
||||
"channelForm": Object { |
|
||||
"isOpen": false, |
|
||||
"local_amt": "", |
|
||||
"node_key": "", |
|
||||
"push_amt": "", |
|
||||
}, |
|
||||
"channels": Array [], |
|
||||
"channelsLoading": false, |
|
||||
"closingChannel": false, |
|
||||
"filter": Object { |
|
||||
"key": "ALL_CHANNELS", |
|
||||
"name": "All Channels", |
|
||||
}, |
|
||||
"filterPulldown": false, |
|
||||
"filters": Array [ |
|
||||
Object { |
|
||||
"key": "ALL_CHANNELS", |
|
||||
"name": "All Channels", |
|
||||
}, |
|
||||
Object { |
|
||||
"key": "ACTIVE_CHANNELS", |
|
||||
"name": "Active Channels", |
|
||||
}, |
|
||||
Object { |
|
||||
"key": "OPEN_CHANNELS", |
|
||||
"name": "Open Channels", |
|
||||
}, |
|
||||
Object { |
|
||||
"key": "OPEN_PENDING_CHANNELS", |
|
||||
"name": "Open Pending Channels", |
|
||||
}, |
|
||||
Object { |
|
||||
"key": "CLOSING_PENDING_CHANNELS", |
|
||||
"name": "Closing Pending Channels", |
|
||||
}, |
|
||||
], |
|
||||
"openingChannel": false, |
|
||||
"pendingChannels": Object { |
|
||||
"pending_closing_channels": Array [], |
|
||||
"pending_force_closing_channels": Array [], |
|
||||
"pending_open_channels": Array [], |
|
||||
"total_limbo_balance": "", |
|
||||
}, |
|
||||
"searchQuery": "", |
|
||||
"viewType": 0, |
|
||||
} |
|
||||
`; |
|
@ -1,13 +0,0 @@ |
|||||
// Jest Snapshot v1, https://goo.gl/fbAQLP |
|
||||
|
|
||||
exports[`reducers formReducer should correctly setFormType 1`] = ` |
|
||||
Object { |
|
||||
"formType": "FOO", |
|
||||
} |
|
||||
`; |
|
||||
|
|
||||
exports[`reducers formReducer should handle initial state 1`] = ` |
|
||||
Object { |
|
||||
"formType": null, |
|
||||
} |
|
||||
`; |
|
@ -1,22 +0,0 @@ |
|||||
// Jest Snapshot v1, https://goo.gl/fbAQLP |
|
||||
|
|
||||
exports[`reducers infoReducer should correctly getInfo 1`] = ` |
|
||||
Object { |
|
||||
"data": Object {}, |
|
||||
"infoLoading": true, |
|
||||
} |
|
||||
`; |
|
||||
|
|
||||
exports[`reducers infoReducer should correctly receiveInfo 1`] = ` |
|
||||
Object { |
|
||||
"data": "foo", |
|
||||
"infoLoading": false, |
|
||||
} |
|
||||
`; |
|
||||
|
|
||||
exports[`reducers infoReducer should handle initial state 1`] = ` |
|
||||
Object { |
|
||||
"data": Object {}, |
|
||||
"infoLoading": false, |
|
||||
} |
|
||||
`; |
|
@ -1,171 +0,0 @@ |
|||||
// Jest Snapshot v1, https://goo.gl/fbAQLP |
|
||||
|
|
||||
exports[`reducers invoiceReducer should correctly getInvoice 1`] = ` |
|
||||
Object { |
|
||||
"data": Object {}, |
|
||||
"formInvoice": Object { |
|
||||
"amount": "0", |
|
||||
"payreq": "", |
|
||||
"r_hash": "", |
|
||||
}, |
|
||||
"invoice": null, |
|
||||
"invoiceLoading": true, |
|
||||
"invoices": Array [], |
|
||||
"invoicesSearchText": "", |
|
||||
} |
|
||||
`; |
|
||||
|
|
||||
exports[`reducers invoiceReducer should correctly getInvoices 1`] = ` |
|
||||
Object { |
|
||||
"data": Object {}, |
|
||||
"formInvoice": Object { |
|
||||
"amount": "0", |
|
||||
"payreq": "", |
|
||||
"r_hash": "", |
|
||||
}, |
|
||||
"invoice": null, |
|
||||
"invoiceLoading": true, |
|
||||
"invoices": Array [], |
|
||||
"invoicesSearchText": "", |
|
||||
} |
|
||||
`; |
|
||||
|
|
||||
exports[`reducers invoiceReducer should correctly invcoiceFailed 1`] = ` |
|
||||
Object { |
|
||||
"data": null, |
|
||||
"formInvoice": Object { |
|
||||
"amount": "0", |
|
||||
"payreq": "", |
|
||||
"r_hash": "", |
|
||||
}, |
|
||||
"invoice": null, |
|
||||
"invoiceLoading": false, |
|
||||
"invoices": Array [], |
|
||||
"invoicesSearchText": "", |
|
||||
} |
|
||||
`; |
|
||||
|
|
||||
exports[`reducers invoiceReducer should correctly invcoiceSuccessful 1`] = ` |
|
||||
Object { |
|
||||
"data": Object {}, |
|
||||
"formInvoice": Object { |
|
||||
"amount": "0", |
|
||||
"payreq": "", |
|
||||
"r_hash": "", |
|
||||
}, |
|
||||
"invoice": null, |
|
||||
"invoiceLoading": false, |
|
||||
"invoices": Array [ |
|
||||
"foo", |
|
||||
], |
|
||||
"invoicesSearchText": "", |
|
||||
} |
|
||||
`; |
|
||||
|
|
||||
exports[`reducers invoiceReducer should correctly receiveFormInvoice 1`] = ` |
|
||||
Object { |
|
||||
"data": Object {}, |
|
||||
"formInvoice": Object { |
|
||||
"amount": "0", |
|
||||
"payreq": "", |
|
||||
"r_hash": "", |
|
||||
}, |
|
||||
"invoice": null, |
|
||||
"invoiceLoading": false, |
|
||||
"invoices": Array [], |
|
||||
"invoicesSearchText": "", |
|
||||
} |
|
||||
`; |
|
||||
|
|
||||
exports[`reducers invoiceReducer should correctly receiveInvoice 1`] = ` |
|
||||
Object { |
|
||||
"data": Object {}, |
|
||||
"formInvoice": Object { |
|
||||
"amount": "0", |
|
||||
"payreq": "", |
|
||||
"r_hash": "", |
|
||||
}, |
|
||||
"invoice": "foo", |
|
||||
"invoiceLoading": false, |
|
||||
"invoices": Array [], |
|
||||
"invoicesSearchText": "", |
|
||||
} |
|
||||
`; |
|
||||
|
|
||||
exports[`reducers invoiceReducer should correctly receiveInvoices 1`] = ` |
|
||||
Object { |
|
||||
"data": Object {}, |
|
||||
"formInvoice": Object { |
|
||||
"amount": "0", |
|
||||
"payreq": "", |
|
||||
"r_hash": "", |
|
||||
}, |
|
||||
"invoice": null, |
|
||||
"invoiceLoading": false, |
|
||||
"invoices": Array [ |
|
||||
1, |
|
||||
2, |
|
||||
], |
|
||||
"invoicesSearchText": "", |
|
||||
} |
|
||||
`; |
|
||||
|
|
||||
exports[`reducers invoiceReducer should correctly searchInvoices 1`] = ` |
|
||||
Object { |
|
||||
"data": Object {}, |
|
||||
"formInvoice": Object { |
|
||||
"amount": "0", |
|
||||
"payreq": "", |
|
||||
"r_hash": "", |
|
||||
}, |
|
||||
"invoice": null, |
|
||||
"invoiceLoading": false, |
|
||||
"invoices": Array [], |
|
||||
"invoicesSearchText": "foo", |
|
||||
} |
|
||||
`; |
|
||||
|
|
||||
exports[`reducers invoiceReducer should correctly sendInvoice 1`] = ` |
|
||||
Object { |
|
||||
"data": Object {}, |
|
||||
"formInvoice": Object { |
|
||||
"amount": "0", |
|
||||
"payreq": "", |
|
||||
"r_hash": "", |
|
||||
}, |
|
||||
"invoice": null, |
|
||||
"invoiceLoading": true, |
|
||||
"invoices": Array [], |
|
||||
"invoicesSearchText": "", |
|
||||
} |
|
||||
`; |
|
||||
|
|
||||
exports[`reducers invoiceReducer should correctly setInvoice 1`] = ` |
|
||||
Object { |
|
||||
"data": Object {}, |
|
||||
"formInvoice": Object { |
|
||||
"amount": "0", |
|
||||
"payreq": "", |
|
||||
"r_hash": "", |
|
||||
}, |
|
||||
"invoice": "foo", |
|
||||
"invoiceLoading": false, |
|
||||
"invoices": Array [], |
|
||||
"invoicesSearchText": "", |
|
||||
} |
|
||||
`; |
|
||||
|
|
||||
exports[`reducers invoiceReducer should handle initial state 1`] = ` |
|
||||
Object { |
|
||||
"data": Object {}, |
|
||||
"formInvoice": Object { |
|
||||
"amount": "0", |
|
||||
"payreq": "", |
|
||||
"r_hash": "", |
|
||||
}, |
|
||||
"invoice": null, |
|
||||
"invoiceLoading": false, |
|
||||
"invoices": Array [], |
|
||||
"invoicesSearchText": "", |
|
||||
} |
|
||||
`; |
|
@ -1,49 +0,0 @@ |
|||||
// Jest Snapshot v1, https://goo.gl/fbAQLP |
|
||||
|
|
||||
exports[`reducers paymentReducer should correctly getPayments 1`] = ` |
|
||||
Object { |
|
||||
"payment": null, |
|
||||
"paymentLoading": true, |
|
||||
"payments": Array [], |
|
||||
"sendingPayment": false, |
|
||||
} |
|
||||
`; |
|
||||
|
|
||||
exports[`reducers paymentReducer should correctly paymentSuccessful 1`] = ` |
|
||||
Object { |
|
||||
"payment": null, |
|
||||
"paymentLoading": false, |
|
||||
"payments": Array [], |
|
||||
"sendingPayment": false, |
|
||||
} |
|
||||
`; |
|
||||
|
|
||||
exports[`reducers paymentReducer should correctly receivePayments 1`] = ` |
|
||||
Object { |
|
||||
"payment": null, |
|
||||
"paymentLoading": false, |
|
||||
"payments": Array [ |
|
||||
1, |
|
||||
2, |
|
||||
], |
|
||||
"sendingPayment": false, |
|
||||
} |
|
||||
`; |
|
||||
|
|
||||
exports[`reducers paymentReducer should correctly sendPayment 1`] = ` |
|
||||
Object { |
|
||||
"payment": "foo", |
|
||||
"paymentLoading": false, |
|
||||
"payments": Array [], |
|
||||
"sendingPayment": false, |
|
||||
} |
|
||||
`; |
|
||||
|
|
||||
exports[`reducers paymentReducer should handle initial state 1`] = ` |
|
||||
Object { |
|
||||
"payment": null, |
|
||||
"paymentLoading": false, |
|
||||
"payments": Array [], |
|
||||
"sendingPayment": false, |
|
||||
} |
|
||||
`; |
|
@ -1,182 +0,0 @@ |
|||||
// Jest Snapshot v1, https://goo.gl/fbAQLP |
|
||||
|
|
||||
exports[`reducers peersReducer should correctly connectFailure 1`] = ` |
|
||||
Object { |
|
||||
"connecting": false, |
|
||||
"disconnecting": false, |
|
||||
"peer": null, |
|
||||
"peerForm": Object { |
|
||||
"host": "", |
|
||||
"isOpen": false, |
|
||||
"pubkey": "", |
|
||||
}, |
|
||||
"peers": Array [], |
|
||||
"peersLoading": false, |
|
||||
"searchQuery": "", |
|
||||
} |
|
||||
`; |
|
||||
|
|
||||
exports[`reducers peersReducer should correctly connectPeer 1`] = ` |
|
||||
Object { |
|
||||
"connecting": true, |
|
||||
"disconnecting": false, |
|
||||
"peer": null, |
|
||||
"peerForm": Object { |
|
||||
"host": "", |
|
||||
"isOpen": false, |
|
||||
"pubkey": "", |
|
||||
}, |
|
||||
"peers": Array [], |
|
||||
"peersLoading": false, |
|
||||
"searchQuery": "", |
|
||||
} |
|
||||
`; |
|
||||
|
|
||||
exports[`reducers peersReducer should correctly connectSuccess 1`] = ` |
|
||||
Object { |
|
||||
"connecting": false, |
|
||||
"disconnecting": false, |
|
||||
"peer": null, |
|
||||
"peerForm": Object { |
|
||||
"host": "", |
|
||||
"isOpen": false, |
|
||||
"pubkey": "", |
|
||||
}, |
|
||||
"peers": Array [ |
|
||||
"foo", |
|
||||
], |
|
||||
"peersLoading": false, |
|
||||
"searchQuery": "", |
|
||||
} |
|
||||
`; |
|
||||
|
|
||||
exports[`reducers peersReducer should correctly disconnectFailure 1`] = ` |
|
||||
Object { |
|
||||
"connecting": false, |
|
||||
"disconnecting": false, |
|
||||
"peer": null, |
|
||||
"peerForm": Object { |
|
||||
"host": "", |
|
||||
"isOpen": false, |
|
||||
"pubkey": "", |
|
||||
}, |
|
||||
"peers": Array [], |
|
||||
"peersLoading": false, |
|
||||
"searchQuery": "", |
|
||||
} |
|
||||
`; |
|
||||
|
|
||||
exports[`reducers peersReducer should correctly disconnectPeer 1`] = ` |
|
||||
Object { |
|
||||
"connecting": false, |
|
||||
"disconnecting": true, |
|
||||
"peer": null, |
|
||||
"peerForm": Object { |
|
||||
"host": "", |
|
||||
"isOpen": false, |
|
||||
"pubkey": "", |
|
||||
}, |
|
||||
"peers": Array [], |
|
||||
"peersLoading": false, |
|
||||
"searchQuery": "", |
|
||||
} |
|
||||
`; |
|
||||
|
|
||||
exports[`reducers peersReducer should correctly disconnectSuccess 1`] = ` |
|
||||
Object { |
|
||||
"connecting": false, |
|
||||
"disconnecting": false, |
|
||||
"peer": null, |
|
||||
"peerForm": Object { |
|
||||
"host": "", |
|
||||
"isOpen": false, |
|
||||
"pubkey": "", |
|
||||
}, |
|
||||
"peers": Array [], |
|
||||
"peersLoading": false, |
|
||||
"searchQuery": "", |
|
||||
} |
|
||||
`; |
|
||||
|
|
||||
exports[`reducers peersReducer should correctly getPeers 1`] = ` |
|
||||
Object { |
|
||||
"connecting": false, |
|
||||
"disconnecting": false, |
|
||||
"peer": null, |
|
||||
"peerForm": Object { |
|
||||
"host": "", |
|
||||
"isOpen": false, |
|
||||
"pubkey": "", |
|
||||
}, |
|
||||
"peers": Array [], |
|
||||
"peersLoading": true, |
|
||||
"searchQuery": "", |
|
||||
} |
|
||||
`; |
|
||||
|
|
||||
exports[`reducers peersReducer should correctly receivePeers 1`] = ` |
|
||||
Object { |
|
||||
"connecting": false, |
|
||||
"disconnecting": false, |
|
||||
"peer": null, |
|
||||
"peerForm": Object { |
|
||||
"host": "", |
|
||||
"isOpen": false, |
|
||||
"pubkey": "", |
|
||||
}, |
|
||||
"peers": "foo", |
|
||||
"peersLoading": false, |
|
||||
"searchQuery": "", |
|
||||
} |
|
||||
`; |
|
||||
|
|
||||
exports[`reducers peersReducer should correctly setPeer 1`] = ` |
|
||||
Object { |
|
||||
"connecting": false, |
|
||||
"disconnecting": false, |
|
||||
"peer": "foo", |
|
||||
"peerForm": Object { |
|
||||
"host": "", |
|
||||
"isOpen": false, |
|
||||
"pubkey": "", |
|
||||
}, |
|
||||
"peers": Array [], |
|
||||
"peersLoading": false, |
|
||||
"searchQuery": "", |
|
||||
} |
|
||||
`; |
|
||||
|
|
||||
exports[`reducers peersReducer should correctly setPeerForm 1`] = ` |
|
||||
Object { |
|
||||
"connecting": false, |
|
||||
"disconnecting": false, |
|
||||
"peer": null, |
|
||||
"peerForm": Object { |
|
||||
"0": "f", |
|
||||
"1": "o", |
|
||||
"2": "o", |
|
||||
"host": "", |
|
||||
"isOpen": false, |
|
||||
"pubkey": "", |
|
||||
}, |
|
||||
"peers": Array [], |
|
||||
"peersLoading": false, |
|
||||
"searchQuery": "", |
|
||||
} |
|
||||
`; |
|
||||
|
|
||||
exports[`reducers peersReducer should handle initial state 1`] = ` |
|
||||
Object { |
|
||||
"connecting": false, |
|
||||
"disconnecting": false, |
|
||||
"peer": null, |
|
||||
"peerForm": Object { |
|
||||
"host": "", |
|
||||
"isOpen": false, |
|
||||
"pubkey": "", |
|
||||
}, |
|
||||
"peers": Array [], |
|
||||
"peersLoading": false, |
|
||||
"searchQuery": "", |
|
||||
} |
|
||||
`; |
|
@ -1,51 +0,0 @@ |
|||||
// Jest Snapshot v1, https://goo.gl/fbAQLP |
|
||||
|
|
||||
exports[`reducers tickerReducer should correctly getTicker 1`] = ` |
|
||||
Object { |
|
||||
"btcTicker": null, |
|
||||
"crypto": "", |
|
||||
"currency": "", |
|
||||
"ltcTicker": null, |
|
||||
"tickerLoading": true, |
|
||||
} |
|
||||
`; |
|
||||
|
|
||||
exports[`reducers tickerReducer should correctly receiveTicker 1`] = ` |
|
||||
Object { |
|
||||
"btcTicker": undefined, |
|
||||
"crypto": "", |
|
||||
"currency": "", |
|
||||
"ltcTicker": undefined, |
|
||||
"tickerLoading": false, |
|
||||
} |
|
||||
`; |
|
||||
|
|
||||
exports[`reducers tickerReducer should correctly setCrypto 1`] = ` |
|
||||
Object { |
|
||||
"btcTicker": null, |
|
||||
"crypto": "foo", |
|
||||
"currency": "", |
|
||||
"ltcTicker": null, |
|
||||
"tickerLoading": false, |
|
||||
} |
|
||||
`; |
|
||||
|
|
||||
exports[`reducers tickerReducer should correctly setCurrency 1`] = ` |
|
||||
Object { |
|
||||
"btcTicker": null, |
|
||||
"crypto": "", |
|
||||
"currency": "foo", |
|
||||
"ltcTicker": null, |
|
||||
"tickerLoading": false, |
|
||||
} |
|
||||
`; |
|
||||
|
|
||||
exports[`reducers tickerReducer should handle initial state 1`] = ` |
|
||||
Object { |
|
||||
"btcTicker": null, |
|
||||
"crypto": "", |
|
||||
"currency": "", |
|
||||
"ltcTicker": null, |
|
||||
"tickerLoading": false, |
|
||||
} |
|
||||
`; |
|
Loading…
Reference in new issue