Browse Source

Merge pull request #351 from mrfelton/feaure/connection-onboarding

Configure LND connection as part of onboarding process
renovate/lint-staged-8.x
JimmyMow 7 years ago
committed by GitHub
parent
commit
f127c37270
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 24
      app/components/Onboarding/Autopilot.js
  2. 4
      app/components/Onboarding/Autopilot.scss
  3. 57
      app/components/Onboarding/ConnectionDetails.js
  4. 29
      app/components/Onboarding/ConnectionDetails.scss
  5. 35
      app/components/Onboarding/ConnectionType.js
  6. 40
      app/components/Onboarding/ConnectionType.scss
  7. 1
      app/components/Onboarding/NewAezeedPassword.js
  8. 1
      app/components/Onboarding/NewWalletPassword.js
  9. 67
      app/components/Onboarding/Onboarding.js
  10. 28
      app/containers/Root.js
  11. 29
      app/lnd/config/index.js
  12. 18
      app/lnd/index.js
  13. 12
      app/lnd/lib/lightning.js
  14. 3
      app/lnd/lib/walletUnlocker.js
  15. 68
      app/lnd/methods/channelController.js
  16. 122
      app/lnd/methods/index.js
  17. 20
      app/lnd/methods/invoicesController.js
  18. 20
      app/lnd/methods/networkController.js
  19. 20
      app/lnd/methods/paymentsController.js
  20. 12
      app/lnd/methods/peersController.js
  21. 22
      app/lnd/methods/walletController.js
  22. 4
      app/lnd/push/closechannel.js
  23. 4
      app/lnd/push/openchannel.js
  24. 4
      app/lnd/push/subscribeinvoice.js
  25. 4
      app/lnd/subscribe/channelgraph.js
  26. 8
      app/lnd/subscribe/index.js
  27. 4
      app/lnd/subscribe/invoices.js
  28. 4
      app/lnd/subscribe/transactions.js
  29. 106
      app/main.dev.js
  30. 57
      app/reducers/onboarding.js
  31. 1
      package.json
  32. 30
      yarn.lock

24
app/components/Onboarding/Autopilot.js

