wire with orders

This commit is contained in:
hatim boufnichel 2021-01-02 20:53:54 +01:00
parent 2079b4f984
commit bd89766265
3 changed files with 94 additions and 49 deletions

View file

@ -12,8 +12,9 @@ const {
Constants: { ErrorCode }, Constants: { ErrorCode },
Schema Schema
} = Common } = Common
const SchemaManager = require('../../../schema')
const LightningServices = require('../../../../utils/lightningServices') const LightningServices = require('../../../../utils/lightningServices')
const LNDHealthManager = require('../../../../utils/lightningServices/errors')
const Key = require('../key') const Key = require('../key')
const Utils = require('../utils') const Utils = require('../utils')
@ -248,7 +249,7 @@ const listenerForAddr = (addr, SEA) => async (order, orderID) => {
}) })
/** /**
* @param {Common.Invoice} invoice * @param {Common.Invoice & {r_hash:Buffer}} invoice
*/ */
const invoiceSubCb = invoice => { const invoiceSubCb = invoice => {
if (!invoice.settled) { if (!invoice.settled) {
@ -260,14 +261,22 @@ const listenerForAddr = (addr, SEA) => async (order, orderID) => {
.get(maybePostId) .get(maybePostId)
.set(null) // each item in the set is a tip .set(null) // each item in the set is a tip
} }
const coordinate = 'lnPub + invoiceIndex + payment hash(?)' //.... const myLndPub = LNDHealthManager.lndPub
const orderData = { const myGunPub = getUser()._.sea.pub
someInfo: 'info ' if (!myLndPub) {
return //should never happen but just to be safe
} }
getUser() SchemaManager.AddOrder({
.get('orders') amount: parseInt(invoice.amt_paid, 10),
.get(coordinate) coordinateHash: invoice.r_hash.toString('hex'),
.set(orderData) coordinateIndex: parseInt(invoice.add_index, 10),
toLndPub: myLndPub,
inbound: true,
type: 'other', //TODO better this
fromGunPub: order.from,
toGunPub: myGunPub,
invoiceMemo: invoice.memo
})
} }
stream.on('data', invoiceSubCb) stream.on('data', invoiceSubCb)

View file

@ -9,8 +9,8 @@ const Key = require('../gunDB/contact-api/key')
* *
* This represents a settled order only, unsettled orders have no coordinate * This represents a settled order only, unsettled orders have no coordinate
* @typedef {object} CoordinateOrder * @typedef {object} CoordinateOrder
* @prop {string} fromLndPub * @prop {string=} fromLndPub can be unknown when inbound
* @prop {string} toLndPub * @prop {string} toLndPub always known
* @prop {string=} fromGunPub can be optional, if the payment/invoice is not related to an order * @prop {string=} fromGunPub can be optional, if the payment/invoice is not related to an order
* @prop {string=} toGunPub can be optional, if the payment/invoice is not related to an order * @prop {string=} toGunPub can be optional, if the payment/invoice is not related to an order
* @prop {boolean} inbound * @prop {boolean} inbound
@ -26,6 +26,7 @@ const Key = require('../gunDB/contact-api/key')
* @prop {OrderType} type * @prop {OrderType} type
* @prop {number} amount * @prop {number} amount
* @prop {string=} description * @prop {string=} description
* @prop {string=} invoiceMemo
* @prop {string=} metadata JSON encoded string to store extra data for special use cases * @prop {string=} metadata JSON encoded string to store extra data for special use cases
* @prop {number=} timestamp timestamp will be added at processing time if empty * @prop {number=} timestamp timestamp will be added at processing time if empty
* *
@ -34,7 +35,7 @@ const Key = require('../gunDB/contact-api/key')
/** /**
* @param {CoordinateOrder} order * @param {CoordinateOrder} order
*/ */
const checkOrderInfo = (order = {}) => { const checkOrderInfo = order => {
const { const {
fromLndPub, fromLndPub,
toLndPub, toLndPub,
@ -47,23 +48,25 @@ const checkOrderInfo = (order = {}) => {
coordinateIndex, coordinateIndex,
coordinateHash, coordinateHash,
metadata, metadata,
invoiceMemo
} = order } = order
if (typeof fromLndPub !== 'string' || fromLndPub === '') { if (fromLndPub && (typeof fromLndPub !== 'string' || fromLndPub === '')) {
return 'invalid or no "fromLndPub" field provided to order coordinate' return 'invalid "fromLndPub" field provided to order coordinate'
} }
if (typeof toLndPub !== 'string' || toLndPub === '') { if (typeof toLndPub !== 'string' || toLndPub === '') {
return 'invalid or no "toLndPub" field provided to order coordinate' return 'invalid or no "toLndPub" field provided to order coordinate'
} }
if (fromGunPub && (typeof fromGunPub !== 'string' || fromGunPub === '')) { if (fromGunPub && (typeof fromGunPub !== 'string' || fromGunPub === '')) {
return 'invalid or no "fromGunPub" field provided to order coordinate' return 'invalid "fromGunPub" field provided to order coordinate'
} }
if (toGunPub && (typeof toGunPub !== 'string' || toGunPub === '')) { if (toGunPub && (typeof toGunPub !== 'string' || toGunPub === '')) {
return 'invalid or no "toGunPub" field provided to order coordinate' return 'invalid "toGunPub" field provided to order coordinate'
} }
if (typeof inbound !== 'boolean') { if (typeof inbound !== 'boolean') {
return 'invalid or no "inbound" field provided to order coordinate' return 'invalid or no "inbound" field provided to order coordinate'
} }
//@ts-expect-error
if (typeof type !== 'string' || type === '') { if (typeof type !== 'string' || type === '') {
return 'invalid or no "type" field provided to order coordinate' return 'invalid or no "type" field provided to order coordinate'
} }
@ -81,6 +84,9 @@ const checkOrderInfo = (order = {}) => {
if (description && (typeof description !== 'string' || description === '')) { if (description && (typeof description !== 'string' || description === '')) {
return 'invalid "description" field provided to order coordinate' return 'invalid "description" field provided to order coordinate'
} }
if (invoiceMemo && (typeof invoiceMemo !== 'string' || invoiceMemo === '')) {
return 'invalid "invoiceMemo" field provided to order coordinate'
}
if (metadata && (typeof metadata !== 'string' || metadata === '')) { if (metadata && (typeof metadata !== 'string' || metadata === '')) {
return 'invalid "metadata" field provided to order coordinate' return 'invalid "metadata" field provided to order coordinate'
} }
@ -90,7 +96,7 @@ const checkOrderInfo = (order = {}) => {
class SchemaManager { class SchemaManager {
constructor({ memIndex = false }) {//config flag? constructor({ memIndex = false }) {//config flag?
this.memIndex = memIndex this.memIndex = memIndex
this.orderCreateIndexCallbacks.push(this.dateIndexCreateCb) //create more Cbs and p this.orderCreateIndexCallbacks.push(this.dateIndexCreateCb) //create more Cbs and put them here for more indexes callbacks
} }
dateIndexName = 'dateIndex' dateIndexName = 'dateIndex'
@ -161,7 +167,7 @@ class SchemaManager {
) )
) )
} else { } else {
res() res(null)
} }
}) })
}) })
@ -179,7 +185,7 @@ class SchemaManager {
if (this.memIndex) { if (this.memIndex) {
//update date memIndex //update date memIndex
} }
const date = new Date(orderInfo.timestamp) const date = new Date(orderInfo.timestamp || 0)
//use UTC for consistency? //use UTC for consistency?
const year = date.getUTCFullYear().toString() const year = date.getUTCFullYear().toString()
const month = date.getUTCMonth().toString() const month = date.getUTCMonth().toString()
@ -194,21 +200,23 @@ class SchemaManager {
/** /**
* if not provided, assume current month and year * if not provided, assume current month and year
* @param {number} year * @param {number|null} year
* @param {number} month * @param {number|null} month
*/ */
async getMonthCoordinates(year = null, month = null) { async getMonthCoordinates(year = null, month = null) {
const now = Date.now() const now = Date.now()
//@ts-expect-error
const stringYear = year !== null ? year.toString() : now.getUTCFullYear().toString() const stringYear = year !== null ? year.toString() : now.getUTCFullYear().toString()
//@ts-expect-error
const stringMonth = month !== null ? month.toString() : now.getUTCMonth().toString() const stringMonth = month !== null ? month.toString() : now.getUTCMonth().toString()
const data = await new Promise((res, rej) => { const data = await new Promise(res => {
getGunUser() getGunUser()
.get(Key.COORDINATE_INDEX) .get(Key.COORDINATE_INDEX)
.get(this.dateIndexName) .get(this.dateIndexName)
.get(stringYear) .get(stringYear)
.get(stringMonth) .get(stringMonth)
.load() .load(res)
}) })
const coordinatesArray = Object const coordinatesArray = Object
.values(data) .values(data)
@ -219,13 +227,15 @@ class SchemaManager {
/** /**
* if not provided, assume current month and year * if not provided, assume current month and year
* @param {number} year * @param {number|null} year
* @param {number} month * @param {number|null} month
* @returns {Promise<CoordinateOrder[]>} from newer to older * @returns {Promise<CoordinateOrder[]>} from newer to older
*/ */
async getMonthOrders(year = null, month = null) { async getMonthOrders(year = null, month = null) {
const now = Date.now() const now = Date.now()
//@ts-expect-error
const intYear = year !== null ? year : now.getUTCFullYear() const intYear = year !== null ? year : now.getUTCFullYear()
//@ts-expect-error
const intMonth = month !== null ? month : now.getUTCMonth() const intMonth = month !== null ? month : now.getUTCMonth()
let coordinates = null let coordinates = null
@ -234,11 +244,21 @@ class SchemaManager {
} else { } else {
coordinates = await this.getMonthCoordinates(intYear, intMonth) coordinates = await this.getMonthCoordinates(intYear, intMonth)
} }
const orders = await CommonUtils.asyncMap(coordinates, async coordinateSHA256 => { /**
* @type {CoordinateOrder[]}
*/
const orders = []
if (!coordinates) {
return orders
}
await CommonUtils.asyncForEach(coordinates, async coordinateSHA256 => {
const encryptedOrderString = await getGunUser() const encryptedOrderString = await getGunUser()
.get(Key.COORDINATES) .get(Key.COORDINATES)
.get(coordinateSHA256) .get(coordinateSHA256)
.then() .then()
if (typeof encryptedOrderString !== 'string') {
return
}
const mySecret = require('../gunDB/Mediator').getMySecret() const mySecret = require('../gunDB/Mediator').getMySecret()
const decryptedString = await SEA.decrypt(encryptedOrderString, mySecret) const decryptedString = await SEA.decrypt(encryptedOrderString, mySecret)
@ -246,10 +266,14 @@ class SchemaManager {
* @type {CoordinateOrder} * @type {CoordinateOrder}
*/ */
const orderJSON = JSON.parse(decryptedString) const orderJSON = JSON.parse(decryptedString)
return orderJSON orders.push(orderJSON)
}) })
//@ts-expect-error
const orderedOrders = orders.sort((a, b) => b.timestamp - a.timestamp) const orderedOrders = orders.sort((a, b) => b.timestamp - a.timestamp)
return orderedOrders return orderedOrders
} }
} }
const Manager = new SchemaManager()
module.exports = Manager

View file

@ -20,17 +20,26 @@ class LNDErrorManager {
*/ */
_isCheckingHealth = false _isCheckingHealth = false
/**
* @type {string|null}
*/
_lndPub = null
get lndPub() {
return this._lndPub
}
/** /**
* @type {HealthListener[]} * @type {HealthListener[]}
*/ */
_healthListeners = [] _healthListeners = []
//rejects if(err && err.code !== 12) //rejects if(err && err.code !== 12)
getAvailableService(){ getAvailableService() {
//require('shock-common').Utils.makePromise((res, rej) => ...) //require('shock-common').Utils.makePromise((res, rej) => ...)
return new Promise((res,rej)=>{ return new Promise((res, rej) => {
if(!this._isCheckingHealth){ if (!this._isCheckingHealth) {
this._isCheckingHealth = true this._isCheckingHealth = true
this.getInfo() this.getInfo()
} }
@ -39,7 +48,7 @@ class LNDErrorManager {
* @param {LNDError} err * @param {LNDError} err
* @param {object} response * @param {object} response
*/ */
const listener = (err,response)=>{ const listener = (err, response) => {
if (err) { if (err) {
if (err.code === 12) { if (err.code === 12) {
res({ res({
@ -58,7 +67,7 @@ class LNDErrorManager {
walletStatus: 'unknown', walletStatus: 'unknown',
success: false success: false
}) })
} else if(err.code === 4){ } else if (err.code === 4) {
rej({ rej({
service: 'unknown', service: 'unknown',
message: message:
@ -93,28 +102,31 @@ class LNDErrorManager {
} }
//private //private
getInfo(){ getInfo() {
const { lightning } = LightningServices.services const { lightning } = LightningServices.services
/** /**
* *
* @param {LNDError} err * @param {LNDError} err
* @param {object} response * @param {{identity_pubkey:string}} response
*/ */
const callback = (err, response) => { const callback = (err, response) => {
this._healthListeners.forEach(l =>{ if (response && response.identity_pubkey) {
l(err,response) this._lndPub = response.identity_pubkey
}
this._healthListeners.forEach(l => {
l(err, response)
}) })
this._healthListeners.length = 0 this._healthListeners.length = 0
this._isCheckingHealth = false this._isCheckingHealth = false
} }
const deadline = Date.now() + 10000 const deadline = Date.now() + 10000
lightning.getInfo({},{deadline}, callback) lightning.getInfo({}, { deadline }, callback)
} }
/** /**
* @param {LNDError} e * @param {LNDError} e
*/ */
handleError(e){ handleError(e) {
return this.sanitizeLNDError(e) return this.sanitizeLNDError(e)
} }
@ -122,13 +134,13 @@ class LNDErrorManager {
* @param {LNDError} e * @param {LNDError} e
*/ */
// eslint-disable-next-line // eslint-disable-next-line
sanitizeLNDError(e){ sanitizeLNDError(e) {
let eMessage = '' let eMessage = ''
if(typeof e === 'string'){ if (typeof e === 'string') {
eMessage = e eMessage = e
}else if(e.details){ } else if (e.details) {
eMessage = e.details eMessage = e.details
} else if(e.message){ } else if (e.message) {
eMessage = e.message eMessage = e.message
} }
if (eMessage.toLowerCase().includes('unknown')) { if (eMessage.toLowerCase().includes('unknown')) {
@ -137,7 +149,7 @@ class LNDErrorManager {
? splittedMessage.slice(1).join('') ? splittedMessage.slice(1).join('')
: splittedMessage.join('') : splittedMessage.join('')
} }
if(eMessage === ''){ if (eMessage === '') {
return 'unknown LND error' return 'unknown LND error'
} }
return eMessage return eMessage