commit
4df7a328ee
6 changed files with 52 additions and 11 deletions
|
|
@ -69,6 +69,10 @@ export class LiquidityProvider {
|
|||
})
|
||||
}
|
||||
|
||||
GetLatestMaxWithdrawable = () => {
|
||||
return this.latestMaxWithdrawable || 0
|
||||
}
|
||||
|
||||
CheckUserState = async () => {
|
||||
const res = await this.client.GetUserInfo()
|
||||
if (res.status === 'ERROR') {
|
||||
|
|
|
|||
|
|
@ -269,11 +269,11 @@ export default class {
|
|||
return res.response
|
||||
}
|
||||
|
||||
async NewInvoice(value: number, memo: string, expiry: number): Promise<Invoice> {
|
||||
async NewInvoice(value: number, memo: string, expiry: number, useProvider = false): Promise<Invoice> {
|
||||
this.log("generating new invoice for", value, "sats")
|
||||
await this.Health()
|
||||
const shouldUseLiquidityProvider = await this.ShouldUseLiquidityProvider({ action: 'receive', amount: value })
|
||||
if (shouldUseLiquidityProvider) {
|
||||
if (shouldUseLiquidityProvider || useProvider) {
|
||||
const invoice = await this.liquidProvider.AddInvoice(value, memo)
|
||||
return { payRequest: invoice }
|
||||
}
|
||||
|
|
@ -300,7 +300,7 @@ export default class {
|
|||
const r = res.response
|
||||
return { local: r.localBalance ? Number(r.localBalance.sat) : 0, remote: r.remoteBalance ? Number(r.remoteBalance.sat) : 0 }
|
||||
}
|
||||
async PayInvoice(invoice: string, amount: number, feeLimit: number): Promise<PaidInvoice> {
|
||||
async PayInvoice(invoice: string, amount: number, feeLimit: number, useProvider = false): Promise<PaidInvoice> {
|
||||
if (this.outgoingOpsLocked) {
|
||||
this.log("outgoing ops locked, rejecting payment request")
|
||||
throw new Error("lnd node is currently out of sync")
|
||||
|
|
@ -308,7 +308,7 @@ export default class {
|
|||
await this.Health()
|
||||
this.log("paying invoice", invoice, "for", amount, "sats")
|
||||
const shouldUseLiquidityProvider = await this.ShouldUseLiquidityProvider({ action: 'spend', amount })
|
||||
if (shouldUseLiquidityProvider) {
|
||||
if (shouldUseLiquidityProvider || useProvider) {
|
||||
const res = await this.liquidProvider.PayInvoice(invoice)
|
||||
return { feeSat: res.network_fee + res.service_fee, valueSat: res.amount_paid, paymentPreimage: res.preimage }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ export default class {
|
|||
this.liquidityManager = new LiquidityManager(this.settings.liquiditySettings, this.storage, this.liquidProvider, this.lnd)
|
||||
this.metricsManager = new MetricsManager(this.storage, this.lnd)
|
||||
|
||||
this.paymentManager = new PaymentManager(this.storage, this.lnd, this.settings, this.addressPaidCb, this.invoicePaidCb)
|
||||
this.paymentManager = new PaymentManager(this.storage, this.lnd, this.settings, this.liquidityManager, this.addressPaidCb, this.invoicePaidCb)
|
||||
this.productManager = new ProductManager(this.storage, this.paymentManager, this.settings)
|
||||
this.applicationManager = new ApplicationManager(this.storage, this.settings, this.paymentManager)
|
||||
this.appUserManager = new AppUserManager(this.storage, this.settings, this.applicationManager)
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import { LiquidityProvider } from "../lnd/liquidityProvider.js"
|
|||
import LND from "../lnd/lnd.js"
|
||||
import { FlashsatsLSP, LoadLSPSettingsFromEnv, LSPSettings, OlympusLSP, VoltageLSP } from "../lnd/lsp.js"
|
||||
import Storage from '../storage/index.js'
|
||||
import { defaultInvoiceExpiry } from "../storage/paymentStorage.js"
|
||||
export type LiquiditySettings = {
|
||||
lspSettings: LSPSettings
|
||||
liquidityProviderPub: string
|
||||
|
|
@ -32,7 +33,26 @@ export class LiquidityManager {
|
|||
this.voltageLSP = new VoltageLSP(settings.lspSettings, lnd, liquidityProvider)
|
||||
this.flashsatsLSP = new FlashsatsLSP(settings.lspSettings, lnd, liquidityProvider)
|
||||
}
|
||||
beforeInvoiceCreation = async () => { }
|
||||
onNewBlock = async () => {
|
||||
const balance = await this.liquidityProvider.GetLatestMaxWithdrawable()
|
||||
const { remote } = await this.lnd.ChannelBalance()
|
||||
if (remote > balance) {
|
||||
this.log("draining provider balance to channel")
|
||||
const invoice = await this.lnd.NewInvoice(balance, "liqudity provider drain", defaultInvoiceExpiry)
|
||||
const res = await this.liquidityProvider.PayInvoice(invoice.payRequest)
|
||||
this.log("drained provider balance to channel", res.amount_paid)
|
||||
}
|
||||
}
|
||||
|
||||
beforeInvoiceCreation = async (amount: number): Promise<'lnd' | 'provider'> => {
|
||||
const { remote } = await this.lnd.ChannelBalance()
|
||||
if (remote > amount) {
|
||||
this.log("channel has enough balance for invoice")
|
||||
return 'lnd'
|
||||
}
|
||||
this.log("channel does not have enough balance for invoice,suggesting provider")
|
||||
return 'provider'
|
||||
}
|
||||
afterInInvoicePaid = async () => {
|
||||
const existingOrder = await this.storage.liquidityStorage.GetLatestLspOrder()
|
||||
if (existingOrder) {
|
||||
|
|
@ -67,6 +87,14 @@ export class LiquidityManager {
|
|||
this.log("no channel requested")
|
||||
}
|
||||
|
||||
beforeOutInvoicePayment = async () => { }
|
||||
beforeOutInvoicePayment = async (amount: number): Promise<'lnd' | 'provider'> => {
|
||||
const balance = await this.liquidityProvider.GetLatestMaxWithdrawable()
|
||||
if (balance > amount) {
|
||||
this.log("provider has enough balance for payment")
|
||||
return 'provider'
|
||||
}
|
||||
this.log("provider does not have enough balance for payment, suggesting lnd")
|
||||
return 'lnd'
|
||||
}
|
||||
afterOutInvoicePaid = async () => { }
|
||||
}
|
||||
|
|
@ -16,6 +16,7 @@ import { AddressReceivingTransaction } from '../storage/entity/AddressReceivingT
|
|||
import { UserTransactionPayment } from '../storage/entity/UserTransactionPayment.js'
|
||||
import { Watchdog } from './watchdog.js'
|
||||
import { LiquidityProvider } from '../lnd/liquidityProvider.js'
|
||||
import { LiquidityManager } from './liquidityManager.js'
|
||||
interface UserOperationInfo {
|
||||
serial_id: number
|
||||
paid_amount: number
|
||||
|
|
@ -47,11 +48,13 @@ export default class {
|
|||
invoicePaidCb: InvoicePaidCb
|
||||
log = getLogger({ component: "PaymentManager" })
|
||||
watchDog: Watchdog
|
||||
constructor(storage: Storage, lnd: LND, settings: MainSettings, addressPaidCb: AddressPaidCb, invoicePaidCb: InvoicePaidCb) {
|
||||
liquidityManager: LiquidityManager
|
||||
constructor(storage: Storage, lnd: LND, settings: MainSettings, liquidityManager: LiquidityManager, addressPaidCb: AddressPaidCb, invoicePaidCb: InvoicePaidCb) {
|
||||
this.storage = storage
|
||||
this.settings = settings
|
||||
this.lnd = lnd
|
||||
this.watchDog = new Watchdog(settings.watchDogSettings, lnd, storage)
|
||||
this.liquidityManager = liquidityManager
|
||||
this.addressPaidCb = addressPaidCb
|
||||
this.invoicePaidCb = invoicePaidCb
|
||||
}
|
||||
|
|
@ -121,7 +124,8 @@ export default class {
|
|||
if (user.locked) {
|
||||
throw new Error("user is banned, cannot generate invoice")
|
||||
}
|
||||
const res = await this.lnd.NewInvoice(req.amountSats, req.memo, options.expiry)
|
||||
const use = await this.liquidityManager.beforeInvoiceCreation(req.amountSats)
|
||||
const res = await this.lnd.NewInvoice(req.amountSats, req.memo, options.expiry, use === 'provider')
|
||||
const userInvoice = await this.storage.paymentStorage.AddUserInvoice(user, res.payRequest, options)
|
||||
const appId = options.linkedApplication ? options.linkedApplication.app_id : ""
|
||||
this.storage.eventsLog.LogEvent({ type: 'new_invoice', userId: user.user_id, appUserId: "", appId, balance: user.balance_sats, data: userInvoice.invoice, amount: req.amountSats })
|
||||
|
|
@ -201,8 +205,9 @@ export default class {
|
|||
const routingFeeLimit = this.lnd.GetFeeLimitAmount(payAmount)
|
||||
await this.storage.userStorage.DecrementUserBalance(userId, totalAmountToDecrement + routingFeeLimit, invoice)
|
||||
const pendingPayment = await this.storage.paymentStorage.AddPendingExternalPayment(userId, invoice, payAmount, linkedApplication)
|
||||
const use = await this.liquidityManager.beforeOutInvoicePayment(payAmount)
|
||||
try {
|
||||
const payment = await this.lnd.PayInvoice(invoice, amountForLnd, routingFeeLimit)
|
||||
const payment = await this.lnd.PayInvoice(invoice, amountForLnd, routingFeeLimit, use === 'provider')
|
||||
|
||||
if (routingFeeLimit - payment.feeSat > 0) {
|
||||
this.log("refund routing fee", routingFeeLimit, payment.feeSat, "sats")
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { EnvCanBeInteger } from "../helpers/envParser.js";
|
||||
import FunctionQueue from "../helpers/functionQueue.js";
|
||||
import { getLogger } from "../helpers/logger.js";
|
||||
import { LiquidityProvider } from "../lnd/liquidityProvider.js";
|
||||
import LND from "../lnd/lnd.js";
|
||||
import { ChannelBalance } from "../lnd/settings.js";
|
||||
import Storage from '../storage/index.js'
|
||||
|
|
@ -20,6 +21,7 @@ export class Watchdog {
|
|||
latestIndexOffset: number;
|
||||
accumulatedHtlcFees: number;
|
||||
lnd: LND;
|
||||
liquidProvider: LiquidityProvider;
|
||||
settings: WatchdogSettings;
|
||||
storage: Storage;
|
||||
latestCheckStart = 0
|
||||
|
|
@ -30,6 +32,7 @@ export class Watchdog {
|
|||
this.lnd = lnd;
|
||||
this.settings = settings;
|
||||
this.storage = storage;
|
||||
this.liquidProvider = lnd.liquidProvider
|
||||
this.queue = new FunctionQueue("watchdog_queue", () => this.StartCheck())
|
||||
}
|
||||
|
||||
|
|
@ -76,7 +79,8 @@ export class Watchdog {
|
|||
getLogger({ component: "debugLndBalancev3" })({ w: walletBalance, c: channelsBalance, u: usersTotal, f: this.accumulatedHtlcFees })
|
||||
const totalLightningBalanceMsats = (channelsBalance.localBalance?.msat || 0n) + (channelsBalance.unsettledLocalBalance?.msat || 0n)
|
||||
const totalLightningBalance = Math.ceil(Number(totalLightningBalanceMsats) / 1000)
|
||||
return Number(walletBalance.confirmedBalance) + totalLightningBalance
|
||||
const providerBalance = this.liquidProvider.GetLatestMaxWithdrawable()
|
||||
return Number(walletBalance.confirmedBalance) + totalLightningBalance + providerBalance
|
||||
}
|
||||
|
||||
checkBalanceUpdate = (deltaLnd: number, deltaUsers: number) => {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue