const serialize = require('../api/resolvers/serial') const { authenticatedLndGrpc, getInvoice, getPayment } = require('ln-service') const { lnd } = authenticatedLndGrpc({ cert: process.env.LND_CERT, macaroon: process.env.LND_MACAROON, socket: process.env.LND_SOCKET }) const walletOptions = { startAfter: 5, retryLimit: 21, retryBackoff: true } function checkInvoice ({ boss, models }) { return async function ({ data: { hash } }) { let inv try { inv = await getInvoice({ id: hash, lnd }) } catch (err) { console.log(err) // on lnd related errors, we manually retry which so we don't exponentially backoff await boss.send('checkInvoice', { hash }, walletOptions) return } console.log(inv) if (inv.is_confirmed) { await serialize(models, models.$executeRaw`SELECT confirm_invoice(${inv.id}, ${Number(inv.received_mtokens)})`) } else if (inv.is_canceled) { // mark as cancelled await serialize(models, models.invoice.update({ where: { hash: inv.id }, data: { cancelled: true } })) } else if (new Date(inv.expires_at) > new Date()) { // not expired, recheck in 5 seconds await boss.send('checkInvoice', { hash }, walletOptions) } } } function checkWithdrawal ({ boss, models }) { return async function ({ data: { id, hash } }) { let wdrwl let notFound = false try { wdrwl = await getPayment({ id: hash, lnd }) } catch (err) { console.log(err) if (err[1] === 'SentPaymentNotFound') { notFound = true } else { // on lnd related errors, we manually retry which so we don't exponentially backoff await boss.send('checkWithdrawal', { id, hash }, walletOptions) return } } console.log(wdrwl) if (wdrwl?.is_confirmed) { const fee = Number(wdrwl.payment.fee_mtokens) const paid = Number(wdrwl.payment.mtokens) - fee await serialize(models, models.$executeRaw` SELECT confirm_withdrawl(${id}, ${paid}, ${fee})`) } else if (wdrwl?.is_failed || notFound) { let status = 'UNKNOWN_FAILURE' if (wdrwl?.failed.is_insufficient_balance) { status = 'INSUFFICIENT_BALANCE' } else if (wdrwl?.failed.is_invalid_payment) { status = 'INVALID_PAYMENT' } else if (wdrwl?.failed.is_pathfinding_timeout) { status = 'PATHFINDING_TIMEOUT' } else if (wdrwl?.failed.is_route_not_found) { status = 'ROUTE_NOT_FOUND' } await serialize(models, models.$executeRaw` SELECT reverse_withdrawl(${id}, ${status})`) } else { // we need to requeue to check again in 5 seconds await boss.send('checkWithdrawal', { id, hash }, walletOptions) } } } module.exports = { checkInvoice, checkWithdrawal }