Merge branch 'master' into dev

This commit is contained in:
Capitalist Dog 2020-09-12 11:58:09 -04:00
commit bb4f897b3a
6 changed files with 345 additions and 94 deletions

View file

@ -46,7 +46,7 @@ module.exports = (mainnet = false) => {
logfile: "shockapi.log",
lndLogFile: parsePath(`${lndDirectory}/logs/bitcoin/${network}/lnd.log`),
lndDirPath: lndDirectory,
peers: ['https://gun.shock.network'],
peers: ['http://gun.shock.network:8765/gun','http://gun2.shock.network:8765/gun'],
useTLS: false,
tokenExpirationMS: 259200000
};

View file

@ -22,7 +22,7 @@
"big.js": "^5.2.2",
"bitcore-lib": "^0.15.0",
"body-parser": "^1.16.0",
"colors": "^1.3.0",
"colors": "^1.4.0",
"command-exists": "^1.2.6",
"commander": "^2.9.0",
"compression": "^1.7.4",
@ -60,12 +60,12 @@
"@types/bluebird": "*",
"@types/dotenv": "^6.1.1",
"@types/express": "^4.17.1",
"@types/gun": "^0.9.1",
"@types/gun": "^0.9.2",
"@types/jest": "^24.0.18",
"@types/jsonwebtoken": "^8.3.7",
"@types/lodash": "^4.14.141",
"@types/ramda": "types/npm-ramda#dist",
"@types/socket.io": "^2.1.4",
"@types/socket.io": "^2.1.11",
"@types/uuid": "^3.4.5",
"babel-eslint": "^10.0.3",
"babel-plugin-transform-es2015-modules-commonjs": "^6.26.2",
@ -73,7 +73,7 @@
"eslint-config-prettier": "^6.5.0",
"eslint-plugin-babel": "^5.3.1",
"eslint-plugin-jest": "^22.20.1",
"eslint-plugin-prettier": "^3.1.1",
"eslint-plugin-prettier": "^3.1.4",
"jest": "^24.9.0",
"lint-staged": "^10.2.2",
"nodemon": "^1.19.3",

View file

