Merge branch 'master' into feature/lnd-sockets

This commit is contained in:
emad-salah 2020-04-05 18:11:04 +01:00
commit 66622c1b0c
7 changed files with 184 additions and 28 deletions

View file

@ -495,7 +495,7 @@ class Mediator {
field: 'deviceId',
message: 'Please specify a device ID'
}
logger.error(error)
logger.error(JSON.stringify(error))
return false
}
@ -776,18 +776,11 @@ class Mediator {
await throwOnInvalidToken(token)
await API.Actions.sendPayment(
recipientPub,
amount,
memo,
gun,
user,
mySEA
)
const preimage = await API.Actions.sendPayment(recipientPub, amount, memo)
this.socket.emit(Action.SEND_PAYMENT, {
ok: true,
msg: null,
msg: preimage,
origBody: reqBody
})
} catch (err) {
@ -932,7 +925,7 @@ class Mediator {
API.Events.onChats(chats => {
if (Config.SHOW_LOG) {
logger.info('---chats---')
logger.info(chats)
logger.info(JSON.stringify(chats))
logger.info('-----------------------')
}
@ -964,7 +957,7 @@ class Mediator {
API.Events.onDisplayName(displayName => {
if (Config.SHOW_LOG) {
logger.info('---displayName---')
logger.info(displayName)
logger.info(displayName || 'null or empty string')
logger.info('-----------------------')
}
@ -996,7 +989,7 @@ class Mediator {
API.Events.onCurrentHandshakeAddress(addr => {
if (Config.SHOW_LOG) {
logger.info('---addr---')
logger.info(addr)
logger.info(addr || 'null or empty string')
logger.info('-----------------------')
}

View file

@ -3,9 +3,6 @@
*/
const uuidv1 = require('uuid/v1')
const logger = require('winston')
const isFinite = require('lodash/isFinite')
const isNumber = require('lodash/isNumber')
const isNaN = require('lodash/isNaN')
const LightningServices = require('../../../utils/lightningServices')
@ -14,7 +11,11 @@ const Getters = require('./getters')
const Key = require('./key')
const Utils = require('./utils')
// const { promisifyGunNode: p } = Utils
const { isHandshakeRequest, isOrderResponse } = require('./schema')
const {
isHandshakeRequest,
isOrderResponse,
encodeSpontaneousPayment
} = require('./schema')
/**
* @typedef {import('./SimpleGUN').GUNNode} GUNNode
* @typedef {import('./SimpleGUN').ISEA} ISEA
@ -875,12 +876,13 @@ const sendHRWithInitialMsg = async (
}
/**
* Returns the preimage corresponding to the payment.
* @param {string} to
* @param {number} amount
* @param {string} memo
* @throws {Error} If no response in less than 20 seconds from the recipient, or
* lightning cannot find a route for the payment.
* @returns {Promise<void>}
* @returns {Promise<string>} The payment's preimage.
*/
const sendPayment = async (to, amount, memo) => {
try {
@ -1027,6 +1029,7 @@ const sendPayment = async (to, amount, memo) => {
* @typedef {object} SendResponse
* @prop {string|null} payment_error
* @prop {any[]|null} payment_route
* @prop {string} payment_preimage
*/
logger.info('Will now send payment through lightning')
@ -1036,7 +1039,8 @@ const sendPayment = async (to, amount, memo) => {
payment_request: orderResponse.response
}
await new Promise((resolve, rej) => {
/** @type {string} */
const preimage = await new Promise((resolve, rej) => {
lightning.sendPaymentSync(sendPaymentSyncArgs, (
/** @type {SendErr=} */ err,
/** @type {SendResponse} */ res
@ -1050,22 +1054,33 @@ const sendPayment = async (to, amount, memo) => {
`sendPaymentSync error response: ${JSON.stringify(res)}`
)
)
} else if (!res.payment_route) {
} else if (!res.payment_route || !res.payment_preimage) {
rej(
new Error(
`sendPaymentSync no payment route response: ${JSON.stringify(
`sendPaymentSync no payment route response or preimage: ${JSON.stringify(
res
)}`
)
)
} else {
resolve()
resolve(res.payment_preimage)
}
} else {
rej(new Error('no error or response received from sendPaymentSync'))
}
})
})
if (Utils.successfulHandshakeAlreadyExists(to)) {
await sendMessage(
to,
encodeSpontaneousPayment(amount, memo || 'no memo', preimage),
require('../Mediator').getUser(),
require('../Mediator').mySEA
)
}
return preimage
} catch (e) {
logger.error('Error inside sendPayment()')
logger.error(e)

View file

@ -0,0 +1,15 @@
/**
* @format
* Contains types that are used throughout the application. Written in
* typescript for easier implementation.
*
* Nominal types are archieved through the enum method as outlined here:
* https://basarat.gitbook.io/typescript/main-1/nominaltyping
*/
enum _EncSpontPayment {
_ = ''
}
/**
* Spontaneous payment as found inside a chat message body.
*/
export type EncSpontPayment = _EncSpontPayment & string

View file

@ -1,6 +1,11 @@
/**
* @format
*/
const logger = require('winston')
const isFinite = require('lodash/isFinite')
const isNumber = require('lodash/isNumber')
const isNaN = require('lodash/isNaN')
/**
* @typedef {object} HandshakeRequest
* @prop {string} from Public key of the requestor.
@ -410,3 +415,105 @@ exports.isOrderResponse = o => {
return obj.type === 'err' || obj.type === 'invoice'
}
/**
* @typedef {import('./schema-types').EncSpontPayment} EncSpontPayment
*/
const ENC_SPONT_PAYMENT_PREFIX = '$$__SHOCKWALLET__SPONT__PAYMENT__'
/**
* @param {string} s
* @returns {s is EncSpontPayment}
*/
const isEncodedSpontPayment = s => s.indexOf(ENC_SPONT_PAYMENT_PREFIX) === 0
exports.isEncodedSpontPayment = isEncodedSpontPayment
/**
* @typedef {object} SpontaneousPayment
* @prop {number} amt
* @prop {string} memo
* @prop {string} preimage
*/
/**
*
* @param {EncSpontPayment} sp
* @throws {Error} If decoding fails.
* @returns {SpontaneousPayment}
*/
exports.decodeSpontPayment = sp => {
try {
const [preimage, amtStr, memo] = sp
.slice(ENC_SPONT_PAYMENT_PREFIX.length)
.split('__')
if (typeof preimage !== 'string') {
throw new TypeError('Could not parse preimage')
}
if (typeof amtStr !== 'string') {
throw new TypeError('Could not parse amt')
}
if (typeof memo !== 'string') {
throw new TypeError('Could not parse memo')
}
const amt = Number(amtStr)
if (!isNumber(amt)) {
throw new TypeError(`Could parse amount as a number, not a number?`)
}
if (isNaN(amt)) {
throw new TypeError(`Could not amount as a number, got NaN.`)
}
if (!isFinite(amt)) {
throw new TypeError(
`Amount was correctly parsed, but got a non finite number.`
)
}
return {
amt,
memo,
preimage
}
} catch (err) {
logger.debug(`Encoded spontaneous payment: ${sp}`)
logger.error(err)
throw err
}
}
/**
*
* @param {number} amt
* @param {string} memo
* @param {string} preimage
* @returns {EncSpontPayment}
*/
exports.encodeSpontaneousPayment = (amt, memo, preimage) => {
if (amt <= 0) {
throw new RangeError('Amt must be greater than zero')
}
if (memo.length < 1) {
throw new TypeError('Memo must be populated')
}
if (preimage.length < 1) {
throw new TypeError('preimage must be populated')
}
const enc = `${ENC_SPONT_PAYMENT_PREFIX}__${amt}__${memo}__${preimage}`
if (isEncodedSpontPayment(enc)) {
return enc
}
throw new Error('isEncodedSpontPayment(enc) false')
}

View file

@ -212,7 +212,7 @@ module.exports = async (
app.use((req, res, next) => {
const deviceId = req.headers["x-shockwallet-device-id"];
console.log("Decrypting route...")
logger.debug("Decrypting route...")
try {
if (nonEncryptedRoutes.includes(req.path)) {
return next();
@ -1671,7 +1671,7 @@ module.exports = async (
try {
const user = require('../services/gunDB/Mediator').getUser()
const data = await timeout5(user.get(Key.BIO).then())
console.log(data)
logger.debug(data)
res.json({
data
})

View file

@ -77,10 +77,10 @@ const server = program => {
const dataHash = hashData(args[0]).slice(-8)
res.set('ETag', dataHash)
console.log('ETag:', req.headers.etag)
console.log('Data Hash:', dataHash)
logger.debug('ETag:', req.headers.etag)
logger.debug('Data Hash:', dataHash)
if (req.headers.etag === dataHash) {
console.log('Same Hash Detected!')
logger.debug('Same Hash Detected!')
args[0] = null
res.status(304)
oldSend.apply(res, args)

View file

@ -16,7 +16,14 @@ const nonEncryptedEvents = [
]
const Encryption = {
/**
* @param {string} event
* @returns {boolean}
*/
isNonEncrypted: event => nonEncryptedEvents.includes(event),
/**
* @param {{ deviceId: string , message: string }} arg0
*/
encryptKey: ({ deviceId, message }) => {
if (!authorizedDevices.has(deviceId)) {
throw { field: 'deviceId', message: 'Unknown Device ID' }
@ -33,6 +40,9 @@ const Encryption = {
)
return encryptedData.toString('base64')
},
/**
* @param {{ deviceId: string , message: string }} arg0
*/
decryptKey: ({ deviceId, message }) => {
if (!authorizedDevices.has(deviceId)) {
throw { field: 'deviceId', message: 'Unknown Device ID' }
@ -49,6 +59,9 @@ const Encryption = {
return encryptedData.toString()
},
/**
* @param {{ deviceId: string , message: any , metadata?: any}} arg0
*/
encryptMessage: ({ deviceId, message, metadata }) => {
const parsedMessage =
typeof message === 'object' ? JSON.stringify(message) : message
@ -68,6 +81,9 @@ const Encryption = {
const encryptedData = encryptedBuffer.toString('base64')
return { encryptedData, encryptedKey, iv: iv.toString('hex'), metadata }
},
/**
* @param {{ message: string , key: string , iv: string }} arg0
*/
decryptMessage: ({ message, key, iv }) => {
const data = Buffer.from(message, 'base64')
const cipher = Crypto.createDecipheriv(
@ -84,6 +100,9 @@ const Encryption = {
return decryptedData.toString()
},
/**
* @param {{ deviceId: string }} arg0
*/
isAuthorizedDevice: ({ deviceId }) => {
if (authorizedDevices.has(deviceId)) {
return true
@ -91,6 +110,9 @@ const Encryption = {
return false
},
/**
* @param {{ deviceId: string , publicKey: string }} arg0
*/
authorizeDevice: ({ deviceId, publicKey }) =>
new Promise((resolve, reject) => {
authorizedDevices.set(deviceId, publicKey)
@ -109,9 +131,10 @@ const Encryption = {
},
(err, publicKey, privateKey) => {
if (err) {
// @ts-ignore
logger.error(err)
reject(err)
return err
return
}
const exportedKey = {
@ -127,6 +150,9 @@ const Encryption = {
}
)
}),
/**
* @param {{ deviceId: string }} arg0
*/
unAuthorizeDevice: ({ deviceId }) => {
authorizedDevices.delete(deviceId)
}