working order ack
This commit is contained in:
parent
4681f22797
commit
9f4a0b05d2
4 changed files with 242 additions and 171 deletions
|
|
@ -923,7 +923,7 @@ const sendHRWithInitialMsg = async (
|
||||||
/**
|
/**
|
||||||
* @typedef {object} SpontPaymentOptions
|
* @typedef {object} SpontPaymentOptions
|
||||||
* @prop {Common.Schema.OrderTargetType} type
|
* @prop {Common.Schema.OrderTargetType} type
|
||||||
* @prop {string=} postID
|
* @prop {string=} ackInfo
|
||||||
*/
|
*/
|
||||||
/**
|
/**
|
||||||
* @typedef {object} OrderRes
|
* @typedef {object} OrderRes
|
||||||
|
|
@ -968,11 +968,8 @@ const sendSpontaneousPayment = async (
|
||||||
from: getUser()._.sea.pub,
|
from: getUser()._.sea.pub,
|
||||||
memo: memo || 'no memo',
|
memo: memo || 'no memo',
|
||||||
timestamp: Date.now(),
|
timestamp: Date.now(),
|
||||||
targetType: opts.type
|
targetType: opts.type,
|
||||||
}
|
ackInfo: opts.ackInfo
|
||||||
|
|
||||||
if (opts.type === 'tip') {
|
|
||||||
order.ackInfo = opts.postID
|
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.info(JSON.stringify(order))
|
logger.info(JSON.stringify(order))
|
||||||
|
|
@ -1009,7 +1006,7 @@ const sendSpontaneousPayment = async (
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
res(ord._.get)
|
setTimeout(() => res(ord._.get), 0)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
@ -1020,7 +1017,8 @@ const sendSpontaneousPayment = async (
|
||||||
)}`
|
)}`
|
||||||
throw new Error(msg)
|
throw new Error(msg)
|
||||||
}
|
}
|
||||||
|
console.log('ORDER ID')
|
||||||
|
console.log(orderID)
|
||||||
/** @type {import('shock-common').Schema.OrderResponse} */
|
/** @type {import('shock-common').Schema.OrderResponse} */
|
||||||
const encryptedOrderRes = await Utils.tryAndWait(
|
const encryptedOrderRes = await Utils.tryAndWait(
|
||||||
gun =>
|
gun =>
|
||||||
|
|
@ -1030,12 +1028,13 @@ const sendSpontaneousPayment = async (
|
||||||
.get(Key.ORDER_TO_RESPONSE)
|
.get(Key.ORDER_TO_RESPONSE)
|
||||||
.get(orderID)
|
.get(orderID)
|
||||||
.on(orderResponse => {
|
.on(orderResponse => {
|
||||||
|
console.log(orderResponse)
|
||||||
if (Schema.isOrderResponse(orderResponse)) {
|
if (Schema.isOrderResponse(orderResponse)) {
|
||||||
res(orderResponse)
|
res(orderResponse)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}),
|
}),
|
||||||
v => !Schema.isOrderResponse(v)
|
v => Schema.isOrderResponse(v)
|
||||||
)
|
)
|
||||||
|
|
||||||
if (!Schema.isOrderResponse(encryptedOrderRes)) {
|
if (!Schema.isOrderResponse(encryptedOrderRes)) {
|
||||||
|
|
@ -1046,10 +1045,12 @@ const sendSpontaneousPayment = async (
|
||||||
throw e
|
throw e
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @type {import('shock-common').Schema.OrderResponse} */
|
/** @type {import('shock-common').Schema.OrderResponse &{ackNode:string}} */
|
||||||
const orderResponse = {
|
const orderResponse = {
|
||||||
response: await SEA.decrypt(encryptedOrderRes.response, ourSecret),
|
response: await SEA.decrypt(encryptedOrderRes.response, ourSecret),
|
||||||
type: encryptedOrderRes.type
|
type: encryptedOrderRes.type,
|
||||||
|
//@ts-expect-error
|
||||||
|
ackNode: encryptedOrderRes.ackNode
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.info('decoded orderResponse: ' + JSON.stringify(orderResponse))
|
logger.info('decoded orderResponse: ' + JSON.stringify(orderResponse))
|
||||||
|
|
@ -1080,7 +1081,10 @@ const sendSpontaneousPayment = async (
|
||||||
payment_request: orderResponse.response
|
payment_request: orderResponse.response
|
||||||
})
|
})
|
||||||
const myLndPub = LNDHealthMananger.lndPub
|
const myLndPub = LNDHealthMananger.lndPub
|
||||||
if (opts.type !== 'contentReveal' && opts.type !== 'torrentSeed') {
|
if (
|
||||||
|
(opts.type !== 'contentReveal' && opts.type !== 'torrentSeed') ||
|
||||||
|
!orderResponse.ackNode
|
||||||
|
) {
|
||||||
SchemaManager.AddOrder({
|
SchemaManager.AddOrder({
|
||||||
type: opts.type,
|
type: opts.type,
|
||||||
amount: parseInt(payment.value_sat, 10),
|
amount: parseInt(payment.value_sat, 10),
|
||||||
|
|
@ -1094,6 +1098,8 @@ const sendSpontaneousPayment = async (
|
||||||
})
|
})
|
||||||
return { payment }
|
return { payment }
|
||||||
}
|
}
|
||||||
|
console.log('ACK NODE')
|
||||||
|
console.log(orderResponse.ackNode)
|
||||||
/** @type {import('shock-common').Schema.OrderResponse} */
|
/** @type {import('shock-common').Schema.OrderResponse} */
|
||||||
const encryptedOrderAckRes = await Utils.tryAndWait(
|
const encryptedOrderAckRes = await Utils.tryAndWait(
|
||||||
gun =>
|
gun =>
|
||||||
|
|
@ -1101,8 +1107,11 @@ const sendSpontaneousPayment = async (
|
||||||
gun
|
gun
|
||||||
.user(to)
|
.user(to)
|
||||||
.get(Key.ORDER_TO_RESPONSE)
|
.get(Key.ORDER_TO_RESPONSE)
|
||||||
.get(orderID)
|
.get(orderResponse.ackNode)
|
||||||
.on(orderResponse => {
|
.on(orderResponse => {
|
||||||
|
console.log(orderResponse)
|
||||||
|
console.log(Schema.isOrderResponse(orderResponse))
|
||||||
|
|
||||||
if (Schema.isOrderResponse(orderResponse)) {
|
if (Schema.isOrderResponse(orderResponse)) {
|
||||||
res(orderResponse)
|
res(orderResponse)
|
||||||
}
|
}
|
||||||
|
|
@ -1113,7 +1122,7 @@ const sendSpontaneousPayment = async (
|
||||||
|
|
||||||
if (!Schema.isOrderResponse(encryptedOrderAckRes)) {
|
if (!Schema.isOrderResponse(encryptedOrderAckRes)) {
|
||||||
const e = TypeError(
|
const e = TypeError(
|
||||||
`Expected OrderResponse got: ${typeof encryptedOrderAckRes}`
|
`Expected encryptedOrderAckRes got: ${typeof encryptedOrderAckRes}`
|
||||||
)
|
)
|
||||||
logger.error(e)
|
logger.error(e)
|
||||||
throw e
|
throw e
|
||||||
|
|
@ -1148,6 +1157,7 @@ const sendSpontaneousPayment = async (
|
||||||
})
|
})
|
||||||
return { payment, orderAck }
|
return { payment, orderAck }
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
console.log(e)
|
||||||
logger.error('Error inside sendPayment()')
|
logger.error('Error inside sendPayment()')
|
||||||
logger.error(e)
|
logger.error(e)
|
||||||
throw e
|
throw e
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
* @format
|
* @format
|
||||||
*/
|
*/
|
||||||
// @ts-check
|
// @ts-check
|
||||||
|
const Gun = require('gun')
|
||||||
const { performance } = require('perf_hooks')
|
const { performance } = require('perf_hooks')
|
||||||
const logger = require('winston')
|
const logger = require('winston')
|
||||||
const isFinite = require('lodash/isFinite')
|
const isFinite = require('lodash/isFinite')
|
||||||
|
|
@ -201,11 +202,15 @@ const listenerForAddr = (addr, SEA) => async (order, orderID) => {
|
||||||
logger.info(
|
logger.info(
|
||||||
`onOrders() -> Will now place the encrypted invoice in order to response usergraph: ${addr}`
|
`onOrders() -> Will now place the encrypted invoice in order to response usergraph: ${addr}`
|
||||||
)
|
)
|
||||||
|
// @ts-expect-error
|
||||||
|
const ackNode = Gun.text.random()
|
||||||
|
|
||||||
/** @type {import('shock-common').Schema.OrderResponse} */
|
/** @type {import('shock-common').Schema.OrderResponse} */
|
||||||
const orderResponse = {
|
const orderResponse = {
|
||||||
response: encInvoice,
|
response: encInvoice,
|
||||||
type: 'invoice'
|
type: 'invoice',
|
||||||
|
//@ts-expect-error
|
||||||
|
ackNode
|
||||||
}
|
}
|
||||||
|
|
||||||
const invoicePutStartTime = performance.now()
|
const invoicePutStartTime = performance.now()
|
||||||
|
|
@ -231,14 +236,12 @@ const listenerForAddr = (addr, SEA) => async (order, orderID) => {
|
||||||
const invoicePutEndTime = performance.now() - invoicePutStartTime
|
const invoicePutEndTime = performance.now() - invoicePutStartTime
|
||||||
|
|
||||||
logger.info(`[PERF] Added invoice to GunDB in ${invoicePutEndTime}ms`)
|
logger.info(`[PERF] Added invoice to GunDB in ${invoicePutEndTime}ms`)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @type {Common.Schema.InvoiceWhenListed & {r_hash:Buffer,payment_addr:string}}
|
* @param {Common.Schema.InvoiceWhenListed & {r_hash:Buffer,payment_addr:string}} paidInvoice
|
||||||
*/
|
*/
|
||||||
const paidInvoice = await new Promise(res => {
|
const invoicePaidCb = async paidInvoice => {
|
||||||
SchemaManager.addListenInvoice(invoice.r_hash, res)
|
console.log('INVOICE PAID')
|
||||||
})
|
|
||||||
const hashString = paidInvoice.r_hash.toString('hex')
|
const hashString = paidInvoice.r_hash.toString('hex')
|
||||||
const {
|
const {
|
||||||
amt_paid_sat: amt,
|
amt_paid_sat: amt,
|
||||||
|
|
@ -264,25 +267,37 @@ const listenerForAddr = (addr, SEA) => async (order, orderID) => {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
case 'contentReveal': {
|
case 'contentReveal': {
|
||||||
|
console.log('cONTENT REVEAL')
|
||||||
//assuming digital product that only requires to be unlocked
|
//assuming digital product that only requires to be unlocked
|
||||||
const postID = ackInfo
|
const postID = ackInfo
|
||||||
|
console.log('ACK INFO')
|
||||||
|
console.log(ackInfo)
|
||||||
if (!Common.isPopulatedString(postID)) {
|
if (!Common.isPopulatedString(postID)) {
|
||||||
break //create the coordinate, but stop because of the invalid id
|
break //create the coordinate, but stop because of the invalid id
|
||||||
}
|
}
|
||||||
|
console.log('IS STRING')
|
||||||
const selectedPost = await new Promise(res => {
|
const selectedPost = await new Promise(res => {
|
||||||
getUser()
|
getUser()
|
||||||
.get(Key.POSTS_NEW)
|
.get(Key.POSTS_NEW)
|
||||||
.get(postID)
|
.get(postID)
|
||||||
.load(res)
|
.load(res)
|
||||||
})
|
})
|
||||||
if (!Common.Schema.isPost(selectedPost)) {
|
console.log('LOAD ok')
|
||||||
|
console.log(selectedPost)
|
||||||
|
if (
|
||||||
|
!selectedPost ||
|
||||||
|
!selectedPost.status ||
|
||||||
|
selectedPost.status !== 'publish'
|
||||||
|
) {
|
||||||
break //create the coordinate, but stop because of the invalid post
|
break //create the coordinate, but stop because of the invalid post
|
||||||
}
|
}
|
||||||
|
console.log('IS POST')
|
||||||
/**
|
/**
|
||||||
* @type {Record<string,string>} <contentID,decryptedRef>
|
* @type {Record<string,string>} <contentID,decryptedRef>
|
||||||
*/
|
*/
|
||||||
const contentsToSend = {}
|
const contentsToSend = {}
|
||||||
const mySecret = require('../../Mediator').getMySecret()
|
const mySecret = require('../../Mediator').getMySecret()
|
||||||
|
console.log('SECRET OK')
|
||||||
await Common.Utils.asyncForEach(
|
await Common.Utils.asyncForEach(
|
||||||
Object.entries(selectedPost.contentItems),
|
Object.entries(selectedPost.contentItems),
|
||||||
async ([contentID, item]) => {
|
async ([contentID, item]) => {
|
||||||
|
|
@ -304,12 +319,14 @@ const listenerForAddr = (addr, SEA) => async (order, orderID) => {
|
||||||
const encrypted = await SEA.encrypt(toSend, secret)
|
const encrypted = await SEA.encrypt(toSend, secret)
|
||||||
const ordResponse = {
|
const ordResponse = {
|
||||||
type: 'orderAck',
|
type: 'orderAck',
|
||||||
content: encrypted
|
response: encrypted
|
||||||
}
|
}
|
||||||
|
console.log('RES READY')
|
||||||
|
|
||||||
await new Promise((res, rej) => {
|
await new Promise((res, rej) => {
|
||||||
getUser()
|
getUser()
|
||||||
.get(Key.ORDER_TO_RESPONSE)
|
.get(Key.ORDER_TO_RESPONSE)
|
||||||
.get(orderID)
|
.get(ackNode)
|
||||||
.put(ordResponse, ack => {
|
.put(ordResponse, ack => {
|
||||||
if (ack.err && typeof ack.err !== 'number') {
|
if (ack.err && typeof ack.err !== 'number') {
|
||||||
rej(
|
rej(
|
||||||
|
|
@ -322,19 +339,24 @@ const listenerForAddr = (addr, SEA) => async (order, orderID) => {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
console.log('RES SENT')
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
case 'torrentSeed': {
|
case 'torrentSeed': {
|
||||||
|
console.log('TORRENT')
|
||||||
const seedUrl = process.env.TORRENT_SEED_URL
|
const seedUrl = process.env.TORRENT_SEED_URL
|
||||||
const seedToken = process.env.TORRENT_SEED_TOKEN
|
const seedToken = process.env.TORRENT_SEED_TOKEN
|
||||||
if (!seedUrl || !seedToken) {
|
if (!seedUrl || !seedToken) {
|
||||||
break //service not available
|
break //service not available
|
||||||
}
|
}
|
||||||
|
console.log('SEED URL OK')
|
||||||
const token = crypto.randomBytes(32).toString('hex')
|
const token = crypto.randomBytes(32).toString('hex')
|
||||||
const reqData = {
|
const reqData = {
|
||||||
seed_token: seedToken,
|
seed_token: seedToken,
|
||||||
wallet_token: token
|
wallet_token: token
|
||||||
}
|
}
|
||||||
|
console.log(seedUrl)
|
||||||
|
console.log(seedToken)
|
||||||
const res = await fetch(`${seedUrl}/api/enroll_token`, {
|
const res = await fetch(`${seedUrl}/api/enroll_token`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
|
|
@ -342,21 +364,22 @@ const listenerForAddr = (addr, SEA) => async (order, orderID) => {
|
||||||
},
|
},
|
||||||
body: JSON.stringify(reqData)
|
body: JSON.stringify(reqData)
|
||||||
})
|
})
|
||||||
if (res.ok) {
|
if (res.status !== 200) {
|
||||||
break //request didnt work, save coordinate anyway
|
break //request didnt work, save coordinate anyway
|
||||||
}
|
}
|
||||||
|
console.log('RES SEED OK')
|
||||||
const ackData = { seedUrl, token }
|
const ackData = { seedUrl, token }
|
||||||
const toSend = JSON.stringify(ackData)
|
const toSend = JSON.stringify(ackData)
|
||||||
const encrypted = await SEA.encrypt(toSend, secret)
|
const encrypted = await SEA.encrypt(toSend, secret)
|
||||||
const serviceResponse = {
|
const serviceResponse = {
|
||||||
type: 'orderAck',
|
type: 'orderAck',
|
||||||
content: encrypted
|
response: encrypted
|
||||||
}
|
}
|
||||||
|
console.log('RES SEED SENT')
|
||||||
await new Promise((res, rej) => {
|
await new Promise((res, rej) => {
|
||||||
getUser()
|
getUser()
|
||||||
.get(Key.ORDER_TO_RESPONSE)
|
.get(Key.ORDER_TO_RESPONSE)
|
||||||
.get(orderID)
|
.get(ackNode)
|
||||||
.put(serviceResponse, ack => {
|
.put(serviceResponse, ack => {
|
||||||
if (ack.err && typeof ack.err !== 'number') {
|
if (ack.err && typeof ack.err !== 'number') {
|
||||||
rej(
|
rej(
|
||||||
|
|
@ -389,6 +412,36 @@ const listenerForAddr = (addr, SEA) => async (order, orderID) => {
|
||||||
toGunPub: myGunPub,
|
toGunPub: myGunPub,
|
||||||
invoiceMemo: memo
|
invoiceMemo: memo
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
console.log('WAITING INVOICE TO BE PAID')
|
||||||
|
new Promise(res => SchemaManager.addListenInvoice(invoice.r_hash, res))
|
||||||
|
.then(invoicePaidCb)
|
||||||
|
.catch(err => {
|
||||||
|
logger.error(
|
||||||
|
`error inside onOrders, orderAddr: ${addr}, orderID: ${orderID}, order: ${JSON.stringify(
|
||||||
|
order
|
||||||
|
)}`
|
||||||
|
)
|
||||||
|
logger.error(err)
|
||||||
|
|
||||||
|
/** @type {import('shock-common').Schema.OrderResponse} */
|
||||||
|
const orderResponse = {
|
||||||
|
response: err.message,
|
||||||
|
type: 'err'
|
||||||
|
}
|
||||||
|
|
||||||
|
getUser()
|
||||||
|
.get(Key.ORDER_TO_RESPONSE)
|
||||||
|
.get(orderID)
|
||||||
|
// @ts-expect-error
|
||||||
|
.put(orderResponse, ack => {
|
||||||
|
if (ack.err && typeof ack.err !== 'number') {
|
||||||
|
logger.error(
|
||||||
|
`Error saving encrypted invoice to order to response usergraph: ${ack}`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
logger.error(
|
logger.error(
|
||||||
`error inside onOrders, orderAddr: ${addr}, orderID: ${orderID}, order: ${JSON.stringify(
|
`error inside onOrders, orderAddr: ${addr}, orderID: ${orderID}, order: ${JSON.stringify(
|
||||||
|
|
|
||||||
|
|
@ -387,6 +387,7 @@ class SchemaManager {
|
||||||
.get(coordinateSHA256)
|
.get(coordinateSHA256)
|
||||||
.put(encryptedOrderString, ack => {
|
.put(encryptedOrderString, ack => {
|
||||||
if (ack.err && typeof ack.err !== 'number') {
|
if (ack.err && typeof ack.err !== 'number') {
|
||||||
|
console.log(ack)
|
||||||
rej(
|
rej(
|
||||||
new Error(
|
new Error(
|
||||||
`Error saving coordinate order to user-graph: ${ack}`
|
`Error saving coordinate order to user-graph: ${ack}`
|
||||||
|
|
|
||||||
|
|
@ -1192,12 +1192,17 @@ module.exports = async (
|
||||||
|
|
||||||
app.post('/api/lnd/unifiedTrx', async (req, res) => {
|
app.post('/api/lnd/unifiedTrx', async (req, res) => {
|
||||||
try {
|
try {
|
||||||
const { type, amt, to, memo, feeLimit, postID } = req.body
|
const { type, amt, to, memo, feeLimit, ackInfo } = req.body
|
||||||
|
if (
|
||||||
if (type !== 'spont' && type !== 'post') {
|
type !== 'spontaneousPayment' &&
|
||||||
|
type !== 'tip' &&
|
||||||
|
type !== 'torrentSeed' &&
|
||||||
|
type !== 'contentReveal' &&
|
||||||
|
type !== 'other'
|
||||||
|
) {
|
||||||
return res.status(415).json({
|
return res.status(415).json({
|
||||||
field: 'type',
|
field: 'type',
|
||||||
errorMessage: `Only 'spont' and 'post' payments supported via this endpoint for now.`
|
errorMessage: `Only 'spontaneousPayment'| 'tip' | 'torrentSeed' | 'contentReveal' | 'other' payments supported via this endpoint for now.`
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1231,17 +1236,17 @@ module.exports = async (
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type === 'post' && typeof postID !== 'string') {
|
if (type === 'tip' && typeof ackInfo !== 'string') {
|
||||||
return res.status(400).json({
|
return res.status(400).json({
|
||||||
field: 'postID',
|
field: 'ackInfo',
|
||||||
errorMessage: `Send postID`
|
errorMessage: `Send ackInfo`
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return res.status(200).json(
|
return res.status(200).json(
|
||||||
await GunActions.sendSpontaneousPayment(to, amt, memo, feeLimit, {
|
await GunActions.sendSpontaneousPayment(to, amt, memo, feeLimit, {
|
||||||
type,
|
type,
|
||||||
postID
|
ackInfo
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|
@ -2164,10 +2169,12 @@ module.exports = async (
|
||||||
app.post(`/api/gun/wall/`, async (req, res) => {
|
app.post(`/api/gun/wall/`, async (req, res) => {
|
||||||
try {
|
try {
|
||||||
const { tags, title, contentItems } = req.body
|
const { tags, title, contentItems } = req.body
|
||||||
|
const SEA = require('../services/gunDB/Mediator').mySEA
|
||||||
return res
|
return res
|
||||||
.status(200)
|
.status(200)
|
||||||
.json(await GunActions.createPostNew(tags, title, contentItems))
|
.json(await GunActions.createPostNew(tags, title, contentItems, SEA))
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
console.log(e)
|
||||||
return res.status(500).json({
|
return res.status(500).json({
|
||||||
errorMessage:
|
errorMessage:
|
||||||
(typeof e === 'string' ? e : e.message) || 'Unknown error.'
|
(typeof e === 'string' ? e : e.message) || 'Unknown error.'
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue