more bypassing
This commit is contained in:
parent
aed90ae929
commit
7728073653
8 changed files with 106 additions and 6 deletions
22
package-lock.json
generated
22
package-lock.json
generated
|
|
@ -33,6 +33,7 @@
|
||||||
"globby": "^13.1.2",
|
"globby": "^13.1.2",
|
||||||
"grpc-tools": "^1.12.4",
|
"grpc-tools": "^1.12.4",
|
||||||
"jsonwebtoken": "^9.0.2",
|
"jsonwebtoken": "^9.0.2",
|
||||||
|
"light-bolt11-decoder": "^3.2.0",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"nostr-tools": "^2.13.0",
|
"nostr-tools": "^2.13.0",
|
||||||
"pg": "^8.4.0",
|
"pg": "^8.4.0",
|
||||||
|
|
@ -4333,6 +4334,27 @@
|
||||||
"safe-buffer": "~5.1.0"
|
"safe-buffer": "~5.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/light-bolt11-decoder": {
|
||||||
|
"version": "3.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/light-bolt11-decoder/-/light-bolt11-decoder-3.2.0.tgz",
|
||||||
|
"integrity": "sha512-3QEofgiBOP4Ehs9BI+RkZdXZNtSys0nsJ6fyGeSiAGCBsMwHGUDS/JQlY/sTnWs91A2Nh0S9XXfA8Sy9g6QpuQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@scure/base": "1.1.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/light-bolt11-decoder/node_modules/@scure/base": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.1.tgz",
|
||||||
|
"integrity": "sha512-ZxOhsSyxYwLJj3pLZCefNitxsj093tb2vq90mp2txoYeBqbcjDjqFhyM8eUjq/uFm6zJ+mUuqxlS2FkuSY1MTA==",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "individual",
|
||||||
|
"url": "https://paulmillr.com/funding/"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/lodash": {
|
"node_modules/lodash": {
|
||||||
"version": "4.17.21",
|
"version": "4.17.21",
|
||||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
||||||
|
|
|
||||||
|
|
@ -51,6 +51,7 @@
|
||||||
"globby": "^13.1.2",
|
"globby": "^13.1.2",
|
||||||
"grpc-tools": "^1.12.4",
|
"grpc-tools": "^1.12.4",
|
||||||
"jsonwebtoken": "^9.0.2",
|
"jsonwebtoken": "^9.0.2",
|
||||||
|
"light-bolt11-decoder": "^3.2.0",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"nostr-tools": "^2.13.0",
|
"nostr-tools": "^2.13.0",
|
||||||
"pg": "^8.4.0",
|
"pg": "^8.4.0",
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ import crypto from 'crypto'
|
||||||
import { credentials, Metadata } from '@grpc/grpc-js'
|
import { credentials, Metadata } from '@grpc/grpc-js'
|
||||||
import { GrpcTransport } from "@protobuf-ts/grpc-transport";
|
import { GrpcTransport } from "@protobuf-ts/grpc-transport";
|
||||||
import fs from 'fs'
|
import fs from 'fs'
|
||||||
|
import { decode as decodeBolt11 } from 'light-bolt11-decoder'
|
||||||
import * as Types from '../../../proto/autogenerated/ts/types.js'
|
import * as Types from '../../../proto/autogenerated/ts/types.js'
|
||||||
import { LightningClient } from '../../../proto/lnd/lightning.client.js'
|
import { LightningClient } from '../../../proto/lnd/lightning.client.js'
|
||||||
import { InvoicesClient } from '../../../proto/lnd/invoices.client.js'
|
import { InvoicesClient } from '../../../proto/lnd/invoices.client.js'
|
||||||
|
|
@ -170,6 +171,9 @@ export default class {
|
||||||
return res.response
|
return res.response
|
||||||
}
|
}
|
||||||
async ListPendingChannels(): Promise<PendingChannelsResponse> {
|
async ListPendingChannels(): Promise<PendingChannelsResponse> {
|
||||||
|
if (this.liquidProvider.getSettings().useOnlyLiquidityProvider) {
|
||||||
|
return { pendingOpenChannels: [], pendingClosingChannels: [], pendingForceClosingChannels: [], waitingCloseChannels: [], totalLimboBalance: 0n }
|
||||||
|
}
|
||||||
// console.log("Listing pending channels")
|
// console.log("Listing pending channels")
|
||||||
const res = await this.lightning.pendingChannels({ includeRawTx: false }, DeadLineMetadata())
|
const res = await this.lightning.pendingChannels({ includeRawTx: false }, DeadLineMetadata())
|
||||||
return res.response
|
return res.response
|
||||||
|
|
@ -195,6 +199,10 @@ export default class {
|
||||||
}
|
}
|
||||||
|
|
||||||
async Health(): Promise<void> {
|
async Health(): Promise<void> {
|
||||||
|
// Skip health check when bypass is enabled
|
||||||
|
if (this.liquidProvider.getSettings().useOnlyLiquidityProvider) {
|
||||||
|
return
|
||||||
|
}
|
||||||
// console.log("Checking health")
|
// console.log("Checking health")
|
||||||
if (!this.ready) {
|
if (!this.ready) {
|
||||||
throw new Error("not ready")
|
throw new Error("not ready")
|
||||||
|
|
@ -324,6 +332,10 @@ export default class {
|
||||||
}
|
}
|
||||||
|
|
||||||
async NewAddress(addressType: Types.AddressType, { useProvider, from }: TxActionOptions): Promise<NewAddressResponse> {
|
async NewAddress(addressType: Types.AddressType, { useProvider, from }: TxActionOptions): Promise<NewAddressResponse> {
|
||||||
|
// Force use of provider when bypass is enabled (addresses not supported by provider, but we should fail gracefully)
|
||||||
|
if (this.liquidProvider.getSettings().useOnlyLiquidityProvider) {
|
||||||
|
throw new Error("Address generation not supported when USE_ONLY_LIQUIDITY_PROVIDER is enabled")
|
||||||
|
}
|
||||||
// console.log("Creating new address")
|
// console.log("Creating new address")
|
||||||
let lndAddressType: AddressType
|
let lndAddressType: AddressType
|
||||||
switch (addressType) {
|
switch (addressType) {
|
||||||
|
|
@ -355,7 +367,9 @@ export default class {
|
||||||
|
|
||||||
async NewInvoice(value: number, memo: string, expiry: number, { useProvider, from }: TxActionOptions, blind = false): Promise<Invoice> {
|
async NewInvoice(value: number, memo: string, expiry: number, { useProvider, from }: TxActionOptions, blind = false): Promise<Invoice> {
|
||||||
// console.log("Creating new invoice")
|
// console.log("Creating new invoice")
|
||||||
if (useProvider) {
|
// Force use of provider when bypass is enabled
|
||||||
|
const mustUseProvider = this.liquidProvider.getSettings().useOnlyLiquidityProvider || useProvider
|
||||||
|
if (mustUseProvider) {
|
||||||
console.log("using provider")
|
console.log("using provider")
|
||||||
const invoice = await this.liquidProvider.AddInvoice(value, memo, from, expiry)
|
const invoice = await this.liquidProvider.AddInvoice(value, memo, from, expiry)
|
||||||
const providerDst = this.liquidProvider.GetProviderDestination()
|
const providerDst = this.liquidProvider.GetProviderDestination()
|
||||||
|
|
@ -372,6 +386,23 @@ export default class {
|
||||||
}
|
}
|
||||||
|
|
||||||
async DecodeInvoice(paymentRequest: string): Promise<DecodedInvoice> {
|
async DecodeInvoice(paymentRequest: string): Promise<DecodedInvoice> {
|
||||||
|
if (this.liquidProvider.getSettings().useOnlyLiquidityProvider) {
|
||||||
|
// Use light-bolt11-decoder when LND is bypassed
|
||||||
|
const decoded = decodeBolt11(paymentRequest)
|
||||||
|
let numSatoshis = 0
|
||||||
|
let paymentHash = ''
|
||||||
|
|
||||||
|
for (const section of decoded.sections) {
|
||||||
|
if (section.name === 'amount') {
|
||||||
|
// Amount is in millisatoshis
|
||||||
|
numSatoshis = Math.floor(Number(section.value) / 1000)
|
||||||
|
} else if (section.name === 'payment_hash') {
|
||||||
|
paymentHash = section.value as string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return { numSatoshis, paymentHash }
|
||||||
|
}
|
||||||
// console.log("Decoding invoice")
|
// console.log("Decoding invoice")
|
||||||
const res = await this.lightning.decodePayReq({ payReq: paymentRequest }, DeadLineMetadata())
|
const res = await this.lightning.decodePayReq({ payReq: paymentRequest }, DeadLineMetadata())
|
||||||
return { numSatoshis: Number(res.response.numSatoshis), paymentHash: res.response.paymentHash }
|
return { numSatoshis: Number(res.response.numSatoshis), paymentHash: res.response.paymentHash }
|
||||||
|
|
@ -400,7 +431,9 @@ export default class {
|
||||||
this.log("outgoing ops locked, rejecting payment request")
|
this.log("outgoing ops locked, rejecting payment request")
|
||||||
throw new Error("lnd node is currently out of sync")
|
throw new Error("lnd node is currently out of sync")
|
||||||
}
|
}
|
||||||
if (useProvider) {
|
// Force use of provider when bypass is enabled
|
||||||
|
const mustUseProvider = this.liquidProvider.getSettings().useOnlyLiquidityProvider || useProvider
|
||||||
|
if (mustUseProvider) {
|
||||||
const res = await this.liquidProvider.PayInvoice(invoice, decodedAmount, from)
|
const res = await this.liquidProvider.PayInvoice(invoice, decodedAmount, from)
|
||||||
const providerDst = this.liquidProvider.GetProviderDestination()
|
const providerDst = this.liquidProvider.GetProviderDestination()
|
||||||
return { feeSat: res.network_fee + res.service_fee, valueSat: res.amount_paid, paymentPreimage: res.preimage, providerDst }
|
return { feeSat: res.network_fee + res.service_fee, valueSat: res.amount_paid, paymentPreimage: res.preimage, providerDst }
|
||||||
|
|
@ -455,6 +488,10 @@ export default class {
|
||||||
}
|
}
|
||||||
|
|
||||||
async PayAddress(address: string, amount: number, satPerVByte: number, label = "", { useProvider, from }: TxActionOptions): Promise<SendCoinsResponse> {
|
async PayAddress(address: string, amount: number, satPerVByte: number, label = "", { useProvider, from }: TxActionOptions): Promise<SendCoinsResponse> {
|
||||||
|
// Address payments not supported when bypass is enabled
|
||||||
|
if (this.liquidProvider.getSettings().useOnlyLiquidityProvider) {
|
||||||
|
throw new Error("Address payments not supported when USE_ONLY_LIQUIDITY_PROVIDER is enabled")
|
||||||
|
}
|
||||||
// console.log("Paying address")
|
// console.log("Paying address")
|
||||||
if (this.outgoingOpsLocked) {
|
if (this.outgoingOpsLocked) {
|
||||||
this.log("outgoing ops locked, rejecting payment request")
|
this.log("outgoing ops locked, rejecting payment request")
|
||||||
|
|
@ -551,6 +588,9 @@ export default class {
|
||||||
}
|
}
|
||||||
|
|
||||||
async GetForwardingHistory(indexOffset: number, startTime = 0, endTime = 0): Promise<ForwardingHistoryResponse> {
|
async GetForwardingHistory(indexOffset: number, startTime = 0, endTime = 0): Promise<ForwardingHistoryResponse> {
|
||||||
|
if (this.liquidProvider.getSettings().useOnlyLiquidityProvider) {
|
||||||
|
return { forwardingEvents: [], lastOffsetIndex: indexOffset }
|
||||||
|
}
|
||||||
// console.log("Getting forwarding history")
|
// console.log("Getting forwarding history")
|
||||||
const { response } = await this.lightning.forwardingHistory({ indexOffset, numMaxEvents: 0, startTime: BigInt(startTime), endTime: BigInt(endTime), peerAliasLookup: false }, DeadLineMetadata())
|
const { response } = await this.lightning.forwardingHistory({ indexOffset, numMaxEvents: 0, startTime: BigInt(startTime), endTime: BigInt(endTime), peerAliasLookup: false }, DeadLineMetadata())
|
||||||
return response
|
return response
|
||||||
|
|
@ -586,6 +626,9 @@ export default class {
|
||||||
}
|
}
|
||||||
|
|
||||||
async GetLatestPaymentIndex(from = 0) {
|
async GetLatestPaymentIndex(from = 0) {
|
||||||
|
if (this.liquidProvider.getSettings().useOnlyLiquidityProvider) {
|
||||||
|
return from
|
||||||
|
}
|
||||||
// console.log("Getting latest payment index")
|
// console.log("Getting latest payment index")
|
||||||
let indexOffset = BigInt(from)
|
let indexOffset = BigInt(from)
|
||||||
while (true) {
|
while (true) {
|
||||||
|
|
|
||||||
|
|
@ -212,6 +212,11 @@ export default class {
|
||||||
|
|
||||||
addressPaidCb: AddressPaidCb = (txOutput, address, amount, used) => {
|
addressPaidCb: AddressPaidCb = (txOutput, address, amount, used) => {
|
||||||
return this.storage.StartTransaction(async tx => {
|
return this.storage.StartTransaction(async tx => {
|
||||||
|
// On-chain payments not supported when bypass is enabled
|
||||||
|
if (this.liquidityProvider.getSettings().useOnlyLiquidityProvider) {
|
||||||
|
getLogger({})("addressPaidCb called but USE_ONLY_LIQUIDITY_PROVIDER is enabled, ignoring")
|
||||||
|
return
|
||||||
|
}
|
||||||
const { blockHeight } = await this.lnd.GetInfo()
|
const { blockHeight } = await this.lnd.GetInfo()
|
||||||
const userAddress = await this.storage.paymentStorage.GetAddressOwner(address, tx)
|
const userAddress = await this.storage.paymentStorage.GetAddressOwner(address, tx)
|
||||||
if (!userAddress) {
|
if (!userAddress) {
|
||||||
|
|
|
||||||
|
|
@ -71,6 +71,10 @@ export class LiquidityManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
afterInInvoicePaid = async () => {
|
afterInInvoicePaid = async () => {
|
||||||
|
// Skip channel ordering if using only liquidity provider
|
||||||
|
if (this.settings.getSettings().liquiditySettings.useOnlyLiquidityProvider) {
|
||||||
|
return
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
await this.orderChannelIfNeeded()
|
await this.orderChannelIfNeeded()
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
|
|
@ -91,6 +95,10 @@ export class LiquidityManager {
|
||||||
afterOutInvoicePaid = async () => { }
|
afterOutInvoicePaid = async () => { }
|
||||||
|
|
||||||
shouldDrainProvider = async () => {
|
shouldDrainProvider = async () => {
|
||||||
|
// Skip draining when bypass is enabled
|
||||||
|
if (this.settings.getSettings().liquiditySettings.useOnlyLiquidityProvider) {
|
||||||
|
return
|
||||||
|
}
|
||||||
const maxW = await this.liquidityProvider.GetLatestMaxWithdrawable()
|
const maxW = await this.liquidityProvider.GetLatestMaxWithdrawable()
|
||||||
const { remote } = await this.lnd.ChannelBalance()
|
const { remote } = await this.lnd.ChannelBalance()
|
||||||
const drainable = Math.min(maxW, remote)
|
const drainable = Math.min(maxW, remote)
|
||||||
|
|
@ -148,6 +156,10 @@ export class LiquidityManager {
|
||||||
|
|
||||||
|
|
||||||
shouldOpenChannel = async (): Promise<{ shouldOpen: false } | { shouldOpen: true, maxSpendable: number }> => {
|
shouldOpenChannel = async (): Promise<{ shouldOpen: false } | { shouldOpen: true, maxSpendable: number }> => {
|
||||||
|
// Skip channel operations if using only liquidity provider
|
||||||
|
if (this.settings.getSettings().liquiditySettings.useOnlyLiquidityProvider) {
|
||||||
|
return { shouldOpen: false }
|
||||||
|
}
|
||||||
const threshold = this.settings.getSettings().lspSettings.channelThreshold
|
const threshold = this.settings.getSettings().lspSettings.channelThreshold
|
||||||
if (threshold === 0) {
|
if (threshold === 0) {
|
||||||
return { shouldOpen: false }
|
return { shouldOpen: false }
|
||||||
|
|
|
||||||
|
|
@ -262,10 +262,18 @@ export class OfferManager {
|
||||||
|
|
||||||
async getNofferInvoice(offerReq: NofferData, appId: string, clinkRequester?: { pub: string, eventId: string }): Promise<{ success: true, invoice: string } | { success: false, code: number, max: number }> {
|
async getNofferInvoice(offerReq: NofferData, appId: string, clinkRequester?: { pub: string, eventId: string }): Promise<{ success: true, invoice: string } | { success: false, code: number, max: number }> {
|
||||||
try {
|
try {
|
||||||
const { remote } = await this.lnd.ChannelBalance()
|
// When bypass is enabled, use provider balance instead of LND channel balance
|
||||||
let maxSendable = remote
|
let maxSendable = 0
|
||||||
if (remote === 0 && (await this.liquidityManager.liquidityProvider.IsReady())) {
|
if (this.liquidityManager.settings.getSettings().liquiditySettings.useOnlyLiquidityProvider) {
|
||||||
maxSendable = 10_000_000
|
if (await this.liquidityManager.liquidityProvider.IsReady()) {
|
||||||
|
maxSendable = 10_000_000
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const { remote } = await this.lnd.ChannelBalance()
|
||||||
|
maxSendable = remote
|
||||||
|
if (remote === 0 && (await this.liquidityManager.liquidityProvider.IsReady())) {
|
||||||
|
maxSendable = 10_000_000
|
||||||
|
}
|
||||||
}
|
}
|
||||||
const split = offerReq.offer.split(':')
|
const split = offerReq.offer.split(':')
|
||||||
if (split.length === 1) {
|
if (split.length === 1) {
|
||||||
|
|
|
||||||
|
|
@ -115,6 +115,11 @@ export default class {
|
||||||
}
|
}
|
||||||
|
|
||||||
checkPendingLndPayment = async (log: PubLogger, p: UserInvoicePayment) => {
|
checkPendingLndPayment = async (log: PubLogger, p: UserInvoicePayment) => {
|
||||||
|
// Skip LND payment checks when bypass is enabled
|
||||||
|
if (this.liquidityManager.settings.getSettings().liquiditySettings.useOnlyLiquidityProvider) {
|
||||||
|
log("USE_ONLY_LIQUIDITY_PROVIDER enabled, skipping LND payment check for", p.serial_id)
|
||||||
|
return
|
||||||
|
}
|
||||||
const decoded = await this.lnd.DecodeInvoice(p.invoice)
|
const decoded = await this.lnd.DecodeInvoice(p.invoice)
|
||||||
const payment = await this.lnd.GetPaymentFromHash(decoded.paymentHash)
|
const payment = await this.lnd.GetPaymentFromHash(decoded.paymentHash)
|
||||||
if (!payment || payment.paymentHash !== decoded.paymentHash) {
|
if (!payment || payment.paymentHash !== decoded.paymentHash) {
|
||||||
|
|
|
||||||
|
|
@ -211,6 +211,10 @@ export class Watchdog {
|
||||||
}
|
}
|
||||||
|
|
||||||
PaymentRequested = async () => {
|
PaymentRequested = async () => {
|
||||||
|
// Skip watchdog check when bypass is enabled
|
||||||
|
if (this.liquidProvider.getSettings().useOnlyLiquidityProvider) {
|
||||||
|
return
|
||||||
|
}
|
||||||
if (!this.ready) {
|
if (!this.ready) {
|
||||||
throw new Error("Watchdog not ready")
|
throw new Error("Watchdog not ready")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue