Browse Source

Merge pull request #63 from LN-Zap/feature/wallet-redesign

Feature/wallet redesign
renovate/lint-staged-8.x
jackmallers 7 years ago
committed by GitHub
parent
commit
ee700efc57
  1. 1
      app/api/index.js
  2. 2
      app/components/Channels/Channels.js
  3. 4
      app/components/ModalRoot/ModalRoot.js
  4. 42
      app/components/ModalRoot/WalletDetails.js
  5. 70
      app/components/ModalRoot/WalletDetails.scss
  6. 54
      app/components/Nav/Nav.js
  7. 1
      app/components/Nav/Nav.scss
  8. 64
      app/components/Wallet/ReceiveModal.js
  9. 38
      app/components/Wallet/ReceiveModal.scss
  10. 71
      app/components/Wallet/Wallet.js
  11. 72
      app/components/Wallet/Wallet.scss
  12. 3
      app/components/Wallet/index.js
  13. 1
      app/main.dev.js
  14. 2
      app/routes/activity/components/components/Modal/Modal.js
  15. 23
      app/routes/app/components/App.js
  16. 4
      app/routes/app/containers/AppContainer.js
  17. 22
      app/routes/wallet/components/Wallet.js
  18. 1
      app/variables.scss
  19. 1
      package.json
  20. BIN
      resources/bin/darwin/lnd
  21. 26
      yarn.lock

1
app/api/index.js

@ -15,7 +15,6 @@ export function requestTickers(ids) {
.then(axios.spread((btcTicker, ltcTicker) => ({ btcTicker: btcTicker[0], ltcTicker: ltcTicker[0] })))
}
export function requestBlockHeight() {
const BASE_URL = 'https://testnet-api.smartbit.com.au/v1/blockchain/blocks?limit=1'
return axios({

2
app/components/Channels/Channels.js

@ -103,7 +103,7 @@ const Channels = ({
}
return (
<Channel
key={channel.chan_id}
key={index}
ticker={ticker}
channel={channel}
setChannel={setChannel}

4
app/components/ModalRoot/ModalRoot.js

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

42
app/components/ModalRoot/WalletDetails.js

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

70
app/components/ModalRoot/WalletDetails.scss

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

54
app/components/Nav/Nav.js

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

1
app/components/Nav/Nav.scss

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

64
app/components/Wallet/ReceiveModal.js

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

38
app/components/Wallet/ReceiveModal.scss

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

71
app/components/Wallet/Wallet.js

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

72
app/components/Wallet/Wallet.scss

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

3
app/components/Wallet/index.js

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

1
app/main.dev.js

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

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

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

23
app/routes/app/components/App.js

@ -5,16 +5,18 @@ import LoadingBolt from 'components/LoadingBolt'
import Form from 'components/Form'
import ModalRoot from 'components/ModalRoot'
import Nav from 'components/Nav'
import Wallet from 'components/Wallet'
import styles from './App.scss'
class App extends Component {
componentWillMount() {
const { fetchTicker, fetchBalance, fetchInfo, lnd: { syncing } } = this.props
const { fetchTicker, fetchBalance, fetchInfo, newAddress, lnd: { syncing } } = this.props
if (!syncing) {
fetchTicker()
fetchBalance()
fetchInfo()
newAddress('p2pkh')
}
}
@ -27,10 +29,11 @@ class App extends Component {
modal: { modalType, modalProps },
hideModal,
ticker,
currentTicker,
address: { address },
balance,
info,
form,
setCurrency,
currentTicker,
openPayForm,
openRequestForm,
@ -65,15 +68,17 @@ class App extends Component {
<Form formType={form.formType} formProps={formProps} closeForm={closeForm} />
<Nav
ticker={ticker}
balance={balance}
setCurrency={setCurrency}
currentTicker={currentTicker}
openPayForm={openPayForm}
openRequestForm={openRequestForm}
/>
<div className={styles.content}>
<Wallet
ticker={ticker}
balance={balance}
address={address}
info={info}
/>
{children}
</div>
</div>
@ -89,16 +94,18 @@ App.propTypes = {
modal: PropTypes.object.isRequired,
ticker: PropTypes.object.isRequired,
address: PropTypes.object.isRequired,
balance: PropTypes.object.isRequired,
info: PropTypes.object.isRequired,
form: PropTypes.object.isRequired,
formProps: PropTypes.object.isRequired,
closeForm: PropTypes.func.isRequired,
newAddress: PropTypes.func.isRequired,
fetchInfo: PropTypes.func.isRequired,
hideModal: PropTypes.func.isRequired,
fetchTicker: PropTypes.func.isRequired,
fetchBalance: PropTypes.func.isRequired,
setCurrency: PropTypes.func.isRequired,
openPayForm: PropTypes.func.isRequired,
openRequestForm: PropTypes.func.isRequired,

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

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

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

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

1
app/variables.scss

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

1
package.json

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

BIN
resources/bin/darwin/lnd

Binary file not shown.

26
yarn.lock

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

Loading…
Cancel
Save