|
|
@ -16,15 +16,20 @@ import fs from 'fs' |
|
|
|
import path from 'path' |
|
|
|
import { spawn, exec } from 'child_process' |
|
|
|
import { lookup } from 'ps-node' |
|
|
|
import { platform } from 'os' |
|
|
|
import os from 'os' |
|
|
|
import MenuBuilder from './menu' |
|
|
|
import lnd from './lnd' |
|
|
|
|
|
|
|
const plat = platform() |
|
|
|
const plat = os.platform() |
|
|
|
const homedir = os.homedir() |
|
|
|
let mainWindow = null |
|
|
|
let neutrino = null |
|
|
|
let syncing = false |
|
|
|
|
|
|
|
let lndPath |
|
|
|
let certPath |
|
|
|
let certInterval |
|
|
|
|
|
|
|
|
|
|
|
if (process.env.NODE_ENV === 'production') { |
|
|
|
const sourceMapSupport = require('source-map-support'); |
|
|
@ -60,9 +65,9 @@ app.on('window-all-closed', () => { |
|
|
|
// Respect the OSX convention of having the application in memory even
|
|
|
|
// after all windows have been closed
|
|
|
|
if (process.platform !== 'darwin') { |
|
|
|
app.quit(); |
|
|
|
app.quit() |
|
|
|
} |
|
|
|
}); |
|
|
|
}) |
|
|
|
|
|
|
|
|
|
|
|
app.on('ready', async () => { |
|
|
@ -73,11 +78,11 @@ app.on('ready', async () => { |
|
|
|
mainWindow = new BrowserWindow({ |
|
|
|
show: false, |
|
|
|
frame: false |
|
|
|
}); |
|
|
|
}) |
|
|
|
|
|
|
|
mainWindow.maximize(); |
|
|
|
|
|
|
|
mainWindow.loadURL(`file://${__dirname}/app.html`); |
|
|
|
mainWindow.loadURL(`file://${__dirname}/app.html`) |
|
|
|
|
|
|
|
// @TODO: Use 'ready-to-show' event
|
|
|
|
// https://github.com/electron/electron/blob/master/docs/api/browser-window.md#using-ready-to-show-event
|
|
|
@ -111,73 +116,33 @@ app.on('ready', async () => { |
|
|
|
if (!results.length) { |
|
|
|
// Let the front end know we have started syncing LND
|
|
|
|
syncing = true |
|
|
|
// Run a bash script that checks for the LND folder and generates Node.js compatible certs
|
|
|
|
console.log('CHECKING/GENERATING CERTS') |
|
|
|
exec(`sh ${path.join(__dirname, '..', 'resources', 'scripts', `${plat}_generate_certs.sh`)}`) |
|
|
|
|
|
|
|
// After the certs are generated, it's time to start LND
|
|
|
|
console.log('STARTING LND') |
|
|
|
const lndPath = path.join(__dirname, '..', 'resources', 'bin', plat, plat === 'win32' ? 'lnd.exe' : 'lnd') |
|
|
|
neutrino = spawn(lndPath, |
|
|
|
[ |
|
|
|
'--bitcoin.active', |
|
|
|
'--bitcoin.testnet', |
|
|
|
'--neutrino.active', |
|
|
|
'--neutrino.connect=faucet.lightning.community:18333', |
|
|
|
'--autopilot.active', |
|
|
|
'--debuglevel=debug', |
|
|
|
'--no-macaroons', |
|
|
|
'--noencryptwallet' |
|
|
|
] |
|
|
|
) |
|
|
|
.on('error', error => console.log(`lnd error: ${error}`)) |
|
|
|
.on('close', code => console.log(`lnd shutting down ${code}`)) |
|
|
|
|
|
|
|
// Listen for when neutrino prints out data
|
|
|
|
neutrino.stdout.on('data', data => { |
|
|
|
// Data stored in variable line, log line to the console
|
|
|
|
let line = data.toString('utf8') |
|
|
|
console.log(line) |
|
|
|
|
|
|
|
// Pass current clock height progress to front end for loading state UX
|
|
|
|
if (line.includes('Caught up to height')) { |
|
|
|
const blockHeight = line.slice(line.indexOf('Caught up to height') + 'Caught up to height'.length).trim() |
|
|
|
mainWindow.webContents.send('lndStdout', blockHeight) |
|
|
|
} |
|
|
|
|
|
|
|
// When LND is all caught up to the blockchain
|
|
|
|
if (line.includes('Done catching up block hashes')) { |
|
|
|
// Log that LND is caught up to the current block height
|
|
|
|
console.log('DONE CATCHING UP BLOCK HASHES') |
|
|
|
// Call lnd
|
|
|
|
lnd((lndSubscribe, lndMethods) => { |
|
|
|
// Subscribe to bi-directional streams
|
|
|
|
lndSubscribe(mainWindow) |
|
|
|
|
|
|
|
// Listen for all gRPC restful methods
|
|
|
|
ipcMain.on('lnd', (event, { msg, data }) => { |
|
|
|
lndMethods(event, msg, data) |
|
|
|
}) |
|
|
|
|
|
|
|
// Let the front end know we have stopped syncing LND
|
|
|
|
syncing = false |
|
|
|
mainWindow.webContents.send('lndSynced') |
|
|
|
}) |
|
|
|
|
|
|
|
// 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 |
|
|
|
} |
|
|
|
|
|
|
|
// Check for certs to exists before we do things
|
|
|
|
certInterval = setInterval(() => { |
|
|
|
if (fs.existsSync(certPath)) { |
|
|
|
clearInterval(certInterval) |
|
|
|
startLnd() |
|
|
|
} |
|
|
|
}) |
|
|
|
}, 500) |
|
|
|
} else { |
|
|
|
// An LND process was found, no need to start our own
|
|
|
|
console.log('LND ALREADY RUNNING') |
|
|
|
// Call lnd
|
|
|
|
lnd((lndSubscribe, lndMethods) => { |
|
|
|
// Subscribe to bi-directional streams
|
|
|
|
lndSubscribe(mainWindow) |
|
|
|
|
|
|
|
// Listen for all gRPC restful methods
|
|
|
|
ipcMain.on('lnd', (event, { msg, data }) => { |
|
|
|
lndMethods(event, msg, data) |
|
|
|
}) |
|
|
|
}) |
|
|
|
startGrpc() |
|
|
|
} |
|
|
|
}) |
|
|
|
}); |
|
|
@ -191,3 +156,61 @@ app.on('open-url', function (event, url) { |
|
|
|
mainWindow.webContents.send('lightningPaymentUri', { payreq }) |
|
|
|
mainWindow.show() |
|
|
|
}) |
|
|
|
|
|
|
|
// Starts the LND node
|
|
|
|
const startLnd = () => { |
|
|
|
lndPath = path.join(__dirname, '..', 'resources', 'bin', plat, plat === 'win32' ? 'lnd.exe' : 'lnd') |
|
|
|
|
|
|
|
neutrino = spawn(lndPath, |
|
|
|
[ |
|
|
|
'--bitcoin.active', |
|
|
|
'--bitcoin.testnet', |
|
|
|
'--neutrino.active', |
|
|
|
'--neutrino.connect=faucet.lightning.community:18333', |
|
|
|
'--autopilot.active', |
|
|
|
'--debuglevel=debug', |
|
|
|
'--no-macaroons', |
|
|
|
'--noencryptwallet' |
|
|
|
] |
|
|
|
) |
|
|
|
.on('error', error => console.log(`lnd error: ${error}`)) |
|
|
|
.on('close', code => console.log(`lnd shutting down ${code}`)) |
|
|
|
|
|
|
|
// Listen for when neutrino prints out data
|
|
|
|
neutrino.stdout.on('data', data => { |
|
|
|
// Data stored in variable line, log line to the console
|
|
|
|
let line = data.toString('utf8') |
|
|
|
|
|
|
|
if (process.env.NODE_ENV === 'development') { console.log(line) } |
|
|
|
|
|
|
|
// Pass current clock height progress to front end for loading state UX
|
|
|
|
if (line.includes('Caught up to height')) { |
|
|
|
const blockHeight = line.slice(line.indexOf('Caught up to height') + 'Caught up to height'.length).trim() |
|
|
|
mainWindow.webContents.send('lndStdout', blockHeight) |
|
|
|
} |
|
|
|
|
|
|
|
// When LND is all caught up to the blockchain
|
|
|
|
if (line.includes('Done catching up block hashes')) { |
|
|
|
// Log that LND is caught up to the current block height
|
|
|
|
console.log('DONE CATCHING UP BLOCK HASHES') |
|
|
|
startGrpc() |
|
|
|
} |
|
|
|
}) |
|
|
|
} |
|
|
|
|
|
|
|
// Create and subscribe the grpc object
|
|
|
|
const startGrpc = () => { |
|
|
|
lnd((lndSubscribe, lndMethods) => { |
|
|
|
// Subscribe to bi-directional streams
|
|
|
|
lndSubscribe(mainWindow) |
|
|
|
|
|
|
|
// Listen for all gRPC restful methods
|
|
|
|
ipcMain.on('lnd', (event, { msg, data }) => { |
|
|
|
lndMethods(event, msg, data) |
|
|
|
}) |
|
|
|
|
|
|
|
// Let the front end know we have stopped syncing LND
|
|
|
|
syncing = false |
|
|
|
mainWindow.webContents.send('lndSynced') |
|
|
|
}) |
|
|
|
} |
|
|
|