2024-08-13 14:48:30 +00:00
|
|
|
import { toPositiveNumber } from '@/lib/validate'
|
2021-04-29 21:58:43 +00:00
|
|
|
import lndService from 'ln-service'
|
|
|
|
|
2021-06-09 21:29:15 +00:00
|
|
|
const { lnd } = lndService.authenticatedLndGrpc({
|
2021-06-11 00:49:20 +00:00
|
|
|
cert: process.env.LND_CERT,
|
2021-06-09 21:29:15 +00:00
|
|
|
macaroon: process.env.LND_MACAROON,
|
|
|
|
socket: process.env.LND_SOCKET
|
|
|
|
})
|
2021-04-29 21:58:43 +00:00
|
|
|
|
2023-05-17 01:09:55 +00:00
|
|
|
// Check LND GRPC connection
|
|
|
|
lndService.getWalletInfo({ lnd }, (err, result) => {
|
|
|
|
if (err) {
|
|
|
|
console.error('LND GRPC connection error')
|
|
|
|
return
|
|
|
|
}
|
|
|
|
console.log('LND GRPC connection successful')
|
|
|
|
})
|
|
|
|
|
2024-08-13 14:48:30 +00:00
|
|
|
export async function estimateRouteFee ({ lnd, destination, tokens, mtokens, request, timeout }) {
|
|
|
|
return await new Promise((resolve, reject) => {
|
|
|
|
lnd.router.estimateRouteFee({
|
|
|
|
dest: Buffer.from(destination, 'hex'),
|
|
|
|
amt_sat: tokens ? toPositiveNumber(tokens) : toPositiveNumber(BigInt(mtokens) / BigInt(1e3)),
|
|
|
|
payment_request: request,
|
|
|
|
timeout
|
|
|
|
}, (err, res) => {
|
|
|
|
if (err) {
|
|
|
|
reject(err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if (res?.failure_reason) {
|
|
|
|
reject(new Error(`Unable to estimate route: ${res.failure_reason}`))
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if (res.routing_fee_msat < 0 || res.time_lock_delay <= 0) {
|
|
|
|
reject(new Error('Unable to estimate route, excessive values: ' + JSON.stringify(res)))
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
resolve({
|
|
|
|
routingFeeMsat: toPositiveNumber(res.routing_fee_msat),
|
|
|
|
timeLockDelay: toPositiveNumber(res.time_lock_delay)
|
|
|
|
})
|
|
|
|
})
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
// created_height is the accepted_height, timeout is the expiry height
|
|
|
|
// ln-service remaps the `htlcs` field of lookupInvoice to `payments` and
|
|
|
|
// see: https://github.com/alexbosworth/lightning/blob/master/lnd_responses/htlc_as_payment.js
|
|
|
|
// and: https://lightning.engineering/api-docs/api/lnd/lightning/lookup-invoice/index.html#lnrpcinvoicehtlc
|
|
|
|
export function hodlInvoiceCltvDetails (inv) {
|
|
|
|
if (!inv.payments) {
|
|
|
|
throw new Error('No payments found')
|
|
|
|
}
|
|
|
|
if (!inv.is_held) {
|
|
|
|
throw new Error('Invoice is not held')
|
|
|
|
}
|
|
|
|
|
|
|
|
const acceptHeight = inv.payments.reduce((max, htlc) => {
|
|
|
|
const createdHeight = toPositiveNumber(htlc.created_height)
|
|
|
|
return createdHeight > max ? createdHeight : max
|
|
|
|
}, 0)
|
|
|
|
const expiryHeight = inv.payments.reduce((min, htlc) => {
|
|
|
|
const timeout = toPositiveNumber(htlc.timeout)
|
|
|
|
return timeout < min ? timeout : min
|
|
|
|
}, Number.MAX_SAFE_INTEGER)
|
|
|
|
|
|
|
|
return {
|
|
|
|
expiryHeight: toPositiveNumber(expiryHeight),
|
|
|
|
acceptHeight: toPositiveNumber(acceptHeight)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export function getPaymentFailureStatus (withdrawal) {
|
|
|
|
if (withdrawal && !withdrawal.is_failed) {
|
|
|
|
throw new Error('withdrawal is not failed')
|
|
|
|
}
|
|
|
|
|
|
|
|
if (withdrawal?.failed.is_insufficient_balance) {
|
|
|
|
return 'INSUFFICIENT_BALANCE'
|
|
|
|
} else if (withdrawal?.failed.is_invalid_payment) {
|
|
|
|
return 'INVALID_PAYMENT'
|
|
|
|
} else if (withdrawal?.failed.is_pathfinding_timeout) {
|
|
|
|
return 'PATHFINDING_TIMEOUT'
|
|
|
|
} else if (withdrawal?.failed.is_route_not_found) {
|
|
|
|
return 'ROUTE_NOT_FOUND'
|
|
|
|
}
|
|
|
|
|
|
|
|
return 'UNKNOWN_FAILURE'
|
|
|
|
}
|
|
|
|
|
2021-06-09 21:29:15 +00:00
|
|
|
export default lnd
|