@ -7,28 +7,14 @@ const Autopilot = ({ autopilot, setAutopilot }) => (
<div className={styles.container}>
<section className={`${styles.enable} ${autopilot && styles.active}`}>
<div onClick={() => setAutopilot(true)}>
{
autopilot ?
<FaCircle />
:
<FaCircleThin />
}
<span className={styles.label}>
Enable Autopilot
</span>
{autopilot ? <FaCircle /> : <FaCircleThin />}
<span className={styles.label}>Enable Autopilot</span>
</div>
</section>
<section className={`${styles.disable} ${(!autopilot && autopilot !== null) && styles.active}`}>
<section className={`${styles.disable} ${!autopilot && autopilot !== null && styles.active}`}>
<div onClick={() => setAutopilot(false)}>
{
!autopilot && autopilot !== null ?
<FaCircle />
:
<FaCircleThin />
}
<span className={styles.label}>
Disable Autopilot
</span>
{!autopilot && autopilot !== null ? <FaCircle /> : <FaCircleThin />}
<span className={styles.label}>Disable Autopilot</span>
</div>
</section>
</div>

4
app/components/Onboarding/Autopilot.scss

@ -5,7 +5,7 @@
section {
margin: 20px 0;
&.enable {
&.active {
div {
@ -50,4 +50,4 @@
margin-left: 15px;
}
}
}
}

57
app/components/Onboarding/ConnectionDetails.js

@ -0,0 +1,57 @@
import React from 'react'
import PropTypes from 'prop-types'
import styles from './ConnectionDetails.scss'
const ConnectionDetails = ({
connectionHost, connectionCert, connectionMacaroon, setConnectionHost, setConnectionCert, setConnectionMacaroon
}) => (
<div className={styles.container}>
<div>
<label htmlFor='connectionHost'>Host:</label>
<input
type='text'
id='connectionHost'
placeholder='Hostname / Port of the Lnd gRPC interface'
className={styles.host}
ref={input => input}
value={connectionHost}
onChange={event => setConnectionHost(event.target.value)}
/>
</div>
<div>
<label htmlFor='connectionCert'>TLS Certificate:</label>
<input
type='text'
id='connectionCert'
placeholder='Path to the lnd tls cert'
className={styles.cert}
ref={input => input}
value={connectionCert}
onChange={event => setConnectionCert(event.target.value)}
/>
</div>
<div>
<label htmlFor='connectionMacaroon'>Macaroon:</label>
<input
type='text'
id='connectionMacaroon'
placeholder='Path to the lnd macaroon file'
className={styles.macaroon}
ref={input => input}
value={connectionMacaroon}
onChange={event => setConnectionMacaroon(event.target.value)}
/>
</div>
</div>
)
ConnectionDetails.propTypes = {
connectionHost: PropTypes.string.isRequired,
connectionCert: PropTypes.string.isRequired,
connectionMacaroon: PropTypes.string.isRequired,
setConnectionHost: PropTypes.func.isRequired,
setConnectionCert: PropTypes.func.isRequired,
setConnectionMacaroon: PropTypes.func.isRequired
}
export default ConnectionDetails

29
app/components/Onboarding/ConnectionDetails.scss

@ -0,0 +1,29 @@
@import '../../variables.scss';
.container {
color: $white;
label {
font-size: 12px;
line-height: 14px;
padding: 10px 0px;
min-height: 14px;
}
input {
background: transparent;
outline: none;
border: 0;
color: $gold;
-webkit-text-fill-color: $white;
font-size: 22px;
width: 100%;
// font-weight: 200;
margin-bottom: 25px;
}
input::-webkit-input-placeholder {
text-shadow: none;
-webkit-text-fill-color: initial;
}
}

35
app/components/Onboarding/ConnectionType.js

@ -0,0 +1,35 @@
import React from 'react'
import PropTypes from 'prop-types'
import { FaCircle, FaCircleThin } from 'react-icons/lib/fa'
import styles from './ConnectionType.scss'
const ConnectionType = ({ connectionType, setConnectionType }) => (
<div className={styles.container}>
<section className={`${styles.option} ${connectionType === 'local' && styles.active}`}>
<div className={`${styles.button}`} onClick={() => setConnectionType('local')}>
{connectionType === 'local' ? <FaCircle /> : <FaCircleThin />}
<span className={styles.label}>Automatic</span>
</div>
<div className={`${styles.description}`}>
In automatic mode, we will check your local machine to see if you already have a Lightning node running.
If so, we will try to use it. If not, we will start up a light-weight neutrino node for you.
</div>
</section>
<section className={`${styles.option} ${connectionType === 'custom' && styles.active}`}>
<div className={`${styles.button}`} onClick={() => setConnectionType('custom')}>
{connectionType === 'custom' ? <FaCircle /> : <FaCircleThin />}
<span className={styles.label}>Custom</span>
</div>
<div className={`${styles.description}`}>
Connect to a remote Lightning node or a node running in a non-standard location (advanced users only).
</div>
</section>
</div>
)
ConnectionType.propTypes = {
connectionType: PropTypes.string.isRequired,
setConnectionType: PropTypes.func.isRequired
}
export default ConnectionType

40
app/components/Onboarding/ConnectionType.scss

@ -0,0 +1,40 @@
@import '../../variables.scss';
.container {
color: $white;
section {
margin: 30px 0;
&.option {
.button {
width: 150px;
text-align: center;
display: inline-block;
padding: 20px;
border: 1px solid $white;
border-radius: 5px;
font-weight: 200;
cursor: pointer;
transition: all 0.25s;
margin-bottom: 20px;
}
&.active {
.button {
color: $gold;
border-color: $gold;
}
}
.button:hover {
color: $gold;
border-color: $gold;
}
.label {
margin-left: 15px;
}
}
}
}

1
app/components/Onboarding/NewAezeedPassword.js

@ -42,4 +42,3 @@ NewAezeedPassword.propTypes = {
}
export default NewAezeedPassword

1
app/components/Onboarding/NewWalletPassword.js

@ -6,7 +6,6 @@ const NewWalletPassword = ({
createWalletPassword,
createWalletPasswordConfirmation,
showCreateWalletPasswordConfirmationError,
updateCreateWalletPassword,
updateCreateWalletPasswordConfirmation
}) => (

67
app/components/Onboarding/Onboarding.js

@ -4,6 +4,8 @@ import PropTypes from 'prop-types'
import LoadingBolt from 'components/LoadingBolt'
import FormContainer from './FormContainer'
import ConnectionType from './ConnectionType'
import ConnectionDetails from './ConnectionDetails'
import Alias from './Alias'
import Autopilot from './Autopilot'
import Login from './Login'
@ -18,6 +20,10 @@ import styles from './Onboarding.scss'
const Onboarding = ({
onboarding: {
step,
connectionType,
connectionHost,
connectionCert,
connectionMacaroon,
alias,
autopilot,
startingLnd,
@ -26,6 +32,8 @@ const Onboarding = ({
aezeedPassword,
fetchingSeed
},
connectionTypeProps,
connectionDetailProps,
changeStep,
startLnd,
submitNewWallet,
@ -40,12 +48,43 @@ const Onboarding = ({
}) => {
const renderStep = () => {
switch (step) {
case 0.1:
return (
<FormContainer
title='Lightning Connection'
description='How will you connect to the Lightning Network?'
back={null}
next={() => changeStep(connectionType === 'local' ? 1 : 0.2)}
>
<ConnectionType {...connectionTypeProps} />
</FormContainer>
)
case 0.2:
return (
<FormContainer
title='Connection details'
description='Enter the connection details for your Lightning node.'
back={() => changeStep(0.1)}
next={() =>
startLnd({
connectionType,
connectionHost,
connectionCert,
connectionMacaroon
})
}
>
<ConnectionDetails {...connectionDetailProps} />
</FormContainer>
)
case 1:
return (
<FormContainer
title='What should we call you?'
description='Set your nickname to help others connect with you on the Lightning Network'
back={null}
back={() => changeStep(0.1)}
next={() => changeStep(2)}
>
<Alias {...aliasProps} />
@ -57,7 +96,7 @@ const Onboarding = ({
title='Autopilot'
description='Autopilot is an automatic network manager. Instead of manually adding people to build your network to make payments, enable autopilot to automatically connect you to the Lightning Network using 60% of your balance.' // eslint-disable-line
back={() => changeStep(1)}
next={() => startLnd(alias, autopilot)}
next={() => startLnd({ connectionType, alias, autopilot })}
>
<Autopilot {...autopilotProps} />
</FormContainer>
@ -81,7 +120,9 @@ const Onboarding = ({
back={null}
next={() => {
// dont allow the user to move on if the confirmation password doesnt match the original password
if (newWalletPasswordProps.showCreateWalletPasswordConfirmationError) { return }
if (newWalletPasswordProps.showCreateWalletPasswordConfirmationError) {
return
}
changeStep(5)
}}
@ -145,7 +186,9 @@ const Onboarding = ({
back={() => changeStep(6)}
next={() => {
// don't allow them to move on if they havent re-entered the seed correctly
if (!reEnterSeedProps.reEnterSeedChecker) { return }
if (!reEnterSeedProps.reEnterSeedChecker) {
return
}
changeStep(8)
}}
@ -174,18 +217,20 @@ const Onboarding = ({
}
}
if (startingLnd) { return <LoadingBolt /> }
if (fetchingSeed) { return <LoadingBolt /> }
if (startingLnd) {
return <LoadingBolt />
}
if (fetchingSeed) {
return <LoadingBolt />
}
return (
<div className={styles.container}>
{renderStep()}
</div>
)
return <div className={styles.container}>{renderStep()}</div>
}
Onboarding.propTypes = {
onboarding: PropTypes.object.isRequired,
connectionTypeProps: PropTypes.object.isRequired,
connectionDetailProps: PropTypes.object.isRequired,
aliasProps: PropTypes.object.isRequired,
autopilotProps: PropTypes.object.isRequired,
initWalletProps: PropTypes.object.isRequired,

28
app/containers/Root.js

@ -8,6 +8,10 @@ import LoadingBolt from '../components/LoadingBolt'
import Onboarding from '../components/Onboarding'
import Syncing from '../components/Onboarding/Syncing'
import {
setConnectionType,
setConnectionHost,
setConnectionCert,
setConnectionMacaroon,
updateAlias,
updatePassword,
setAutopilot,
@ -29,6 +33,10 @@ import { fetchBlockHeight, lndSelectors } from '../reducers/lnd'
import Routes from '../routes'
const mapDispatchToProps = {
setConnectionType,
setConnectionHost,
setConnectionCert,
setConnectionMacaroon,
updateAlias,
updatePassword,
updateCreateWalletPassword,
@ -65,6 +73,20 @@ const mergeProps = (stateProps, dispatchProps, ownProps) => {
syncPercentage: stateProps.syncPercentage
}
const connectionTypeProps = {
connectionType: stateProps.onboarding.connectionType,
setConnectionType: dispatchProps.setConnectionType
}
const connectionDetailProps = {
connectionHost: stateProps.onboarding.connectionHost,
connectionCert: stateProps.onboarding.connectionCert,
connectionMacaroon: stateProps.onboarding.connectionMacaroon,
setConnectionHost: dispatchProps.setConnectionHost,
setConnectionCert: dispatchProps.setConnectionCert,
setConnectionMacaroon: dispatchProps.setConnectionMacaroon
}
const aliasProps = {
updateAlias: dispatchProps.updateAlias,
alias: stateProps.onboarding.alias
@ -135,6 +157,8 @@ const mergeProps = (stateProps, dispatchProps, ownProps) => {
changeStep: dispatchProps.changeStep,
startLnd: dispatchProps.startLnd,
submitNewWallet: dispatchProps.submitNewWallet,
connectionTypeProps,
connectionDetailProps,
aliasProps,
autopilotProps,
initWalletProps,
@ -174,7 +198,9 @@ const Root = ({
}
// Don't launch the app without gRPC connection
if (!lnd.grpcStarted) { return <LoadingBolt /> }
if (!lnd.grpcStarted) {
return <LoadingBolt />
}
return (
<Provider store={store}>

29
app/lnd/config/index.js

@ -4,29 +4,48 @@
// Windows: TODO find out where cert is located for windows machine
import { userInfo, platform } from 'os'
import { join } from 'path'
import Store from 'electron-store'
const store = new Store({ name: 'connection' })
const plat = platform()
let loc
let macaroonPath
switch (platform()) {
let lndBin
let lndPath
switch (plat) {
case 'darwin':
loc = 'Library/Application Support/Lnd/tls.cert'
macaroonPath = 'Library/Application Support/Lnd/admin.macaroon'
lndBin = 'lnd'
break
case 'linux':
loc = '.lnd/tls.cert'
macaroonPath = '.lnd/admin.macaroon'
lndBin = 'lnd'
break
case 'win32':
loc = join('Appdata', 'Local', 'Lnd', 'tls.cert')
macaroonPath = join('Appdata', 'Local', 'Lnd', 'admin.macaroon')
lndBin = 'lnd.exe'
break
default:
break
}
if (process.env.NODE_ENV === 'development') {
lndPath = join(__dirname, '..', '..', '..', 'resources', 'bin', plat, lndBin)
} else {
lndPath = join(__dirname, '..', '..', '..', 'bin', lndBin)
}
export default {
lightningRpc: `${__dirname}/rpc.proto`,
lightningHost: 'localhost:10009',
cert: join(userInfo().homedir, loc),
macaroon: join(userInfo().homedir, macaroonPath)
lnd: () => ({
lndPath,
lightningRpc: `${__dirname}/rpc.proto`,
lightningHost: store.get('host') || 'localhost:10009',
cert: store.get('cert') || join(userInfo().homedir, loc),
macaroon: store.get('macaroon') || join(userInfo().homedir, macaroonPath)
})
}

18
app/lnd/index.js

@ -1,5 +1,3 @@
import grpc from 'grpc'
import fs from 'fs'
import config from './config'
import lightning from './lib/lightning'
import walletUnlocker from './lib/walletUnlocker'
@ -8,26 +6,24 @@ import methods from './methods'
import walletUnlockerMethods from './walletUnlockerMethods'
const initLnd = (callback) => {
const macaroonFile = fs.readFileSync(config.macaroon)
const meta = new grpc.Metadata()
meta.add('macaroon', macaroonFile.toString('hex'))
const lndConfig = config.lnd()
const lnd = lightning(lndConfig.lightningRpc, lndConfig.lightningHost)
const lnd = lightning(config.lightningRpc, config.lightningHost)
const lndSubscribe = mainWindow => subscribe(mainWindow, lnd, meta)
const lndMethods = (event, msg, data) => methods(lnd, meta, event, msg, data)
const lndSubscribe = mainWindow => subscribe(mainWindow, lnd)
const lndMethods = (event, msg, data) => methods(lnd, event, msg, data)
callback(lndSubscribe, lndMethods)
}
const initWalletUnlocker = (callback) => {
const walletUnlockerObj = walletUnlocker(config.lightningRpc, config.lightningHost)
const lndConfig = config.lnd()
const walletUnlockerObj = walletUnlocker(lndConfig.lightningRpc, lndConfig.lightningHost)
const walletUnlockerMethodsCallback = (event, msg, data) => walletUnlockerMethods(walletUnlockerObj, event, msg, data)
callback(walletUnlockerMethodsCallback)
}
export default {
initLnd,
initWalletUnlocker

12
app/lnd/lib/lightning.js

@ -19,10 +19,18 @@ process.env.GRPC_SSL_CIPHER_SUITES = process.env.GRPC_SSL_CIPHER_SUITES || [
].join(':')
const lightning = (rpcpath, host) => {
const lndCert = fs.readFileSync(config.cert)
const credentials = grpc.credentials.createSsl(lndCert)
const lndConfig = config.lnd()
const lndCert = fs.readFileSync(lndConfig.cert)
const sslCreds = grpc.credentials.createSsl(lndCert)
const rpc = grpc.load(path.join(__dirname, 'rpc.proto'))
const metadata = new grpc.Metadata()
const macaroonHex = fs.readFileSync(lndConfig.macaroon).toString('hex')
metadata.add('macaroon', macaroonHex)
const macaroonCreds = grpc.credentials.createFromMetadataGenerator((params, callback) => callback(null, metadata))
const credentials = grpc.credentials.combineChannelCredentials(sslCreds, macaroonCreds)
return new rpc.lnrpc.Lightning(host, credentials)
}

3
app/lnd/lib/walletUnlocker.js

@ -19,7 +19,8 @@ process.env.GRPC_SSL_CIPHER_SUITES = process.env.GRPC_SSL_CIPHER_SUITES || [
].join(':')
const walletUnlocker = (rpcpath, host) => {
const lndCert = fs.readFileSync(config.cert)
const lndConfig = config.lnd()
const lndCert = fs.readFileSync(lndConfig.cert)
const credentials = grpc.credentials.createSsl(lndCert)
const rpc = grpc.load(path.join(__dirname, 'rpc.proto'))

68
app/lnd/methods/channelController.js

@ -2,15 +2,14 @@ import find from 'lodash/find'
import { listPeers, connectPeer } from './peersController'
import pushopenchannel from '../push/openchannel'
function ensurePeerConnected(lnd, meta, pubkey, host) {
return listPeers(lnd, meta)
.then(({ peers }) => {
const peer = find(peers, { pub_key: pubkey })
if (peer) {
return peer
}
return connectPeer(lnd, meta, { pubkey, host })
})
function ensurePeerConnected(lnd, pubkey, host) {
return listPeers(lnd).then(({ peers }) => {
const peer = find(peers, { pub_key: pubkey })
if (peer) {
return peer
}
return connectPeer(lnd, { pubkey, host })
})
}
/**
@ -20,15 +19,15 @@ function ensurePeerConnected(lnd, meta, pubkey, host) {
* @param {[type]} payload [description]
* @return {[type]} [description]
*/
export function connectAndOpen(lnd, meta, event, payload) {
export function connectAndOpen(lnd, event, payload) {
const { pubkey, host, localamt } = payload
return ensurePeerConnected(lnd, meta, pubkey, host)
return ensurePeerConnected(lnd, pubkey, host)
.then(() => {
const call = lnd.openChannel({
node_pubkey: Buffer.from(pubkey, 'hex'),
local_funding_amount: Number(localamt)
}, meta)
})
call.on('data', data => event.sender.send('pushchannelupdated', { pubkey, data }))
call.on('error', error => event.sender.send('pushchannelerror', { pubkey, error: error.toString() }))
@ -48,7 +47,7 @@ export function connectAndOpen(lnd, meta, event, payload) {
* @param {[type]} payload [description]
* @return {[type]} [description]
*/
export function openChannel(lnd, meta, event, payload) {
export function openChannel(lnd, event, payload) {
const { pubkey, localamt, pushamt } = payload
const res = {
node_pubkey: Buffer.from(pubkey, 'hex'),
@ -57,44 +56,45 @@ export function openChannel(lnd, meta, event, payload) {
}
return new Promise((resolve, reject) =>
pushopenchannel(lnd, meta, event, res)
pushopenchannel(lnd, event, res)
.then(data => resolve(data))
.catch(error => reject(error)))
}
/**
* Returns the total funds available across all open channels in satoshis
* @param {[type]} lnd [description]
* @return {[type]} [description]
*/
export function channelBalance(lnd, meta) {
export function channelBalance(lnd) {
return new Promise((resolve, reject) => {
lnd.channelBalance({}, meta, (err, data) => {
if (err) { reject(err) }
lnd.channelBalance({}, (err, data) => {
if (err) {
reject(err)
}
resolve(data)
})
})
}
/**
* Returns a description of all the open channels that this node is a participant in
* @param {[type]} lnd [description]
* @return {[type]} [description]
*/
export function listChannels(lnd, meta) {
export function listChannels(lnd) {
return new Promise((resolve, reject) => {
lnd.listChannels({}, meta, (err, data) => {
if (err) { reject(err) }
lnd.listChannels({}, (err, data) => {
if (err) {
reject(err)
}
resolve(data)
})
})
}
/**
* Attempts to close an active channel identified by its channel outpoint (ChannelPoint)
* @param {[type]} lnd [description]
@ -102,7 +102,7 @@ export function listChannels(lnd, meta) {
* @param {[type]} payload [description]
* @return {[type]} [description]
*/
export function closeChannel(lnd, meta, event, payload) {
export function closeChannel(lnd, event, payload) {
const { channel_point: { funding_txid, output_index }, chan_id, force } = payload
const tx = funding_txid.match(/.{2}/g).reverse().join('')
@ -116,7 +116,7 @@ export function closeChannel(lnd, meta, event, payload) {
return new Promise((resolve, reject) => {
try {
const call = lnd.closeChannel(res, meta)
const call = lnd.closeChannel(res)
call.on('data', data => event.sender.send('pushclosechannelupdated', { data, chan_id }))
call.on('end', () => event.sender.send('pushclosechannelend'))
@ -130,33 +130,35 @@ export function closeChannel(lnd, meta, event, payload) {
})
}
/**
* Returns a list of all the channels that are currently considered pending"
* @param {[type]} lnd [description]
* @return {[type]} [description]
*/
export function pendingChannels(lnd, meta) {
export function pendingChannels(lnd) {
return new Promise((resolve, reject) => {
lnd.pendingChannels({}, meta, (err, data) => {
if (err) { reject(err) }
lnd.pendingChannels({}, (err, data) => {
if (err) {
reject(err)
}
resolve(data)
})
})
}
/**
* Returns the latest authenticated network announcement for the given channel
* @param {[type]} lnd [description]
* @param {[type]} channelId [description]
* @return {[type]} [description]
*/
export function getChanInfo(lnd, meta, { chanId }) {
export function getChanInfo(lnd, { chanId }) {
return new Promise((resolve, reject) => {
lnd.getChanInfo({ chan_id: chanId }, meta, (err, data) => {
if (err) { reject(err) }
lnd.getChanInfo({ chan_id: chanId }, (err, data) => {
if (err) {
reject(err)
}
resolve(data)
})

122
app/lnd/methods/index.js

@ -18,10 +18,11 @@ import * as networkController from './networkController'
// TODO - SendPayment
// TODO - DeleteAllPayments
export default function (lnd, meta, event, msg, data) {
export default function (lnd, event, msg, data) {
switch (msg) {
case 'info':
networkController.getInfo(lnd, meta)
networkController
.getInfo(lnd)
.then((infoData) => {
event.sender.send('receiveInfo', infoData)
event.sender.send('receiveCryptocurrency', infoData.chains[0])
@ -30,21 +31,24 @@ export default function (lnd, meta, event, msg, data) {
.catch(() => event.sender.send('infoFailed'))
break
case 'describeNetwork':
networkController.describeGraph(lnd, meta)
networkController
.describeGraph(lnd)
.then(networkData => event.sender.send('receiveDescribeNetwork', networkData))
.catch(error => console.log('describeGraph error: ', error))
break
case 'queryRoutes':
// Data looks like { pubkey: String, amount: Number }
networkController.queryRoutes(lnd, meta, data)
// Data looks like { pubkey: String, amount: Number }
networkController
.queryRoutes(lnd, data)
.then(routes => event.sender.send('receiveQueryRoutes', routes))
.catch(error => console.log('queryRoutes error: ', error))
break
case 'getInvoiceAndQueryRoutes':
// Data looks like { pubkey: String, amount: Number }
invoicesController.getInvoice(lnd, meta, { pay_req: data.payreq })
// Data looks like { pubkey: String, amount: Number }
invoicesController
.getInvoice(lnd, { pay_req: data.payreq })
.then(invoiceData =>
networkController.queryRoutes(lnd, meta, {
networkController.queryRoutes(lnd, {
pubkey: invoiceData.destination,
amount: invoiceData.num_satoshis
}))
@ -53,57 +57,63 @@ export default function (lnd, meta, event, msg, data) {
break
case 'newaddress':
// Data looks like { address: '' }
walletController.newAddress(lnd, meta, data.type)
walletController
.newAddress(lnd, data.type)
.then(({ address }) => event.sender.send('receiveAddress', address))
.catch(error => console.log('newaddress error: ', error))
break
case 'setAlias':
// Data looks like { new_alias: '' }
walletController.setAlias(lnd, meta, data)
// Data looks like { new_alias: '' }
walletController
.setAlias(lnd, data)
.then(() => event.sender.send('aliasSet'))
.catch(error => console.log('setAlias error: ', error))
break
case 'peers':
// Data looks like { peers: [] }
peersController.listPeers(lnd, meta)
// Data looks like { peers: [] }
peersController
.listPeers(lnd)
.then(peersData => event.sender.send('receivePeers', peersData))
.catch(error => console.log('peers error: ', error))
break
case 'channels':
// Data looks like
// [ { channels: [] }, { total_limbo_balance: 0, pending_open_channels: [], pending_closing_channels: [], pending_force_closing_channels: [] } ]
Promise.all([channelController.listChannels, channelController.pendingChannels].map(func => func(lnd, meta)))
.then(channelsData =>
event.sender.send('receiveChannels', { channels: channelsData[0].channels, pendingChannels: channelsData[1] }))
// Data looks like
// [ { channels: [] }, { total_limbo_balance: 0, pending_open_channels: [], pending_closing_channels: [], pending_force_closing_channels: [] } ]
Promise.all([channelController.listChannels, channelController.pendingChannels].map(func => func(lnd)))
.then(channelsData => event.sender.send('receiveChannels', { channels: channelsData[0].channels, pendingChannels: channelsData[1] }))
.catch(error => console.log('channels error: ', error))
break
case 'transactions':
// Data looks like { transactions: [] }
walletController.getTransactions(lnd, meta)
// Data looks like { transactions: [] }
walletController
.getTransactions(lnd)
.then(transactionsData => event.sender.send('receiveTransactions', transactionsData))
.catch(error => console.log('transactions error: ', error))
break
case 'payments':
// Data looks like { payments: [] }
paymentsController.listPayments(lnd, meta)
// Data looks like { payments: [] }
paymentsController
.listPayments(lnd)
.then(paymentsData => event.sender.send('receivePayments', paymentsData))
.catch(error => console.log('payments error: ', error))
break
case 'invoices':
// Data looks like { invoices: [] }
invoicesController.listInvoices(lnd, meta)
// Data looks like { invoices: [] }
invoicesController
.listInvoices(lnd)
.then(invoicesData => event.sender.send('receiveInvoices', invoicesData))
.catch(error => console.log('invoices error: ', error))
break
case 'invoice':
// Data looks like { invoices: [] }
invoicesController.getInvoice(lnd, meta, { pay_req: data.payreq })
// Data looks like { invoices: [] }
invoicesController
.getInvoice(lnd, { pay_req: data.payreq })
.then(invoiceData => event.sender.send('receiveInvoice', invoiceData))
.catch(error => console.log('invoice error: ', error))
break
case 'balance':
// Balance looks like [ { balance: '129477456' }, { balance: '243914' } ]
Promise.all([walletController.walletBalance, channelController.channelBalance].map(func => func(lnd, meta)))
// Balance looks like [ { balance: '129477456' }, { balance: '243914' } ]
Promise.all([walletController.walletBalance, channelController.channelBalance].map(func => func(lnd)))
.then((balance) => {
event.sender.send('receiveBalance', { walletBalance: balance[0].total_balance, channelBalance: balance[1].balance })
return balance
@ -111,9 +121,10 @@ export default function (lnd, meta, event, msg, data) {
.catch(error => console.log('balance error: ', error))
break
case 'createInvoice':
// Invoice looks like { r_hash: Buffer, payment_request: '' }
// { memo, value } = data
invoicesController.addInvoice(lnd, meta, data)
// Invoice looks like { r_hash: Buffer, payment_request: '' }
// { memo, value } = data
invoicesController
.addInvoice(lnd, data)
.then(newinvoice =>
event.sender.send(
'createdInvoice',
@ -130,9 +141,10 @@ export default function (lnd, meta, event, msg, data) {
})
break
case 'sendPayment':
// Payment looks like { payment_preimage: Buffer, payment_route: Object }
// { paymentRequest } = data
paymentsController.sendPaymentSync(lnd, meta, data)
// Payment looks like { payment_preimage: Buffer, payment_route: Object }
// { paymentRequest } = data
paymentsController
.sendPaymentSync(lnd, data)
.then((payment) => {
const { payment_route } = payment
console.log('payinvoice success: ', payment_route)
@ -145,9 +157,10 @@ export default function (lnd, meta, event, msg, data) {
})
break
case 'sendCoins':
// Transaction looks like { txid: String }
// { amount, addr } = data
walletController.sendCoins(lnd, meta, data)
// Transaction looks like { txid: String }
// { amount, addr } = data
walletController
.sendCoins(lnd, data)
.then(({ txid }) => event.sender.send('transactionSuccessful', { amount: data.amount, addr: data.addr, txid }))
.catch((error) => {
console.log('error: ', error)
@ -155,9 +168,10 @@ export default function (lnd, meta, event, msg, data) {
})
break
case 'openChannel':
// Response is empty. Streaming updates on channel status and updates
// { pubkey, localamt, pushamt } = data
channelController.openChannel(lnd, meta, event, data)
// Response is empty. Streaming updates on channel status and updates
// { pubkey, localamt, pushamt } = data
channelController
.openChannel(lnd, event, data)
.then((channel) => {
console.log('CHANNEL: ', channel)
event.sender.send('channelSuccessful', { channel })
@ -166,9 +180,10 @@ export default function (lnd, meta, event, msg, data) {
.catch(error => console.log('openChannel error: ', error))
break
case 'closeChannel':
// Response is empty. Streaming updates on channel status and updates
// { channel_point, force } = data
channelController.closeChannel(lnd, meta, event, data)
// Response is empty. Streaming updates on channel status and updates
// { channel_point, force } = data
channelController
.closeChannel(lnd, event, data)
.then((result) => {
console.log('CLOSE CHANNEL: ', result)
event.sender.send('closeChannelSuccessful')
@ -177,9 +192,10 @@ export default function (lnd, meta, event, msg, data) {
.catch(error => console.log('closeChannel error: ', error))
break
case 'connectPeer':
// Returns a peer_id. Pass the pubkey, host and peer_id so we can add a new peer to the list
// { pubkey, host } = data
peersController.connectPeer(lnd, meta, data)
// Returns a peer_id. Pass the pubkey, host and peer_id so we can add a new peer to the list
// { pubkey, host } = data
peersController
.connectPeer(lnd, data)
.then((peer) => {
const { peer_id } = peer
console.log('peer_id: ', peer_id)
@ -192,9 +208,10 @@ export default function (lnd, meta, event, msg, data) {
})
break
case 'disconnectPeer':
// Empty response. Pass back pubkey on success to remove it from the peers list
// { pubkey } = data
peersController.disconnectPeer(lnd, meta, data)
// Empty response. Pass back pubkey on success to remove it from the peers list
// { pubkey } = data
peersController
.disconnectPeer(lnd, data)
.then(() => {
console.log('pubkey: ', data.pubkey)
event.sender.send('disconnectSuccess', { pubkey: data.pubkey })
@ -203,9 +220,10 @@ export default function (lnd, meta, event, msg, data) {
.catch(error => console.log('disconnectPeer error: ', error))
break
case 'connectAndOpen':
// Connects to a peer if we aren't connected already and then attempt to open a channel
// {} = data
channelController.connectAndOpen(lnd, meta, event, data)
// Connects to a peer if we aren't connected already and then attempt to open a channel
// {} = data
channelController
.connectAndOpen(lnd, event, data)
.then((channelData) => {
console.log('connectAndOpen data: ', channelData)
// event.sender.send('connectSuccess', { pub_key: data.pubkey, address: data.host, peer_id })

20
app/lnd/methods/invoicesController.js

@ -7,9 +7,9 @@ import pushinvoices from '../push/subscribeinvoice'
* @param value [description]
* @return [description]
*/
export function addInvoice(lnd, meta, { memo, value }) {
export function addInvoice(lnd, { memo, value }) {
return new Promise((resolve, reject) => {
lnd.addInvoice({ memo, value }, meta, (err, data) => {
lnd.addInvoice({ memo, value }, (err, data) => {
if (err) { reject(err) }
resolve(data)
@ -22,9 +22,9 @@ export function addInvoice(lnd, meta, { memo, value }) {
* @param {[type]} lnd [description]
* @return {[type]} [description]
*/
export function listInvoices(lnd, meta) {
export function listInvoices(lnd) {
return new Promise((resolve, reject) => {
lnd.listInvoices({}, meta, (err, data) => {
lnd.listInvoices({}, (err, data) => {
if (err) { reject(err) }
resolve(data)
@ -36,9 +36,9 @@ export function listInvoices(lnd, meta) {
* @param {[type]} payreq [description]
* @return {[type]} [description]
*/
export function getInvoice(lnd, meta, { pay_req }) {
export function getInvoice(lnd, { pay_req }) {
return new Promise((resolve, reject) => {
lnd.decodePayReq({ pay_req }, meta, (err, data) => {
lnd.decodePayReq({ pay_req }, (err, data) => {
if (err) { reject(err) }
resolve(data)
@ -53,9 +53,9 @@ export function getInvoice(lnd, meta, { pay_req }) {
* @param {[type]} rhash [description]
* @return {[type]} [description]
*/
export function lookupInvoice(lnd, meta, { rhash }) {
export function lookupInvoice(lnd, { rhash }) {
return new Promise((resolve, reject) => {
lnd.lookupInvoice({ r_hash: rhash }, meta, (err, data) => {
lnd.lookupInvoice({ r_hash: rhash }, (err, data) => {
if (err) { reject(err) }
resolve(data)
@ -70,9 +70,9 @@ export function lookupInvoice(lnd, meta, { rhash }) {
* @param {[type]} event [description]
* @return {[type]} [description]
*/
export function subscribeInvoices(lnd, meta, event) {
export function subscribeInvoices(lnd, event) {
return new Promise((resolve, reject) => {
pushinvoices(lnd, meta, event)
pushinvoices(lnd, event)
.then(data => resolve(data))
.catch(error => reject(error))
})

20
app/lnd/methods/networkController.js

@ -3,9 +3,9 @@
* @param {[type]} lnd [description]
* @return {[type]} [description]
*/
export function getInfo(lnd, meta) {
export function getInfo(lnd) {
return new Promise((resolve, reject) => {
lnd.getInfo({}, meta, (err, data) => {
lnd.getInfo({}, (err, data) => {
if (err) { reject(err) }
resolve(data)
@ -20,9 +20,9 @@ export function getInfo(lnd, meta) {
* @param {[type]} pubkey [description]
* @return {[type]} [description]
*/
export function getNodeInfo(lnd, meta, { pubkey }) {
export function getNodeInfo(lnd, { pubkey }) {
return new Promise((resolve, reject) => {
lnd.getNodeInfo({ pub_key: pubkey }, meta, (err, data) => {
lnd.getNodeInfo({ pub_key: pubkey }, (err, data) => {
if (err) { reject(err) }
resolve(data)
@ -36,9 +36,9 @@ export function getNodeInfo(lnd, meta, { pubkey }) {
* @param {[type]} lnd [description]
* @return {[type]} [description]
*/
export function describeGraph(lnd, meta) {
export function describeGraph(lnd) {
return new Promise((resolve, reject) => {
lnd.describeGraph({}, meta, (err, data) => {
lnd.describeGraph({}, (err, data) => {
if (err) { reject(err) }
resolve(data)
@ -54,9 +54,9 @@ export function describeGraph(lnd, meta) {
* @param {[type]} amount [description]
* @return {[type]} [description]
*/
export function queryRoutes(lnd, meta, { pubkey, amount }) {
export function queryRoutes(lnd, { pubkey, amount }) {
return new Promise((resolve, reject) => {
lnd.queryRoutes({ pub_key: pubkey, amt: amount }, meta, (err, data) => {
lnd.queryRoutes({ pub_key: pubkey, amt: amount }, (err, data) => {
if (err) { reject(err) }
resolve(data)
@ -70,9 +70,9 @@ export function queryRoutes(lnd, meta, { pubkey, amount }) {
* @param {[type]} lnd [description]
* @return {[type]} [description]
*/
export function getNetworkInfo(lnd, meta) {
export function getNetworkInfo(lnd) {
return new Promise((resolve, reject) => {
lnd.getNetworkInfo({}, meta, (err, data) => {
lnd.getNetworkInfo({}, (err, data) => {
if (err) { reject(err) }
resolve(data)

20
app/lnd/methods/paymentsController.js

@ -4,9 +4,9 @@
* @param {[type]} paymentRequest [description]
* @return {[type]} [description]
*/
export function sendPaymentSync(lnd, meta, { paymentRequest }) {
export function sendPaymentSync(lnd, { paymentRequest }) {
return new Promise((resolve, reject) => {
lnd.sendPaymentSync({ payment_request: paymentRequest }, meta, (error, data) => {
lnd.sendPaymentSync({ payment_request: paymentRequest }, (error, data) => {
if (error) {
reject({ error })
return
@ -27,9 +27,9 @@ export function sendPaymentSync(lnd, meta, { paymentRequest }) {
* @param {[type]} paymentRequest [description]
* @return {[type]} [description]
*/
export function sendPayment(lnd, meta, { paymentRequest }) {
export function sendPayment(lnd, { paymentRequest }) {
return new Promise((resolve, reject) => {
lnd.sendPayment({ payment_request: paymentRequest }, meta, (err, data) => {
lnd.sendPayment({ payment_request: paymentRequest }, (err, data) => {
if (err) { reject(err) }
resolve(data)
@ -43,9 +43,9 @@ export function sendPayment(lnd, meta, { paymentRequest }) {
* @param {[type]} payReq [description]
* @return {[type]} [description]
*/
export function decodePayReq(lnd, meta, { payReq }) {
export function decodePayReq(lnd, { payReq }) {
return new Promise((resolve, reject) => {
lnd.decodePayReq({ pay_req: payReq }, meta, (err, data) => {
lnd.decodePayReq({ pay_req: payReq }, (err, data) => {
if (err) { reject(err) }
resolve(data)
@ -58,9 +58,9 @@ export function decodePayReq(lnd, meta, { payReq }) {
* @param {[type]} lnd [description]
* @return {[type]} [description]
*/
export function listPayments(lnd, meta) {
export function listPayments(lnd) {
return new Promise((resolve, reject) => {
lnd.listPayments({}, meta, (err, data) => {
lnd.listPayments({}, (err, data) => {
if (err) { reject(err) }
resolve(data)
@ -73,9 +73,9 @@ export function listPayments(lnd, meta) {
* @param {[type]} lnd [description]
* @return {[type]} [description]
*/
export function deleteAllPayments(lnd, meta) {
export function deleteAllPayments(lnd) {
return new Promise((resolve, reject) => {
lnd.deleteAllPayments({}, meta, (err, data) => {
lnd.deleteAllPayments({}, (err, data) => {
if (err) { reject(err) }
resolve(data)

12
app/lnd/methods/peersController.js

@ -5,9 +5,9 @@
* @param {[type]} host [description]
* @return {[type]} [description]
*/
export function connectPeer(lnd, meta, { pubkey, host }) {
export function connectPeer(lnd, { pubkey, host }) {
return new Promise((resolve, reject) => {
lnd.connectPeer({ addr: { pubkey, host } }, meta, (err, data) => {
lnd.connectPeer({ addr: { pubkey, host } }, (err, data) => {
if (err) { reject(err) }
resolve(data)
@ -22,9 +22,9 @@ export function connectPeer(lnd, meta, { pubkey, host }) {
* @param {[type]} pubkey [description]
* @return {[type]} [description]
*/
export function disconnectPeer(lnd, meta, { pubkey }) {
export function disconnectPeer(lnd, { pubkey }) {
return new Promise((resolve, reject) => {
lnd.disconnectPeer({ pub_key: pubkey }, meta, (err, data) => {
lnd.disconnectPeer({ pub_key: pubkey }, (err, data) => {
if (err) { reject(err) }
resolve(data)
@ -38,9 +38,9 @@ export function disconnectPeer(lnd, meta, { pubkey }) {
* @param {[type]} lnd [description]
* @return {[type]} [description]
*/
export function listPeers(lnd, meta) {
export function listPeers(lnd) {
return new Promise((resolve, reject) => {
lnd.listPeers({}, meta, (err, data) => {
lnd.listPeers({}, (err, data) => {
if (err) { reject(err) }
resolve(data)

22
app/lnd/methods/walletController.js

@ -3,9 +3,9 @@
* @param {[type]} lnd [description]
* @return {[type]} [description]
*/
export function walletBalance(lnd, meta) {
export function walletBalance(lnd) {
return new Promise((resolve, reject) => {
lnd.walletBalance({}, meta, (err, data) => {
lnd.walletBalance({}, (err, data) => {
if (err) { reject(err) }
resolve(data)
@ -20,9 +20,9 @@ export function walletBalance(lnd, meta) {
* @param {[type]} type [description]
* @return {[type]} [description]
*/
export function newAddress(lnd, meta, type) {
export function newAddress(lnd, type) {
return new Promise((resolve, reject) => {
lnd.newAddress({ type }, meta, (err, data) => {
lnd.newAddress({ type }, (err, data) => {
if (err) { reject(err) }
resolve(data)
@ -35,9 +35,9 @@ export function newAddress(lnd, meta, type) {
* @param {[type]} lnd [description]
* @return {[type]} [description]
*/
export function newWitnessAddress(lnd, meta, { addr }) {
export function newWitnessAddress(lnd, { addr }) {
return new Promise((resolve, reject) => {
lnd.newWitnessAddress({ address: addr }, meta, (err, data) => {
lnd.newWitnessAddress({ address: addr }, (err, data) => {
if (err) { reject(err) }
resolve(data)
@ -51,9 +51,9 @@ export function newWitnessAddress(lnd, meta, { addr }) {
* @param {[type]} lnd [description]
* @return {[type]} [description]
*/
export function getTransactions(lnd, meta) {
export function getTransactions(lnd) {
return new Promise((resolve, reject) => {
lnd.getTransactions({}, meta, (err, data) => {
lnd.getTransactions({}, (err, data) => {
if (err) { reject(err) }
resolve(data)
@ -69,9 +69,9 @@ export function getTransactions(lnd, meta) {
* @param {[type]} amount [description]
* @return {[type]} [description]
*/
export function sendCoins(lnd, meta, { addr, amount }) {
export function sendCoins(lnd, { addr, amount }) {
return new Promise((resolve, reject) => {
lnd.sendCoins({ addr, amount }, meta, (err, data) => {
lnd.sendCoins({ addr, amount }, (err, data) => {
if (err) { reject(err) }
resolve(data)
@ -83,7 +83,7 @@ export function sendCoins(lnd, meta, { addr, amount }) {
* Executes a request to set the alias for the node
* @param {[type]} new_alias [description]
*/
export function setAlias(lnd, meta, { new_alias }) {
export function setAlias(lnd, { new_alias }) {
return new Promise((resolve, reject) => {
lnd.setAlias({ new_alias }, (err, data) => {
if (err) { reject(err) }

4
app/lnd/push/closechannel.js

@ -1,7 +1,7 @@
export default function pushclosechannel(lnd, meta, event, payload) {
export default function pushclosechannel(lnd, event, payload) {
return new Promise((resolve, reject) => {
try {
const call = lnd.closeChannel(payload, meta)
const call = lnd.closeChannel(payload)
call.on('data', data => event.sender.send('pushclosechannelupdated', { data }))
call.on('end', () => event.sender.send('pushclosechannelend'))

4
app/lnd/push/openchannel.js

@ -1,7 +1,7 @@
export default function pushopenchannel(lnd, meta, event, payload) {
export default function pushopenchannel(lnd, event, payload) {
return new Promise((resolve, reject) => {
try {
const call = lnd.openChannel(payload, meta)
const call = lnd.openChannel(payload)
call.on('data', data => event.sender.send('pushchannelupdated', { data }))
call.on('end', () => event.sender.send('pushchannelend'))

4
app/lnd/push/subscribeinvoice.js

@ -1,7 +1,7 @@
export default function pushinvoices(lnd, meta, event) {
export default function pushinvoices(lnd, event) {
return new Promise((resolve, reject) => {
try {
const call = lnd.subscribeInvoices({}, meta)
const call = lnd.subscribeInvoices({})
call.on('data', data => event.sender.send('pushinvoicesupdated', { data }))
call.on('end', () => event.sender.send('pushinvoicesend'))

4
app/lnd/subscribe/channelgraph.js

@ -1,5 +1,5 @@
export default function subscribeToChannelGraph(mainWindow, lnd, meta) {
const call = lnd.subscribeChannelGraph({}, meta)
export default function subscribeToChannelGraph(mainWindow, lnd) {
const call = lnd.subscribeChannelGraph({})
call.on('data', channelGraphData => mainWindow.send('channelGraphData', { channelGraphData }))
call.on('status', channelGraphStatus => mainWindow.send('channelGraphStatus', { channelGraphStatus }))

8
app/lnd/subscribe/index.js

@ -2,8 +2,8 @@ import subscribeToTransactions from './transactions'
import subscribeToInvoices from './invoices'
import subscribeToChannelGraph from './channelgraph'
export default (mainWindow, lnd, meta) => {
subscribeToTransactions(mainWindow, lnd, meta)
subscribeToInvoices(mainWindow, lnd, meta)
subscribeToChannelGraph(mainWindow, lnd, meta)
export default (mainWindow, lnd) => {
subscribeToTransactions(mainWindow, lnd)
subscribeToInvoices(mainWindow, lnd)
subscribeToChannelGraph(mainWindow, lnd)
}

4
app/lnd/subscribe/invoices.js

@ -1,5 +1,5 @@
export default function subscribeToInvoices(mainWindow, lnd, meta) {
const call = lnd.subscribeInvoices({}, meta)
export default function subscribeToInvoices(mainWindow, lnd) {
const call = lnd.subscribeInvoices({})
call.on('data', invoice => mainWindow.send('invoiceUpdate', { invoice }))
call.on('end', () => console.log('end'))

4
app/lnd/subscribe/transactions.js

@ -1,5 +1,5 @@
export default function subscribeToTransactions(mainWindow, lnd, meta) {
const call = lnd.subscribeTransactions({}, meta)
export default function subscribeToTransactions(mainWindow, lnd) {
const call = lnd.subscribeTransactions({})
call.on('data', (transaction) => {
console.log('TRANSACTION: ', transaction)
mainWindow.send('newTransaction', { transaction })

106
app/main.dev.js

@ -15,12 +15,11 @@ import path from 'path'
import fs from 'fs'
import { spawn } from 'child_process'
import { lookup } from 'ps-node'
import os from 'os'
import Store from 'electron-store'
import MenuBuilder from './menu'
import lnd from './lnd'
import config from './lnd/config'
const plat = os.platform()
const homedir = os.homedir()
let mainWindow = null
let didFinishLoad = false
@ -28,8 +27,6 @@ let didFinishLoad = false
let startedSync = false
let sentGrpcDisconnect = false
let certPath
if (process.env.NODE_ENV === 'production') {
const sourceMapSupport = require('source-map-support')
sourceMapSupport.install()
@ -44,17 +41,12 @@ if (process.env.NODE_ENV === 'development' || process.env.DEBUG_PROD === 'true')
const installExtensions = async () => {
const installer = require('electron-devtools-installer')
const forceDownload = !!process.env.UPGRADE_EXTENSIONS
const extensions = [
'REACT_DEVELOPER_TOOLS',
'REDUX_DEVTOOLS'
]
const extensions = ['REACT_DEVELOPER_TOOLS', 'REDUX_DEVTOOLS']
return Promise
.all(extensions.map(name => installer.default(installer[name], forceDownload)))
.catch(console.log)
return Promise.all(extensions.map(name => installer.default(installer[name], forceDownload))).catch(console.log)
}
// Send the front end event letting them know the gRPC connection has started
// Send the front end event letting them know the gRPC connection is disconnected
const sendGrpcDisconnected = () => {
const sendGrpcDisonnectedInterval = setInterval(() => {
if (didFinishLoad) {
@ -152,13 +144,8 @@ const sendLndSynced = () => {
// Starts the LND node
const startLnd = (alias, autopilot) => {
let lndPath
if (process.env.NODE_ENV === 'development') {
lndPath = path.join(__dirname, '..', 'resources', 'bin', plat, plat === 'win32' ? 'lnd.exe' : 'lnd')
} else {
lndPath = path.join(__dirname, '..', 'bin', plat === 'win32' ? 'lnd.exe' : 'lnd')
}
const lndConfig = config.lnd()
console.log('lndConfig', lndConfig)
const neutrinoArgs = [
'--bitcoin.active',
@ -171,7 +158,7 @@ const startLnd = (alias, autopilot) => {
`${alias ? `--alias=${alias}` : ''}`
]
const neutrino = spawn(lndPath, neutrinoArgs)
const neutrino = spawn(lndConfig.lndPath, neutrinoArgs)
.on('error', error => console.log(`lnd error: ${error}`))
.on('close', code => console.log(`lnd shutting down ${code}`))
@ -180,12 +167,15 @@ const startLnd = (alias, autopilot) => {
// Data stored in variable line, log line to the console
const line = data.toString('utf8')
if (process.env.NODE_ENV === 'development') { console.log(line) }
if (process.env.NODE_ENV === 'development') {
console.log(line)
}
// If the gRPC proxy has started we can start ours
if (line.includes('gRPC proxy started')) {
const certInterval = setInterval(() => {
if (fs.existsSync(certPath)) {
console.log('lndConfig', lndConfig)
if (fs.existsSync(lndConfig.cert)) {
clearInterval(certInterval)
console.log('CERT EXISTS, STARTING WALLET UNLOCKER')
@ -233,7 +223,6 @@ app.on('window-all-closed', () => {
}
})
app.on('ready', async () => {
if (process.env.NODE_ENV === 'development' || process.env.DEBUG_PROD === 'true') {
await installExtensions()
@ -275,40 +264,49 @@ app.on('ready', async () => {
menuBuilder.buildMenu()
sendGrpcDisconnected()
// Check to see if an LND process is running
lookup({ command: 'lnd' }, (err, results) => {
// There was an error checking for the LND process
if (err) { throw new Error(err) }
// No LND process was found
if (!results.length) {
// let the application know onboarding has started
sendStartOnboarding()
// Assign path to certs to certPath
switch (os.platform()) {
case 'darwin':
certPath = path.join(homedir, 'Library/Application Support/Lnd/tls.cert')
break
case 'linux':
certPath = path.join(homedir, '.lnd/tls.cert')
break
case 'win32':
certPath = path.join(homedir, 'AppData', 'Local', 'Lnd', 'tls.cert')
break
default:
break
}
// Start LND
// once the onboarding has finished we wanna let the application we have started syncing and start LND
ipcMain.on('startLnd', (event, { alias, autopilot }) => {
startLnd(alias, autopilot)
// Let the application know onboarding has started.
sendStartOnboarding()
// Start LND
// once the onboarding has enough information, start or connect to LND.
ipcMain.on('startLnd', (event, options = {}) => {
console.log('STARTING LND', options)
const store = new Store({ name: 'connection' })
store.store = {
type: options.connectionType,
host: options.connectionHost,
cert: options.connectionCert,
macaroon: options.connectionMacaroon,
alias: options.alias,
autopilot: options.autopilot
}
console.log('SAVED CONFIG TO:', store.pathm, 'AS', store.store)
if (options.connectionType === 'local') {
console.log('LOOKING FOR LOCAL LND')
// Check to see if an LND process is running.
lookup({ command: 'lnd' }, (err, results) => {
// There was an error checking for the LND process.
if (err) {
throw new Error(err)
}
// No LND process was found.
if (!results.length) {
startLnd(options.alias, options.autopilot)
} else {
// An LND process was found, no need to start our own.
console.log('LND ALREADY RUNNING')
startGrpc()
}
})
} else {
// An LND process was found, no need to start our own
console.log('LND ALREADY RUNNING')
console.log('USING CUSTOM LND')
startGrpc()
mainWindow.webContents.send('successfullyCreatedWallet')
}
})
})

57
app/reducers/onboarding.js

@ -1,9 +1,17 @@
import { createSelector } from 'reselect'
import { ipcRenderer } from 'electron'
import Store from 'electron-store'
const store = new Store({ name: 'connection' })
// ------------------------------------
// Constants
// ------------------------------------
export const SET_CONNECTION_TYPE = 'SET_CONNECTION_TYPE'
export const SET_CONNECTION_HOST = 'SET_CONNECTION_HOST'
export const SET_CONNECTION_CERT = 'SET_CONNECTION_CERT'
export const SET_CONNECTION_MACAROON = 'SET_CONNECTION_MACAROON'
export const UPDATE_ALIAS = 'UPDATE_ALIAS'
export const UPDATE_PASSWORD = 'UPDATE_PASSWORD'
export const UPDATE_CREATE_WALLET_PASSWORD = 'UPDATE_CREATE_WALLET_PASSWORD'
@ -37,6 +45,32 @@ export const SET_SIGNUP_IMPORT = 'SET_SIGNUP_IMPORT'
// ------------------------------------
// Actions
// ------------------------------------
export function setConnectionType(connectionType) {
return {
type: SET_CONNECTION_TYPE,
connectionType
}
}
export function setConnectionHost(connectionHost) {
return {
type: SET_CONNECTION_HOST,
connectionHost
}
}
export function setConnectionCert(connectionCert) {
return {
type: SET_CONNECTION_CERT,
connectionCert
}
}
export function setConnectionMacaroon(connectionMacaroon) {
return {
type: SET_CONNECTION_MACAROON,
connectionMacaroon
}
}
export function updateAlias(alias) {
return {
type: UPDATE_ALIAS,
@ -112,9 +146,9 @@ export function changeStep(step) {
}
}
export function startLnd(alias, autopilot) {
export function startLnd(options) {
// once the user submits the data needed to start LND we will alert the app that it should start LND
ipcRenderer.send('startLnd', { alias, autopilot })
ipcRenderer.send('startLnd', options)
return {
type: STARTING_LND
@ -177,6 +211,10 @@ export const unlockWalletError = () => (dispatch) => {
// Action Handlers
// ------------------------------------
const ACTION_HANDLERS = {
[SET_CONNECTION_TYPE]: (state, { connectionType }) => ({ ...state, connectionType }),
[SET_CONNECTION_HOST]: (state, { connectionHost }) => ({ ...state, connectionHost }),
[SET_CONNECTION_CERT]: (state, { connectionCert }) => ({ ...state, connectionCert }),
[SET_CONNECTION_MACAROON]: (state, { connectionMacaroon }) => ({ ...state, connectionMacaroon }),
[UPDATE_ALIAS]: (state, { alias }) => ({ ...state, alias }),
[UPDATE_PASSWORD]: (state, { password }) => ({ ...state, password }),
[UPDATE_CREATE_WALLET_PASSWORD]: (state, { createWalletPassword }) => ({ ...state, createWalletPassword }),
@ -223,10 +261,7 @@ const aezeedPasswordConfirmationSelector = state => state.onboarding.aezeedPassw
const seedSelector = state => state.onboarding.seed
const seedInputSelector = state => state.onboarding.seedInput
onboardingSelectors.passwordIsValid = createSelector(
passwordSelector,
password => password.length >= 8
)
onboardingSelectors.passwordIsValid = createSelector(passwordSelector, password => password.length >= 8)
onboardingSelectors.showCreateWalletPasswordConfirmationError = createSelector(
createWalletPasswordSelector,
@ -253,8 +288,12 @@ export { onboardingSelectors }
// ------------------------------------
const initialState = {
onboarded: true,
step: 1,
alias: '',
step: 0.1,
connectionType: store.get('type', ''),
connectionHost: store.get('host', ''),
connectionCert: store.get('cert', ''),
connectionMacaroon: store.get('macaroon', ''),
alias: store.get('alias', ''),
password: '',
startingLnd: false,
@ -287,7 +326,7 @@ const initialState = {
import: false
},
autopilot: null
autopilot: store.get('autopilot', null)
}
// ------------------------------------

1
package.json

@ -213,6 +213,7 @@
"devtron": "^1.4.0",
"electron": "1.8.4",
"electron-debug": "^1.2.0",
"electron-store": "^1.3.0",
"font-awesome": "^4.7.0",
"history": "^4.6.3",
"lodash": "^4.17.4",

30
yarn.lock

@ -2469,6 +2469,16 @@ concurrently@^3.5.0:
supports-color "^3.2.3"
tree-kill "^1.1.0"
conf@^1.3.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/conf/-/conf-1.4.0.tgz#1ea66c9d7a9b601674a5bb9d2b8dc3c726625e67"
dependencies:
dot-prop "^4.1.0"
env-paths "^1.0.0"
make-dir "^1.0.0"
pkg-up "^2.0.0"
write-file-atomic "^2.3.0"
configstore@^3.0.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/configstore/-/configstore-3.1.0.tgz#45df907073e26dfa1cf4b2d52f5b60545eaa11d1"
@ -3405,6 +3415,12 @@ electron-releases@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/electron-releases/-/electron-releases-2.1.0.tgz#c5614bf811f176ce3c836e368a0625782341fd4e"
electron-store@^1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/electron-store/-/electron-store-1.3.0.tgz#ee488a28a61fb982fd35b658fb9cb6331eb201f8"
dependencies:
conf "^1.3.0"
electron-to-chromium@^1.2.7, electron-to-chromium@^1.3.11:
version "1.3.14"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.14.tgz#64af0f9efd3c3c6acd57d71f83b49ca7ee9c4b43"
@ -7324,6 +7340,12 @@ pkg-dir@^2.0.0:
dependencies:
find-up "^2.1.0"
pkg-up@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/pkg-up/-/pkg-up-2.0.0.tgz#c819ac728059a461cab1c3889a2be3c49a004d7f"
dependencies:
find-up "^2.1.0"
plist@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/plist/-/plist-2.1.0.tgz#57ccdb7a0821df21831217a3cad54e3e146a1025"
@ -10266,6 +10288,14 @@ write-file-atomic@^2.0.0:
imurmurhash "^0.1.4"
slide "^1.1.5"
write-file-atomic@^2.3.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-2.3.0.tgz#1ff61575c2e2a4e8e510d6fa4e243cce183999ab"
dependencies:
graceful-fs "^4.1.11"
imurmurhash "^0.1.4"
signal-exit "^3.0.2"
write@^0.2.1:
version "0.2.1"
resolved "https://registry.yarnpkg.com/write/-/write-0.2.1.tgz#5fc03828e264cea3fe91455476f7a3c566cb0757"

Loading…
Cancel
Save