@ -21,6 +21,7 @@ const auth = require('../services/auth/auth')
const FS = require('../utils/fs')
const Encryption = require('../utils/encryptionStore')
const LightningServices = require('../utils/lightningServices')
const lndErrorManager = require('../utils/lightningServices/errors')
const GunDB = require('../services/gunDB/Mediator')
const {
unprotectedRoutes,
@ -64,7 +65,10 @@ module.exports = async (
return message
}
const getAvailableService = () =>
const getAvailableService = () => {
return lndErrorManager.getAvailableService()
}
/*
new Promise((resolve, reject) => {
const { lightning } = LightningServices.services
@ -106,13 +110,22 @@ module.exports = async (
success: true
})
})
})
})*/
const checkHealth = async () => {
logger.info('Getting service status...')
let LNDStatus = {}
try {
const serviceStatus = await getAvailableService()
logger.info('Received status:', serviceStatus)
const LNDStatus = serviceStatus
LNDStatus = serviceStatus
} catch (e) {
LNDStatus = {
message: e.message,
success: false
}
}
try {
logger.info('Getting API status...')
const APIHealth = await Http.get(
@ -368,14 +381,31 @@ module.exports = async (
const walletStatus = await walletExists()
const availableService = await getAvailableService()
const statusMessage = availableService.walletStatus
if (availableService.code === 12) {
return res.status(401).json({
field: 'lnd_locked',
errorMessage: availableService.message
? availableService.message
: 'unknown'
})
}
if (availableService.code === 14) {
return res.status(401).json({
field: 'lnd_dead',
errorMessage: availableService.message
? availableService.message
: 'unknown'
})
}
if (walletStatus) {
if (statusMessage === 'unlocked') {
return next()
}
return res.status(401).json({
field: 'wallet',
errorMessage: statusMessage ? statusMessage : 'unknown'
errorMessage: availableService.message
? availableService.message
: 'unknown'
})
}
@ -387,6 +417,18 @@ module.exports = async (
next()
} catch (err) {
logger.error(err)
if (err.code === 12) {
return res.status(401).json({
field: 'lnd_locked',
errorMessage: err.message ? err.message : 'unknown'
})
}
if (err.code === 14) {
return res.status(401).json({
field: 'lnd_dead',
errorMessage: err.message ? err.message : 'unknown'
})
}
res.status(500).json({
field: 'wallet',
errorMessage: err.message ? err.message : err
@ -590,17 +632,46 @@ module.exports = async (
stream.on('end', () => {
logger.info('Channel backup stream ended, starting a new one...')
// Prevents call stack overflow exceptions
process.nextTick(onNewChannelBackup)
//process.nextTick(onNewChannelBackup)
})
stream.on('error', err => {
logger.error('Channel backup stream error:', err)
})
stream.on('status', status => {
if (status.code === 14) {
// Prevents call stack overflow exceptions
process.nextTick(() => setTimeout(onNewChannelBackup, 30000))
} else {
logger.error('Channel backup stream status:', status)
switch (status.code) {
case 0: {
logger.info('Channel backup stream ok')
break
}
case 2: {
//Happens to fire when the grpc client lose access to macaroon file
logger.warn('Channel backup got UNKNOWN error status')
break
}
case 12: {
logger.warn(
'Channel backup LND locked, new registration in 60 seconds'
)
process.nextTick(() =>
setTimeout(() => onNewTransaction(socket, subID), 60000)
)
break
}
case 13: {
//https://grpc.github.io/grpc/core/md_doc_statuscodes.html
logger.error('Channel backup INTERNAL LND error')
break
}
case 14: {
logger.error(
'Channel backup LND disconnected, sockets reconnecting in 30 seconds...'
)
process.nextTick(() =>
setTimeout(() => onNewTransaction(socket, subID), 30000)
)
break
}
}
})
}

View file

@ -122,21 +122,45 @@ module.exports = (
stream.on('end', () => {
logger.info('New invoice stream ended, starting a new one...')
// Prevents call stack overflow exceptions
process.nextTick(() => onNewInvoice(socket))
//process.nextTick(() => onNewInvoice(socket))
})
stream.on('error', err => {
logger.error('New invoice stream error:' + subID, err)
})
stream.on('status', status => {
logger.warn('New invoice stream status:' + subID, status)
if (status.code === 14) {
// Prevents call stack overflow exceptions
switch (status.code) {
case 0: {
logger.info('[event:invoice:new] stream ok')
break
}
case 2: {
logger.warn('[event:invoice:new] got UNKNOWN error status')
break
}
case 12: {
logger.warn(
'[event:invoice:new] LND locked, new registration in 60 seconds'
)
process.nextTick(() =>
setTimeout(() => onNewInvoice(socket, subID), 60000)
)
break
}
case 13: {
//https://grpc.github.io/grpc/core/md_doc_statuscodes.html
logger.error('[event:invoice:new] INTERNAL LND error')
break
}
case 14: {
logger.error(
'[event:invoice:new] LND disconnected, sockets reconnecting in 30 seconds...'
)
process.nextTick(() =>
setTimeout(() => onNewInvoice(socket, subID), 30000)
)
break
}
}
})
return () => {
@ -154,20 +178,46 @@ module.exports = (
})
stream.on('end', () => {
logger.info('New transactions stream ended, starting a new one...')
process.nextTick(() => onNewTransaction(socket))
//process.nextTick(() => onNewTransaction(socket))
})
stream.on('error', err => {
logger.error('New transactions stream error:' + subID, err)
})
stream.on('status', status => {
logger.error('New transactions stream status:' + subID, status)
if (status.code === 14) {
switch (status.code) {
case 0: {
logger.info('[event:transaction:new] stream ok')
break
}
case 2: {
//Happens to fire when the grpc client lose access to macaroon file
logger.warn('[event:transaction:new] got UNKNOWN error status')
break
}
case 12: {
logger.warn(
'[event:transaction:new] LND locked, new registration in 60 seconds'
)
process.nextTick(() =>
setTimeout(() => onNewTransaction(socket, subID), 60000)
)
break
}
case 13: {
//https://grpc.github.io/grpc/core/md_doc_statuscodes.html
logger.error('[event:transaction:new] INTERNAL LND error')
break
}
case 14: {
logger.error(
'[event:transaction:new] LND disconnected, sockets reconnecting in 30 seconds...'
)
process.nextTick(() =>
setTimeout(() => onNewTransaction(socket, subID), 30000)
)
break
}
}
})
return () => {

View file

@ -0,0 +1,152 @@
const LightningServices = require('./lightning-services')
/**
* @typedef {{
* code:number,
* details:string,
* message:string
* }} LNDError
*/
/**
* @typedef {(err:LNDError,response:object)=>void} HealthListener
*/
class LNDErrorManager {
/**
* @type {boolean}
*/
_isCheckingHealth = false
/**
* @type {HealthListener[]}
*/
_healthListeners = []
//rejects if(err && err.code !== 12)
getAvailableService(){
//require('shock-common').Utils.makePromise((res, rej) => ...)
return new Promise((res,rej)=>{
if(!this._isCheckingHealth){
this._isCheckingHealth = true
this.getInfo()
}
/**
*
* @param {LNDError} err
* @param {object} response
*/
const listener = (err,response)=>{
if (err) {
if (err.code === 12) {
res({
service: 'walletUnlocker',
message: 'Wallet locked',
code: err.code,
walletStatus: 'locked',
success: true
})
} else if (err.code === 14) {
rej({
service: 'unknown',
message:
"Failed to connect to LND server, make sure it's up and running.",
code: 14,
walletStatus: 'unknown',
success: false
})
} else if(err.code === 4){
rej({
service: 'unknown',
message:
"LND Timeout",
code: 4,
walletStatus: 'unknown',
success: false
})
} else {
rej({
service: 'lightning',
message: this.sanitizeLNDError(err),
code: err.code,
walletStatus: 'unlocked',
success: false
})
}
}
res({
service: 'lightning',
message: response,
code: null,
walletStatus: 'unlocked',
success: true
})
}
this._healthListeners.push(listener)
})
}
//private
getInfo(){
const { lightning } = LightningServices.services
/**
*
* @param {LNDError} err
* @param {object} response
*/
const callback = (err, response) => {
this._healthListeners.forEach(l =>{
l(err,response)
})
this._healthListeners.length = 0
this._isCheckingHealth = false
}
const deadline = Date.now() + 4000
lightning.getInfo({},{deadline}, callback)
}
/**
* @param {LNDError} e
*/
handleError(e){
return this.sanitizeLNDError(e)
}
/**
* @param {LNDError} e
*/
// eslint-disable-next-line
sanitizeLNDError(e){
let eMessage = ''
if(typeof e === 'string'){
eMessage = e
}else if(e.details){
eMessage = e.details
} else if(e.message){
eMessage = e.message
}
if (eMessage.toLowerCase().includes('unknown')) {
const splittedMessage = eMessage.split('UNKNOWN: ')
return splittedMessage.length > 1
? splittedMessage.slice(1).join('')
: splittedMessage.join('')
}
if(eMessage === ''){
return 'unknown LND error'
}
return eMessage
}
}
const lndErrorManager = new LNDErrorManager()
module.exports = lndErrorManager

View file

@ -605,6 +605,13 @@
dependencies:
"@types/node" "*"
"@types/engine.io@*":
version "3.1.4"
resolved "https://registry.yarnpkg.com/@types/engine.io/-/engine.io-3.1.4.tgz#3d9472711d179daa7c95c051e50ad411e18a9bdc"
integrity sha512-98rXVukLD6/ozrQ2O80NAlWDGA4INg+tqsEReWJldqyi2fulC9V7Use/n28SWgROXKm6003ycWV4gZHoF8GA6w==
dependencies:
"@types/node" "*"
"@types/express-serve-static-core@*":
version "4.16.9"
resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.16.9.tgz#69e00643b0819b024bdede95ced3ff239bb54558"
@ -622,10 +629,10 @@
"@types/express-serve-static-core" "*"
"@types/serve-static" "*"
"@types/gun@^0.9.1":
version "0.9.1"
resolved "https://registry.yarnpkg.com/@types/gun/-/gun-0.9.1.tgz#00ce80f50305e9583f807e750275547aaeb4737d"
integrity sha512-frQF4+FbyG70MhfNmY3jPhXA5nRA+145B5QcXk2mo+n3qpxLhO28YEET/gjH0lxxqQQrHPKjLMt1yEtaIErtgw==
"@types/gun@^0.9.2":
version "0.9.2"
resolved "https://registry.yarnpkg.com/@types/gun/-/gun-0.9.2.tgz#72493631c5e7fb3fae9a195b1ea8bf3d727fd19d"
integrity sha512-s3O5tnnXtWaZqA2yjfN+Ty3OINRxV51lUevNVldAeky4lk3/6QHSc8hkfPTc0f44JrJCidILrU5bMBGN0SWz1A==
"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0":
version "2.0.1"
@ -723,11 +730,12 @@
"@types/express-serve-static-core" "*"
"@types/mime" "*"
"@types/socket.io@^2.1.4":
version "2.1.4"
resolved "https://registry.yarnpkg.com/@types/socket.io/-/socket.io-2.1.4.tgz#674e7bc193c5ccdadd4433f79f3660d31759e9ac"
integrity sha512-cI98INy7tYnweTsUlp8ocveVdAxENUThO0JsLSCs51cjOP2yV5Mqo5QszMDPckyRRA+PO6+wBgKvGvHUCc23TQ==
"@types/socket.io@^2.1.11":
version "2.1.11"
resolved "https://registry.yarnpkg.com/@types/socket.io/-/socket.io-2.1.11.tgz#e0d6759880e5f9818d5297a3328b36641bae996b"
integrity sha512-bVprmqPhJMLb9ZCm8g0Xy8kwBFRbnanOWSxzWkDkkIwxTvud5tKMfAJymXX6LQbizUKCS1yima7JM4BeLqjNqA==
dependencies:
"@types/engine.io" "*"
"@types/node" "*"
"@types/stack-utils@^1.0.1":
@ -1726,16 +1734,11 @@ color@3.0.x:
color-convert "^1.9.1"
color-string "^1.5.2"
colors@^1.2.1:
colors@^1.2.1, colors@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78"
integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==
colors@^1.3.0:
version "1.3.3"
resolved "https://registry.yarnpkg.com/colors/-/colors-1.3.3.tgz#39e005d546afe01e01f9c4ca8fa50f686a01205d"
integrity sha512-mmGt/1pZqYRjMxB1axhTo16/snVZ5krrKkcmMeVKxzECMMXoCgnvTPp10QgHfcbQZw8Dq2jMNG6je4JlWU0gWg==
colorspace@1.1.x:
version "1.1.2"
resolved "https://registry.yarnpkg.com/colorspace/-/colorspace-1.1.2.tgz#e0128950d082b86a2168580796a0aa5d6c68d8c5"
@ -1771,11 +1774,6 @@ commander@^5.0.0:
resolved "https://registry.yarnpkg.com/commander/-/commander-5.1.0.tgz#46abbd1652f8e059bddaef99bbdcb2ad9cf179ae"
integrity sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==
commander@~2.20.0:
version "2.20.1"
resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.1.tgz#3863ce3ca92d0831dcf2a102f5fb4b5926afd0f9"
integrity sha512-cCuLsMhJeWQ/ZpsFTbE765kvVfoeSddc4nU3up4fV+fDBcfUXnbITJ+JzhkdjzOqhURjZgujxaioam4RM9yGUg==
compare-versions@^3.6.0:
version "3.6.0"
resolved "https://registry.yarnpkg.com/compare-versions/-/compare-versions-3.6.0.tgz#1a5689913685e5a87637b8d3ffca75514ec41d62"
@ -2349,10 +2347,10 @@ eslint-plugin-jest@^22.20.1:
dependencies:
"@typescript-eslint/experimental-utils" "^1.13.0"
eslint-plugin-prettier@^3.1.1:
version "3.1.1"
resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-3.1.1.tgz#507b8562410d02a03f0ddc949c616f877852f2ba"
integrity sha512-A+TZuHZ0KU0cnn56/9mfR7/KjUJ9QNVXUhwvRFSR7PGPe0zQR6PTkmyqg1AtUUEOzTqeRsUwyKFh0oVZKVCrtA==
eslint-plugin-prettier@^3.1.4:
version "3.1.4"
resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-3.1.4.tgz#168ab43154e2ea57db992a2cd097c828171f75c2"
integrity sha512-jZDa8z76klRqo+TdGDTFJSavwbnWK2ZpqGKNZ+VvweMW516pDUMmQ2koXvxEE4JhzNvTv+radye/bWGBmA6jmg==
dependencies:
prettier-linter-helpers "^1.0.0"
@ -3061,13 +3059,14 @@ grpc@^1.21.1:
text-encoding "^0.7.0"
handlebars@^4.1.2:
version "4.4.0"
resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.4.0.tgz#22e1a897c5d83023d39801f35f6b65cf97ed8b25"
integrity sha512-xkRtOt3/3DzTKMOt3xahj2M/EqNhY988T+imYSlMgs5fVhLN2fmKVVj0LtEGmb+3UUYV5Qmm1052Mm3dIQxOvw==
version "4.7.6"
resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.6.tgz#d4c05c1baf90e9945f77aa68a7a219aa4a7df74e"
integrity sha512-1f2BACcBfiwAfStCKZNrUCgqNZkGsAT7UM3kkYtXuLo0KnaVfjKOyf7PRzB6++aK9STyT1Pd2ZCPe3EGOXleXA==
dependencies:
minimist "^1.2.5"
neo-async "^2.6.0"
optimist "^0.6.1"
source-map "^0.6.1"
wordwrap "^1.0.0"
optionalDependencies:
uglify-js "^3.1.4"
@ -4639,15 +4638,10 @@ minimist@0.0.8:
resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d"
integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=
minimist@^1.1.1, minimist@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284"
integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=
minimist@~0.0.1:
version "0.0.10"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf"
integrity sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=
minimist@^1.1.1, minimist@^1.2.0, minimist@^1.2.5:
version "1.2.5"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602"
integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==
minipass@^2.2.1, minipass@^2.3.5:
version "2.5.1"
@ -4746,9 +4740,9 @@ negotiator@0.6.2:
integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==
neo-async@^2.6.0:
version "2.6.1"
resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.1.tgz#ac27ada66167fa8849a6addd837f6b189ad2081c"
integrity sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw==
version "2.6.2"
resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f"
integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==
nice-try@^1.0.4:
version "1.0.5"
@ -5022,14 +5016,6 @@ openurl@1.1.1:
resolved "https://registry.yarnpkg.com/openurl/-/openurl-1.1.1.tgz#3875b4b0ef7a52c156f0db41d4609dbb0f94b387"
integrity sha1-OHW0sO96UsFW8NtB1GCduw+Us4c=
optimist@^0.6.1:
version "0.6.1"
resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686"
integrity sha1-2j6nRob6IaGaERwybpDrFaAZZoY=
dependencies:
minimist "~0.0.1"
wordwrap "~0.0.2"
optionator@^0.8.1, optionator@^0.8.2:
version "0.8.2"
resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64"
@ -6752,12 +6738,9 @@ typescript@^4.0.2:
integrity sha512-e4ERvRV2wb+rRZ/IQeb3jm2VxBsirQLpQhdxplZ2MEzGvDkkMmPglecnNDfSUBivMjP93vRbngYYDQqQ/78bcQ==
uglify-js@^3.1.4:
version "3.6.0"
resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.6.0.tgz#704681345c53a8b2079fb6cec294b05ead242ff5"
integrity sha512-W+jrUHJr3DXKhrsS7NUVxn3zqMOFn0hL/Ei6v0anCIMoKC93TjcflTagwIHLW7SfMFfiQuktQyFVCFHGUE0+yg==
dependencies:
commander "~2.20.0"
source-map "~0.6.1"
version "3.10.2"
resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.10.2.tgz#8cfa1209fd04199cc8a7f9930ddedb30b0f1912d"
integrity sha512-GXCYNwqoo0MbLARghYjxVBxDCnU0tLqN7IPLdHHbibCb1NI5zBkU2EPcy/GaVxc0BtTjqyGXJCINe6JMR2Dpow==
uid-safe@~2.1.5:
version "2.1.5"
@ -7066,12 +7049,7 @@ winston@^3.3.3:
triple-beam "^1.3.0"
winston-transport "^4.4.0"
wordwrap@~0.0.2:
version "0.0.3"
resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107"
integrity sha1-o9XabNXAvAAI03I0u68b7WMFkQc=
wordwrap@~1.0.0:
wordwrap@^1.0.0, wordwrap@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb"
integrity sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=