You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

171 lines
4.0 KiB

import { success, failure } from '../utils/res'
import { models } from '../models'
import * as network from '../network'
import constants from '../constants'
import * as short from 'short-uuid'
import * as lightning from '../utils/lightning'
import {listUnspent,UTXO} from '../utils/wallet'
import * as jsonUtils from '../utils/json'
import { Op } from 'sequelize'
type QueryType = 'onchain_address'
export interface Query {
type: QueryType
uuid: string
result?: string
app: string
}
let queries: { [k: string]: Query } = {}
const hub_pubkey = '023d70f2f76d283c6c4e58109ee3a2816eb9d8feb40b23d62469060a2b2867b77f'
export async function listUTXOs(req, res) {
try {
const utxos:UTXO[] = await listUnspent() // at least 1 confg
const addys = utxos.map(utxo=> utxo.address)
const accountings = await models.Accounting.findAll({
where:{
onchain_address: {
[Op.in]: addys
},
status: constants.statuses.pending
}
})
const ret: any[] = []
accountings.forEach(a=>{
const acc = {...a.dataValues}
const utxo = utxos.find(u=>u.address===a.onchainAddress)
if(utxo) {
acc.amount = utxo.amount_sat
acc.confirmations = utxo.confirmations
ret.push(acc)
}
})
success(res, ret.map(acc=> jsonUtils.accountingToJson(acc)))
} catch(e) {
failure(res, e)
}
}
export async function queryOnchainAddress(req, res) {
console.log('=> queryOnchainAddress')
const uuid = short.generate()
const owner = await models.Contact.findOne({ where: { isOwner: true } })
const app = req.params.app;
const query:Query = {
type:'onchain_address',
uuid,
app
}
const opts = {
amt: constants.min_sat_amount,
dest: hub_pubkey,
data: <network.Msg>{
type: constants.message_types.query,
message: {
content: JSON.stringify(query)
},
sender: { pub_key: owner.publicKey }
}
}
try {
await network.signAndSend(opts)
} catch (e) {
failure(res, e)
return
}
let i = 0
let interval = setInterval(() => {
if (i >= 15) {
clearInterval(interval)
delete queries[uuid]
failure(res, 'no response received')
return
}
if (queries[uuid]) {
success(res, queries[uuid].result)
clearInterval(interval)
delete queries[uuid]
return
}
i++
}, 1000)
}
export const receiveQuery = async (payload) => {
const dat = payload.content || payload
const sender_pub_key = dat.sender.pub_key
const content = dat.message.content
const owner = await models.Contact.findOne({ where: { isOwner: true } })
if(!sender_pub_key || !content || !owner) {
return console.log('=> wrong query format')
}
let q:Query
try {
q = JSON.parse(content)
} catch(e) {
console.log("=> ERROR receiveQuery,",e)
return
}
console.log('=> query received', q)
let result = ''
switch (q.type) {
case 'onchain_address':
const addy = await lightning.newAddress(lightning.NESTED_PUBKEY_HASH)
const acc = {
date: new Date(),
pubkey: sender_pub_key,
onchainAddress: addy,
amount: 0,
sourceApp: q.app,
status:constants.statuses.pending,
error:'',
}
await models.Accounting.create(acc)
result = addy
}
const ret:Query = {
type: q.type,
uuid: q.uuid,
app: q.app,
result,
}
const opts = {
amt: constants.min_sat_amount,
dest: sender_pub_key,
data: <network.Msg>{
type: constants.message_types.query_response,
message: {
content: JSON.stringify(ret)
},
sender: { pub_key: owner.publicKey }
}
}
try {
await network.signAndSend(opts)
} catch (e) {
console.log("FAILED TO SEND QUERY_RESPONSE")
return
}
}
export const receiveQueryResponse = async (payload) => {
console.log('=> receiveQueryResponse')
const dat = payload.content || payload
// const sender_pub_key = dat.sender.pub_key
const content = dat.message.content
try {
const q:Query = JSON.parse(content)
queries[q.uuid] = q
} catch(e) {
console.log("=> ERROR receiveQueryResponse,",e)
}
}