From a596e186fe48bd57ed53591c2ef09adb5c2dd326 Mon Sep 17 00:00:00 2001 From: boufni95 Date: Wed, 21 Jan 2026 16:04:33 +0000 Subject: [PATCH 01/66] admin swaps --- src/services/lnd/swaps.ts | 657 --------------------- src/services/lnd/swaps/reverseSwaps.ts | 280 +++++++++ src/services/lnd/swaps/submarineSwaps.ts | 167 ++++++ src/services/lnd/swaps/swapHelpers.ts | 50 ++ src/services/lnd/swaps/swaps.ts | 226 +++++++ src/services/main/adminManager.ts | 2 +- src/services/main/init.ts | 2 +- src/services/main/paymentManager.ts | 6 +- src/services/storage/db/db.ts | 4 +- src/services/storage/entity/InvoiceSwap.ts | 74 +++ src/services/storage/paymentStorage.ts | 14 +- 11 files changed, 817 insertions(+), 665 deletions(-) delete mode 100644 src/services/lnd/swaps.ts create mode 100644 src/services/lnd/swaps/reverseSwaps.ts create mode 100644 src/services/lnd/swaps/submarineSwaps.ts create mode 100644 src/services/lnd/swaps/swapHelpers.ts create mode 100644 src/services/lnd/swaps/swaps.ts create mode 100644 src/services/storage/entity/InvoiceSwap.ts diff --git a/src/services/lnd/swaps.ts b/src/services/lnd/swaps.ts deleted file mode 100644 index 727f0e88..00000000 --- a/src/services/lnd/swaps.ts +++ /dev/null @@ -1,657 +0,0 @@ -import zkpInit from '@vulpemventures/secp256k1-zkp'; -import axios from 'axios'; -import { crypto, initEccLib, Transaction, address, Network } from 'bitcoinjs-lib'; -// import bolt11 from 'bolt11'; -import { - Musig, SwapTreeSerializer, TaprootUtils, detectSwap, - constructClaimTransaction, targetFee, OutputType, - Networks, -} from 'boltz-core'; -import { randomBytes, createHash } from 'crypto'; -import { ECPairFactory, ECPairInterface } from 'ecpair'; -import * as ecc from 'tiny-secp256k1'; -import ws from 'ws'; -import { getLogger, PubLogger, ERROR } from '../helpers/logger.js'; -import SettingsManager from '../main/settingsManager.js'; -import * as Types from '../../../proto/autogenerated/ts/types.js'; -import { BTCNetwork } from '../main/settings.js'; -import Storage from '../storage/index.js'; -import LND from './lnd.js'; -import { UserInvoicePayment } from '../storage/entity/UserInvoicePayment.js'; -type InvoiceSwapResponse = { id: string, claimPublicKey: string, swapTree: string } -type InvoiceSwapInfo = { paymentHash: string, keys: ECPairInterface } -type InvoiceSwapData = { createdResponse: InvoiceSwapResponse, info: InvoiceSwapInfo } - -type TransactionSwapFees = { - percentage: number, - minerFees: { - claim: number, - lockup: number, - } -} - -type TransactionSwapFeesRes = { - BTC?: { - BTC?: { - fees: TransactionSwapFees - } - } -} - - -type TransactionSwapResponse = { - id: string, refundPublicKey: string, swapTree: string, - timeoutBlockHeight: number, lockupAddress: string, invoice: string, - onchainAmount?: number -} -type TransactionSwapInfo = { destinationAddress: string, preimage: Buffer, keys: ECPairInterface, chainFee: number } -export type TransactionSwapData = { createdResponse: TransactionSwapResponse, info: TransactionSwapInfo } -export class Swaps { - settings: SettingsManager - revSwappers: Record - // submarineSwaps: SubmarineSwaps - storage: Storage - lnd: LND - log = getLogger({ component: 'swaps' }) - constructor(settings: SettingsManager, storage: Storage) { - this.settings = settings - this.revSwappers = {} - const network = settings.getSettings().lndSettings.network - const { boltzHttpUrl, boltzWebSocketUrl, boltsHttpUrlAlt, boltsWebSocketUrlAlt } = settings.getSettings().swapsSettings - if (boltzHttpUrl && boltzWebSocketUrl) { - this.revSwappers[boltzHttpUrl] = new ReverseSwaps({ httpUrl: boltzHttpUrl, wsUrl: boltzWebSocketUrl, network }) - } - if (boltsHttpUrlAlt && boltsWebSocketUrlAlt) { - this.revSwappers[boltsHttpUrlAlt] = new ReverseSwaps({ httpUrl: boltsHttpUrlAlt, wsUrl: boltsWebSocketUrlAlt, network }) - } - this.storage = storage - } - - SetLnd = (lnd: LND) => { - this.lnd = lnd - } - - Stop = () => { } - - GetKeys = (privateKey: string) => { - const keys = ECPairFactory(ecc).fromPrivateKey(Buffer.from(privateKey, 'hex')) - return keys - } - - ListSwaps = async (appUserId: string, payments: UserInvoicePayment[], newOp: (p: UserInvoicePayment) => Types.UserOperation | undefined, getServiceFee: (amt: number) => number): Promise => { - const completedSwaps = await this.storage.paymentStorage.ListCompletedSwaps(appUserId, payments) - const pendingSwaps = await this.storage.paymentStorage.ListPendingTransactionSwaps(appUserId) - return { - swaps: completedSwaps.map(s => { - const p = s.payment - const op = p ? newOp(p) : undefined - return { - operation_payment: op, - swap_operation_id: s.swap.swap_operation_id, - address_paid: s.swap.address_paid, - failure_reason: s.swap.failure_reason, - } - }), - quotes: pendingSwaps.map(s => { - const serviceFee = getServiceFee(s.invoice_amount) - return { - swap_operation_id: s.swap_operation_id, - invoice_amount_sats: s.invoice_amount, - transaction_amount_sats: s.transaction_amount, - chain_fee_sats: s.chain_fee_sats, - service_fee_sats: serviceFee, - swap_fee_sats: s.swap_fee_sats, - service_url: s.service_url, - } - }) - } - } - GetTxSwapQuotes = async (appUserId: string, amt: number, getServiceFee: (decodedAmt: number) => number): Promise => { - if (!this.settings.getSettings().swapsSettings.enableSwaps) { - throw new Error("Swaps are not enabled") - } - const swappers = Object.values(this.revSwappers) - if (swappers.length === 0) { - throw new Error("No swap services available") - } - const res = await Promise.allSettled(swappers.map(sw => this.getTxSwapQuote(sw, appUserId, amt, getServiceFee))) - const failures: string[] = [] - const success: Types.TransactionSwapQuote[] = [] - for (const r of res) { - if (r.status === 'fulfilled') { - success.push(r.value) - } else { - failures.push(r.reason.message ? r.reason.message : r.reason.toString()) - } - } - if (success.length === 0) { - throw new Error(failures.join("\n")) - } - return success - } - - private async getTxSwapQuote(swapper: ReverseSwaps, appUserId: string, amt: number, getServiceFee: (decodedAmt: number) => number): Promise { - this.log("getting transaction swap quote") - const feesRes = await swapper.GetFees() - if (!feesRes.ok) { - throw new Error(feesRes.error) - } - const { claim, lockup } = feesRes.fees.minerFees - const minerFee = claim + lockup - const chainTotal = amt + minerFee - const res = await swapper.SwapTransaction(chainTotal) - if (!res.ok) { - throw new Error(res.error) - } - const decoded = await this.lnd.DecodeInvoice(res.createdResponse.invoice) - const swapFee = decoded.numSatoshis - chainTotal - const serviceFee = getServiceFee(decoded.numSatoshis) - const newSwap = await this.storage.paymentStorage.AddTransactionSwap({ - app_user_id: appUserId, - swap_quote_id: res.createdResponse.id, - swap_tree: JSON.stringify(res.createdResponse.swapTree), - lockup_address: res.createdResponse.lockupAddress, - refund_public_key: res.createdResponse.refundPublicKey, - timeout_block_height: res.createdResponse.timeoutBlockHeight, - invoice: res.createdResponse.invoice, - invoice_amount: decoded.numSatoshis, - transaction_amount: chainTotal, - swap_fee_sats: swapFee, - chain_fee_sats: minerFee, - preimage: res.preimage, - ephemeral_private_key: res.privKey, - ephemeral_public_key: res.pubkey, - service_url: swapper.getHttpUrl(), - }) - return { - swap_operation_id: newSwap.swap_operation_id, - swap_fee_sats: swapFee, - invoice_amount_sats: decoded.numSatoshis, - transaction_amount_sats: amt, - chain_fee_sats: minerFee, - service_fee_sats: serviceFee, - service_url: swapper.getHttpUrl(), - } - } - - async PayAddrWithSwap(appUserId: string, swapOpId: string, address: string, payInvoice: (invoice: string, amt: number) => Promise) { - if (!this.settings.getSettings().swapsSettings.enableSwaps) { - throw new Error("Swaps are not enabled") - } - this.log("paying address with swap", { appUserId, swapOpId, address }) - if (!swapOpId) { - throw new Error("request a swap quote before paying an external address") - } - const txSwap = await this.storage.paymentStorage.GetTransactionSwap(swapOpId, appUserId) - if (!txSwap) { - throw new Error("swap quote not found") - } - const info = await this.lnd.GetInfo() - if (info.blockHeight >= txSwap.timeout_block_height) { - throw new Error("swap timeout") - } - const swapper = this.revSwappers[txSwap.service_url] - if (!swapper) { - throw new Error("swapper service not found") - } - const keys = this.GetKeys(txSwap.ephemeral_private_key) - const data: TransactionSwapData = { - createdResponse: { - id: txSwap.swap_quote_id, - invoice: txSwap.invoice, - lockupAddress: txSwap.lockup_address, - refundPublicKey: txSwap.refund_public_key, - swapTree: txSwap.swap_tree, - timeoutBlockHeight: txSwap.timeout_block_height, - onchainAmount: txSwap.transaction_amount, - }, - info: { - destinationAddress: address, - keys, - chainFee: txSwap.chain_fee_sats, - preimage: Buffer.from(txSwap.preimage, 'hex'), - } - } - // the swap and the invoice payment are linked, swap will not start until the invoice payment is started, and will not complete once the invoice payment is completed - let swapResult = { ok: false, error: "swap never completed" } as { ok: true, txId: string } | { ok: false, error: string } - swapper.SubscribeToTransactionSwap(data, result => { - swapResult = result - }) - try { - await payInvoice(txSwap.invoice, txSwap.invoice_amount) - if (!swapResult.ok) { - this.log("invoice payment successful, but swap failed") - await this.storage.paymentStorage.FailTransactionSwap(swapOpId, address, swapResult.error) - throw new Error(swapResult.error) - } - this.log("swap completed successfully") - await this.storage.paymentStorage.FinalizeTransactionSwap(swapOpId, address, swapResult.txId) - } catch (err: any) { - if (swapResult.ok) { - this.log("failed to pay swap invoice, but swap completed successfully", swapResult.txId) - await this.storage.paymentStorage.FailTransactionSwap(swapOpId, address, err.message) - } else { - this.log("failed to pay swap invoice and swap failed", swapResult.error) - await this.storage.paymentStorage.FailTransactionSwap(swapOpId, address, swapResult.error) - } - throw err - } - const networkFeesTotal = txSwap.chain_fee_sats + txSwap.swap_fee_sats - return { - txId: swapResult.txId, - network_fee: networkFeesTotal - } - } -} - - - -export class ReverseSwaps { - // settings: SettingsManager - private httpUrl: string - private wsUrl: string - log: PubLogger - private network: BTCNetwork - constructor({ httpUrl, wsUrl, network }: { httpUrl: string, wsUrl: string, network: BTCNetwork }) { - this.httpUrl = httpUrl - this.wsUrl = wsUrl - this.network = network - this.log = getLogger({ component: 'ReverseSwaps' }) - initEccLib(ecc) - } - - getHttpUrl = () => { - return this.httpUrl - } - getWsUrl = () => { - return this.wsUrl - } - - calculateFees = (fees: TransactionSwapFees, receiveAmount: number) => { - const pct = fees.percentage / 100 - const minerFee = fees.minerFees.claim + fees.minerFees.lockup - - const preFee = receiveAmount + minerFee - const fee = Math.ceil(preFee * pct) - const total = preFee + fee - return { total, fee, minerFee } - } - - GetFees = async (): Promise<{ ok: true, fees: TransactionSwapFees, } | { ok: false, error: string }> => { - const url = `${this.httpUrl}/v2/swap/reverse` - const feesRes = await loggedGet(this.log, url) - if (!feesRes.ok) { - return { ok: false, error: feesRes.error } - } - if (!feesRes.data.BTC?.BTC?.fees) { - return { ok: false, error: 'No fees found for BTC to BTC swap' } - } - - return { ok: true, fees: feesRes.data.BTC.BTC.fees } - } - - SwapTransaction = async (txAmount: number): Promise<{ ok: true, createdResponse: TransactionSwapResponse, preimage: string, pubkey: string, privKey: string } | { ok: false, error: string }> => { - const preimage = randomBytes(32); - const keys = ECPairFactory(ecc).makeRandom() - if (!keys.privateKey) { - return { ok: false, error: 'Failed to generate keys' } - } - const url = `${this.httpUrl}/v2/swap/reverse` - const req: any = { - onchainAmount: txAmount, - to: 'BTC', - from: 'BTC', - claimPublicKey: Buffer.from(keys.publicKey).toString('hex'), - preimageHash: createHash('sha256').update(preimage).digest('hex'), - } - const createdResponseRes = await loggedPost(this.log, url, req) - if (!createdResponseRes.ok) { - return createdResponseRes - } - const createdResponse = createdResponseRes.data - this.log('Created transaction swap'); - this.log(createdResponse); - return { - ok: true, createdResponse, - preimage: Buffer.from(preimage).toString('hex'), - pubkey: Buffer.from(keys.publicKey).toString('hex'), - privKey: Buffer.from(keys.privateKey).toString('hex') - } - } - - SubscribeToTransactionSwap = async (data: TransactionSwapData, swapDone: (result: { ok: true, txId: string } | { ok: false, error: string }) => void) => { - const webSocket = new ws(`${this.wsUrl}/v2/ws`) - const subReq = { op: 'subscribe', channel: 'swap.update', args: [data.createdResponse.id] } - webSocket.on('open', () => { - webSocket.send(JSON.stringify(subReq)) - }) - let txId = "", isDone = false - const done = () => { - isDone = true - webSocket.close() - swapDone({ ok: true, txId }) - } - webSocket.on('error', (err) => { - this.log(ERROR, 'Error in WebSocket', err.message) - }) - webSocket.on('close', () => { - if (!isDone) { - this.log(ERROR, 'WebSocket closed before swap was done'); - swapDone({ ok: false, error: 'WebSocket closed before swap was done' }) - } - }) - webSocket.on('message', async (rawMsg) => { - try { - const result = await this.handleSwapTransactionMessage(rawMsg, data, done) - if (result) { - txId = result - } - } catch (err: any) { - this.log(ERROR, 'Error handling transaction WebSocket message', err.message) - isDone = true - webSocket.close() - swapDone({ ok: false, error: err.message }) - return - } - }) - } - - handleSwapTransactionMessage = async (rawMsg: ws.RawData, data: TransactionSwapData, done: () => void) => { - const msg = JSON.parse(rawMsg.toString('utf-8')); - if (msg.event !== 'update') { - return; - } - - this.log('Got WebSocket update'); - this.log(msg); - switch (msg.args[0].status) { - // "swap.created" means Boltz is waiting for the invoice to be paid - case 'swap.created': - this.log('Waiting invoice to be paid'); - return; - - // "transaction.mempool" means that Boltz sent an onchain transaction - case 'transaction.mempool': - const txIdRes = await this.handleTransactionMempool(data, msg.args[0].transaction.hex) - if (!txIdRes.ok) { - throw new Error(txIdRes.error) - } - return txIdRes.txId - case 'invoice.settled': - this.log('Transaction swap successful'); - done() - return; - } - } - - handleTransactionMempool = async (data: TransactionSwapData, txHex: string): Promise<{ ok: true, txId: string } | { ok: false, error: string }> => { - this.log('Creating claim transaction'); - const { createdResponse, info } = data - const { destinationAddress, keys, preimage, chainFee } = info - const boltzPublicKey = Buffer.from( - createdResponse.refundPublicKey, - 'hex', - ); - - // Create a musig signing session and tweak it with the Taptree of the swap scripts - const musig = new Musig(await zkpInit(), keys, randomBytes(32), [ - boltzPublicKey, - Buffer.from(keys.publicKey), - ]); - const tweakedKey = TaprootUtils.tweakMusig( - musig, - // swap tree can either be a string or an object - SwapTreeSerializer.deserializeSwapTree(createdResponse.swapTree).tree, - ); - - // Parse the lockup transaction and find the output relevant for the swap - const lockupTx = Transaction.fromHex(txHex); - const swapOutput = detectSwap(tweakedKey, lockupTx); - if (swapOutput === undefined) { - this.log(ERROR, 'No swap output found in lockup transaction'); - return { ok: false, error: 'No swap output found in lockup transaction' } - } - const network = getNetwork(this.network) - // Create a claim transaction to be signed cooperatively via a key path spend - const claimTx = constructClaimTransaction( - [ - { - ...swapOutput, - keys, - preimage, - cooperative: true, - type: OutputType.Taproot, - txHash: lockupTx.getHash(), - }, - ], - address.toOutputScript(destinationAddress, network), - chainFee, - ) - // Get the partial signature from Boltz - const claimUrl = `${this.httpUrl}/v2/swap/reverse/${createdResponse.id}/claim` - const claimReq = { - index: 0, - transaction: claimTx.toHex(), - preimage: preimage.toString('hex'), - pubNonce: Buffer.from(musig.getPublicNonce()).toString('hex'), - } - const boltzSigRes = await loggedPost<{ pubNonce: string, partialSignature: string }>(this.log, claimUrl, claimReq) - if (!boltzSigRes.ok) { - return boltzSigRes - } - const boltzSig = boltzSigRes.data - - // Aggregate the nonces - musig.aggregateNonces([ - [boltzPublicKey, Buffer.from(boltzSig.pubNonce, 'hex')], - ]); - - // Initialize the session to sign the claim transaction - musig.initializeSession( - claimTx.hashForWitnessV1( - 0, - [swapOutput.script], - [swapOutput.value], - Transaction.SIGHASH_DEFAULT, - ), - ); - - // Add the partial signature from Boltz - musig.addPartial( - boltzPublicKey, - Buffer.from(boltzSig.partialSignature, 'hex'), - ); - - // Create our partial signature - musig.signPartial(); - - // Witness of the input to the aggregated signature - claimTx.ins[0].witness = [musig.aggregatePartials()]; - - // Broadcast the finalized transaction - const broadcastUrl = `${this.httpUrl}/v2/chain/BTC/transaction` - const broadcastReq = { - hex: claimTx.toHex(), - } - - const broadcastResponse = await loggedPost(this.log, broadcastUrl, broadcastReq) - if (!broadcastResponse.ok) { - return broadcastResponse - } - this.log('Transaction broadcasted', broadcastResponse.data) - const txId = claimTx.getId() - return { ok: true, txId } - } -} - -const loggedPost = async (log: PubLogger, url: string, req: any): Promise<{ ok: true, data: T } | { ok: false, error: string }> => { - try { - const { data } = await axios.post(url, req) - return { ok: true, data: data as T } - } catch (err: any) { - if (err.response?.data) { - log(ERROR, 'Error sending request', err.response.data) - return { ok: false, error: JSON.stringify(err.response.data) } - } - log(ERROR, 'Error sending request', err.message) - return { ok: false, error: err.message } - } -} - -const loggedGet = async (log: PubLogger, url: string): Promise<{ ok: true, data: T } | { ok: false, error: string }> => { - try { - const { data } = await axios.get(url) - return { ok: true, data: data as T } - } catch (err: any) { - if (err.response?.data) { - log(ERROR, 'Error getting request', err.response.data) - return { ok: false, error: err.response.data } - } - log(ERROR, 'Error getting request', err.message) - return { ok: false, error: err.message } - } -} - -const getNetwork = (network: BTCNetwork): Network => { - switch (network) { - case 'mainnet': - return Networks.bitcoinMainnet - case 'testnet': - return Networks.bitcoinTestnet - case 'regtest': - return Networks.bitcoinRegtest - default: - throw new Error(`Invalid network: ${network}`) - } -} - -// Submarine swaps currently not supported, keeping the code for future reference -/* -export class SubmarineSwaps { - settings: SettingsManager - log: PubLogger - constructor(settings: SettingsManager) { - this.settings = settings - this.log = getLogger({ component: 'SubmarineSwaps' }) - } - - SwapInvoice = async (invoice: string, paymentHash: string) => { - if (!this.settings.getSettings().swapsSettings.enableSwaps) { - this.log(ERROR, 'Swaps are not enabled'); - return; - } - const keys = ECPairFactory(ecc).makeRandom() - const refundPublicKey = Buffer.from(keys.publicKey).toString('hex') - const req = { invoice, to: 'BTC', from: 'BTC', refundPublicKey } - const url = `${this.settings.getSettings().swapsSettings.boltzHttpUrl}/v2/swap/submarine` - this.log('Sending invoice swap request to', url); - const createdResponseRes = await loggedPost(this.log, url, req) - if (!createdResponseRes.ok) { - return createdResponseRes - } - const createdResponse = createdResponseRes.data - this.log('Created invoice swap'); - this.log(createdResponse); - - const webSocket = new ws(`${this.settings.getSettings().swapsSettings.boltzWebSocketUrl}/v2/ws`) - const subReq = { op: 'subscribe', channel: 'swap.update', args: [createdResponse.id] } - webSocket.on('open', () => { - webSocket.send(JSON.stringify(subReq)) - }) - - webSocket.on('message', async (rawMsg) => { - try { - await this.handleSwapInvoiceMessage(rawMsg, { createdResponse, info: { paymentHash, keys } }, () => webSocket.close()) - } catch (err: any) { - this.log(ERROR, 'Error handling invoice WebSocket message', err.message) - webSocket.close() - return - } - }); - } - - handleSwapInvoiceMessage = async (rawMsg: ws.RawData, data: InvoiceSwapData, closeWebSocket: () => void) => { - const msg = JSON.parse(rawMsg.toString('utf-8')); - if (msg.event !== 'update') { - return; - } - - this.log('Got invoice WebSocket update'); - this.log(msg); - switch (msg.args[0].status) { - // "invoice.set" means Boltz is waiting for an onchain transaction to be sent - case 'invoice.set': - this.log('Waiting for onchain transaction'); - return; - // Create a partial signature to allow Boltz to do a key path spend to claim the mainchain coins - case 'transaction.claim.pending': - await this.handleInvoiceClaimPending(data) - return; - - case 'transaction.claimed': - this.log('Invoice swap successful'); - closeWebSocket() - return; - } - - } - - handleInvoiceClaimPending = async (data: InvoiceSwapData) => { - this.log('Creating cooperative claim transaction'); - const { createdResponse, info } = data - const { paymentHash, keys } = info - const { boltzHttpUrl } = this.settings.getSettings().swapsSettings - // Get the information request to create a partial signature - const url = `${boltzHttpUrl}/v2/swap/submarine/${createdResponse.id}/claim` - const claimTxDetailsRes = await loggedGet<{ preimage: string, transactionHash: string, pubNonce: string }>(this.log, url) - if (!claimTxDetailsRes.ok) { - return claimTxDetailsRes - } - const claimTxDetails = claimTxDetailsRes.data - // Verify that Boltz actually paid the invoice by comparing the preimage hash - // of the invoice to the SHA256 hash of the preimage from the response - const claimTxPreimageHash = createHash('sha256').update(Buffer.from(claimTxDetails.preimage, 'hex')).digest() - const invoicePreimageHash = Buffer.from(paymentHash, 'hex') - - if (!claimTxPreimageHash.equals(invoicePreimageHash)) { - this.log(ERROR, 'Boltz provided invalid preimage'); - return; - } - - const boltzPublicKey = Buffer.from(createdResponse.claimPublicKey, 'hex') - - // Create a musig signing instance - const musig = new Musig(await zkpInit(), keys, randomBytes(32), [ - boltzPublicKey, - Buffer.from(keys.publicKey), - ]); - // Tweak that musig with the Taptree of the swap scripts - TaprootUtils.tweakMusig( - musig, - SwapTreeSerializer.deserializeSwapTree(createdResponse.swapTree).tree, - ); - - // Aggregate the nonces - musig.aggregateNonces([ - [boltzPublicKey, Buffer.from(claimTxDetails.pubNonce, 'hex')], - ]); - // Initialize the session to sign the transaction hash from the response - musig.initializeSession( - Buffer.from(claimTxDetails.transactionHash, 'hex'), - ); - - // Give our public nonce and the partial signature to Boltz - const claimUrl = `${boltzHttpUrl}/v2/swap/submarine/${createdResponse.id}/claim` - const claimReq = { - pubNonce: Buffer.from(musig.getPublicNonce()).toString('hex'), - partialSignature: Buffer.from(musig.signPartial()).toString('hex'), - } - const claimResponseRes = await loggedPost<{ pubNonce: string, partialSignature: string }>(this.log, claimUrl, claimReq) - if (!claimResponseRes.ok) { - return claimResponseRes - } - const claimResponse = claimResponseRes.data - this.log('Claim response', claimResponse) - } -} -*/ \ No newline at end of file diff --git a/src/services/lnd/swaps/reverseSwaps.ts b/src/services/lnd/swaps/reverseSwaps.ts new file mode 100644 index 00000000..4510389b --- /dev/null +++ b/src/services/lnd/swaps/reverseSwaps.ts @@ -0,0 +1,280 @@ +import zkpInit from '@vulpemventures/secp256k1-zkp'; +import { initEccLib, Transaction, address } from 'bitcoinjs-lib'; +// import bolt11 from 'bolt11'; +import { + Musig, SwapTreeSerializer, TaprootUtils, detectSwap, + constructClaimTransaction, OutputType, +} from 'boltz-core'; +import { randomBytes, createHash } from 'crypto'; +import { ECPairFactory, ECPairInterface } from 'ecpair'; +import * as ecc from 'tiny-secp256k1'; +import ws from 'ws'; +import { getLogger, PubLogger, ERROR } from '../../helpers/logger.js'; +import { BTCNetwork } from '../../main/settings.js'; +import { loggedGet, loggedPost, getNetwork } from './swapHelpers.js'; + + +type TransactionSwapFees = { + percentage: number, + minerFees: { + claim: number, + lockup: number, + } +} + +type TransactionSwapFeesRes = { + BTC?: { + BTC?: { + fees: TransactionSwapFees + } + } +} + + +type TransactionSwapResponse = { + id: string, refundPublicKey: string, swapTree: string, + timeoutBlockHeight: number, lockupAddress: string, invoice: string, + onchainAmount?: number +} +type TransactionSwapInfo = { destinationAddress: string, preimage: Buffer, keys: ECPairInterface, chainFee: number } +export type TransactionSwapData = { createdResponse: TransactionSwapResponse, info: TransactionSwapInfo } + + + +export class ReverseSwaps { + // settings: SettingsManager + private httpUrl: string + private wsUrl: string + log: PubLogger + private network: BTCNetwork + constructor({ httpUrl, wsUrl, network }: { httpUrl: string, wsUrl: string, network: BTCNetwork }) { + this.httpUrl = httpUrl + this.wsUrl = wsUrl + this.network = network + this.log = getLogger({ component: 'ReverseSwaps' }) + initEccLib(ecc) + } + + getHttpUrl = () => { + return this.httpUrl + } + getWsUrl = () => { + return this.wsUrl + } + + calculateFees = (fees: TransactionSwapFees, receiveAmount: number) => { + const pct = fees.percentage / 100 + const minerFee = fees.minerFees.claim + fees.minerFees.lockup + + const preFee = receiveAmount + minerFee + const fee = Math.ceil(preFee * pct) + const total = preFee + fee + return { total, fee, minerFee } + } + + GetFees = async (): Promise<{ ok: true, fees: TransactionSwapFees, } | { ok: false, error: string }> => { + const url = `${this.httpUrl}/v2/swap/reverse` + const feesRes = await loggedGet(this.log, url) + if (!feesRes.ok) { + return { ok: false, error: feesRes.error } + } + if (!feesRes.data.BTC?.BTC?.fees) { + return { ok: false, error: 'No fees found for BTC to BTC swap' } + } + + return { ok: true, fees: feesRes.data.BTC.BTC.fees } + } + + SwapTransaction = async (txAmount: number): Promise<{ ok: true, createdResponse: TransactionSwapResponse, preimage: string, pubkey: string, privKey: string } | { ok: false, error: string }> => { + const preimage = randomBytes(32); + const keys = ECPairFactory(ecc).makeRandom() + if (!keys.privateKey) { + return { ok: false, error: 'Failed to generate keys' } + } + const url = `${this.httpUrl}/v2/swap/reverse` + const req: any = { + onchainAmount: txAmount, + to: 'BTC', + from: 'BTC', + claimPublicKey: Buffer.from(keys.publicKey).toString('hex'), + preimageHash: createHash('sha256').update(preimage).digest('hex'), + } + const createdResponseRes = await loggedPost(this.log, url, req) + if (!createdResponseRes.ok) { + return createdResponseRes + } + const createdResponse = createdResponseRes.data + this.log('Created transaction swap'); + this.log(createdResponse); + return { + ok: true, createdResponse, + preimage: Buffer.from(preimage).toString('hex'), + pubkey: Buffer.from(keys.publicKey).toString('hex'), + privKey: Buffer.from(keys.privateKey).toString('hex') + } + } + + SubscribeToTransactionSwap = async (data: TransactionSwapData, swapDone: (result: { ok: true, txId: string } | { ok: false, error: string }) => void) => { + const webSocket = new ws(`${this.wsUrl}/v2/ws`) + const subReq = { op: 'subscribe', channel: 'swap.update', args: [data.createdResponse.id] } + webSocket.on('open', () => { + webSocket.send(JSON.stringify(subReq)) + }) + let txId = "", isDone = false + const done = () => { + isDone = true + webSocket.close() + swapDone({ ok: true, txId }) + } + webSocket.on('error', (err) => { + this.log(ERROR, 'Error in WebSocket', err.message) + }) + webSocket.on('close', () => { + if (!isDone) { + this.log(ERROR, 'WebSocket closed before swap was done'); + swapDone({ ok: false, error: 'WebSocket closed before swap was done' }) + } + }) + webSocket.on('message', async (rawMsg) => { + try { + const result = await this.handleSwapTransactionMessage(rawMsg, data, done) + if (result) { + txId = result + } + } catch (err: any) { + this.log(ERROR, 'Error handling transaction WebSocket message', err.message) + isDone = true + webSocket.close() + swapDone({ ok: false, error: err.message }) + return + } + }) + } + + handleSwapTransactionMessage = async (rawMsg: ws.RawData, data: TransactionSwapData, done: () => void) => { + const msg = JSON.parse(rawMsg.toString('utf-8')); + if (msg.event !== 'update') { + return; + } + + this.log('Got WebSocket update'); + this.log(msg); + switch (msg.args[0].status) { + // "swap.created" means Boltz is waiting for the invoice to be paid + case 'swap.created': + this.log('Waiting invoice to be paid'); + return; + + // "transaction.mempool" means that Boltz sent an onchain transaction + case 'transaction.mempool': + const txIdRes = await this.handleTransactionMempool(data, msg.args[0].transaction.hex) + if (!txIdRes.ok) { + throw new Error(txIdRes.error) + } + return txIdRes.txId + case 'invoice.settled': + this.log('Transaction swap successful'); + done() + return; + } + } + + handleTransactionMempool = async (data: TransactionSwapData, txHex: string): Promise<{ ok: true, txId: string } | { ok: false, error: string }> => { + this.log('Creating claim transaction'); + const { createdResponse, info } = data + const { destinationAddress, keys, preimage, chainFee } = info + const boltzPublicKey = Buffer.from( + createdResponse.refundPublicKey, + 'hex', + ); + + // Create a musig signing session and tweak it with the Taptree of the swap scripts + const musig = new Musig(await zkpInit(), keys, randomBytes(32), [ + boltzPublicKey, + Buffer.from(keys.publicKey), + ]); + const tweakedKey = TaprootUtils.tweakMusig( + musig, + // swap tree can either be a string or an object + SwapTreeSerializer.deserializeSwapTree(createdResponse.swapTree).tree, + ); + + // Parse the lockup transaction and find the output relevant for the swap + const lockupTx = Transaction.fromHex(txHex); + const swapOutput = detectSwap(tweakedKey, lockupTx); + if (swapOutput === undefined) { + this.log(ERROR, 'No swap output found in lockup transaction'); + return { ok: false, error: 'No swap output found in lockup transaction' } + } + const network = getNetwork(this.network) + // Create a claim transaction to be signed cooperatively via a key path spend + const claimTx = constructClaimTransaction( + [ + { + ...swapOutput, + keys, + preimage, + cooperative: true, + type: OutputType.Taproot, + txHash: lockupTx.getHash(), + }, + ], + address.toOutputScript(destinationAddress, network), + chainFee, + ) + // Get the partial signature from Boltz + const claimUrl = `${this.httpUrl}/v2/swap/reverse/${createdResponse.id}/claim` + const claimReq = { + index: 0, + transaction: claimTx.toHex(), + preimage: preimage.toString('hex'), + pubNonce: Buffer.from(musig.getPublicNonce()).toString('hex'), + } + const boltzSigRes = await loggedPost<{ pubNonce: string, partialSignature: string }>(this.log, claimUrl, claimReq) + if (!boltzSigRes.ok) { + return boltzSigRes + } + const boltzSig = boltzSigRes.data + + // Aggregate the nonces + musig.aggregateNonces([ + [boltzPublicKey, Buffer.from(boltzSig.pubNonce, 'hex')], + ]); + + // Initialize the session to sign the claim transaction + musig.initializeSession( + claimTx.hashForWitnessV1( + 0, + [swapOutput.script], + [swapOutput.value], + Transaction.SIGHASH_DEFAULT, + ), + ); + + // Add the partial signature from Boltz + musig.addPartial( + boltzPublicKey, + Buffer.from(boltzSig.partialSignature, 'hex'), + ); + + // Create our partial signature + musig.signPartial(); + + // Witness of the input to the aggregated signature + claimTx.ins[0].witness = [musig.aggregatePartials()]; + + // Broadcast the finalized transaction + const broadcastUrl = `${this.httpUrl}/v2/chain/BTC/transaction` + const broadcastReq = { + hex: claimTx.toHex(), + } + + const broadcastResponse = await loggedPost(this.log, broadcastUrl, broadcastReq) + if (!broadcastResponse.ok) { + return broadcastResponse + } + this.log('Transaction broadcasted', broadcastResponse.data) + const txId = claimTx.getId() + return { ok: true, txId } + } +} \ No newline at end of file diff --git a/src/services/lnd/swaps/submarineSwaps.ts b/src/services/lnd/swaps/submarineSwaps.ts new file mode 100644 index 00000000..0c7de08c --- /dev/null +++ b/src/services/lnd/swaps/submarineSwaps.ts @@ -0,0 +1,167 @@ +import zkpInit from '@vulpemventures/secp256k1-zkp'; +// import bolt11 from 'bolt11'; +import { + Musig, SwapTreeSerializer, TaprootUtils +} from 'boltz-core'; +import { randomBytes, createHash } from 'crypto'; +import { ECPairFactory, ECPairInterface } from 'ecpair'; +import * as ecc from 'tiny-secp256k1'; +import ws from 'ws'; +import { getLogger, PubLogger, ERROR } from '../../helpers/logger.js'; +import { loggedGet, loggedPost } from './swapHelpers.js'; +import { BTCNetwork } from '../../main/settings.js'; + +type InvoiceSwapResponse = { id: string, claimPublicKey: string, swapTree: string } +type InvoiceSwapInfo = { paymentHash: string, keys: ECPairInterface } +type InvoiceSwapData = { createdResponse: InvoiceSwapResponse, info: InvoiceSwapInfo } + + +export class SubmarineSwaps { + private httpUrl: string + private wsUrl: string + log: PubLogger + constructor({ httpUrl, wsUrl }: { httpUrl: string, wsUrl: string, network: BTCNetwork }) { + this.httpUrl = httpUrl + this.wsUrl = wsUrl + this.log = getLogger({ component: 'SubmarineSwaps' }) + } + + getHttpUrl = () => { + return this.httpUrl + } + getWsUrl = () => { + return this.wsUrl + } + + SwapInvoice = async (invoice: string, paymentHash: string) => { + const keys = ECPairFactory(ecc).makeRandom() + const refundPublicKey = Buffer.from(keys.publicKey).toString('hex') + const req = { invoice, to: 'BTC', from: 'BTC', refundPublicKey } + const url = `${this.httpUrl}/v2/swap/submarine` + this.log('Sending invoice swap request to', url); + const createdResponseRes = await loggedPost(this.log, url, req) + if (!createdResponseRes.ok) { + return createdResponseRes + } + const createdResponse = createdResponseRes.data + this.log('Created invoice swap'); + this.log(createdResponse); + + + } + + SubscribeToInvoiceSwap = async (data: InvoiceSwapData, swapDone: (result: { ok: true, txId: string } | { ok: false, error: string }) => void) => { + const webSocket = new ws(`${this.wsUrl}/v2/ws`) + const subReq = { op: 'subscribe', channel: 'swap.update', args: [data.createdResponse.id] } + webSocket.on('open', () => { + webSocket.send(JSON.stringify(subReq)) + }) + let txId = "", isDone = false + const done = () => { + isDone = true + webSocket.close() + swapDone({ ok: true, txId }) + } + webSocket.on('error', (err) => { + this.log(ERROR, 'Error in WebSocket', err.message) + }) + webSocket.on('close', () => { + if (!isDone) { + this.log(ERROR, 'WebSocket closed before swap was done'); + swapDone({ ok: false, error: 'WebSocket closed before swap was done' }) + } + }) + webSocket.on('message', async (rawMsg) => { + try { + await this.handleSwapInvoiceMessage(rawMsg, data, done) + } catch (err: any) { + this.log(ERROR, 'Error handling invoice WebSocket message', err.message) + webSocket.close() + return + } + }); + } + + handleSwapInvoiceMessage = async (rawMsg: ws.RawData, data: InvoiceSwapData, closeWebSocket: () => void) => { + const msg = JSON.parse(rawMsg.toString('utf-8')); + if (msg.event !== 'update') { + return; + } + + this.log('Got invoice WebSocket update'); + this.log(msg); + switch (msg.args[0].status) { + // "invoice.set" means Boltz is waiting for an onchain transaction to be sent + case 'invoice.set': + this.log('Waiting for onchain transaction'); + return; + // Create a partial signature to allow Boltz to do a key path spend to claim the mainchain coins + case 'transaction.claim.pending': + await this.handleInvoiceClaimPending(data) + return; + + case 'transaction.claimed': + this.log('Invoice swap successful'); + closeWebSocket() + return; + } + + } + + handleInvoiceClaimPending = async (data: InvoiceSwapData) => { + this.log('Creating cooperative claim transaction'); + const { createdResponse, info } = data + const { paymentHash, keys } = info + // Get the information request to create a partial signature + const url = `${this.httpUrl}/v2/swap/submarine/${createdResponse.id}/claim` + const claimTxDetailsRes = await loggedGet<{ preimage: string, transactionHash: string, pubNonce: string }>(this.log, url) + if (!claimTxDetailsRes.ok) { + return claimTxDetailsRes + } + const claimTxDetails = claimTxDetailsRes.data + // Verify that Boltz actually paid the invoice by comparing the preimage hash + // of the invoice to the SHA256 hash of the preimage from the response + const claimTxPreimageHash = createHash('sha256').update(Buffer.from(claimTxDetails.preimage, 'hex')).digest() + const invoicePreimageHash = Buffer.from(paymentHash, 'hex') + + if (!claimTxPreimageHash.equals(invoicePreimageHash)) { + this.log(ERROR, 'Boltz provided invalid preimage'); + return; + } + + const boltzPublicKey = Buffer.from(createdResponse.claimPublicKey, 'hex') + + // Create a musig signing instance + const musig = new Musig(await zkpInit(), keys, randomBytes(32), [ + boltzPublicKey, + Buffer.from(keys.publicKey), + ]); + // Tweak that musig with the Taptree of the swap scripts + TaprootUtils.tweakMusig( + musig, + SwapTreeSerializer.deserializeSwapTree(createdResponse.swapTree).tree, + ); + + // Aggregate the nonces + musig.aggregateNonces([ + [boltzPublicKey, Buffer.from(claimTxDetails.pubNonce, 'hex')], + ]); + // Initialize the session to sign the transaction hash from the response + musig.initializeSession( + Buffer.from(claimTxDetails.transactionHash, 'hex'), + ); + + // Give our public nonce and the partial signature to Boltz + const claimUrl = `${this.httpUrl}/v2/swap/submarine/${createdResponse.id}/claim` + const claimReq = { + pubNonce: Buffer.from(musig.getPublicNonce()).toString('hex'), + partialSignature: Buffer.from(musig.signPartial()).toString('hex'), + } + const claimResponseRes = await loggedPost<{ pubNonce: string, partialSignature: string }>(this.log, claimUrl, claimReq) + if (!claimResponseRes.ok) { + return claimResponseRes + } + const claimResponse = claimResponseRes.data + this.log('Claim response', claimResponse) + } +} diff --git a/src/services/lnd/swaps/swapHelpers.ts b/src/services/lnd/swaps/swapHelpers.ts new file mode 100644 index 00000000..8c34f4fd --- /dev/null +++ b/src/services/lnd/swaps/swapHelpers.ts @@ -0,0 +1,50 @@ +import axios from 'axios'; +import { Network } from 'bitcoinjs-lib'; +// import bolt11 from 'bolt11'; +import { + Networks, +} from 'boltz-core'; +import { PubLogger, ERROR } from '../../helpers/logger.js'; +import { BTCNetwork } from '../../main/settings.js'; + + +export const loggedPost = async (log: PubLogger, url: string, req: any): Promise<{ ok: true, data: T } | { ok: false, error: string }> => { + try { + const { data } = await axios.post(url, req) + return { ok: true, data: data as T } + } catch (err: any) { + if (err.response?.data) { + log(ERROR, 'Error sending request', err.response.data) + return { ok: false, error: JSON.stringify(err.response.data) } + } + log(ERROR, 'Error sending request', err.message) + return { ok: false, error: err.message } + } +} + +export const loggedGet = async (log: PubLogger, url: string): Promise<{ ok: true, data: T } | { ok: false, error: string }> => { + try { + const { data } = await axios.get(url) + return { ok: true, data: data as T } + } catch (err: any) { + if (err.response?.data) { + log(ERROR, 'Error getting request', err.response.data) + return { ok: false, error: err.response.data } + } + log(ERROR, 'Error getting request', err.message) + return { ok: false, error: err.message } + } +} + +export const getNetwork = (network: BTCNetwork): Network => { + switch (network) { + case 'mainnet': + return Networks.bitcoinMainnet + case 'testnet': + return Networks.bitcoinTestnet + case 'regtest': + return Networks.bitcoinRegtest + default: + throw new Error(`Invalid network: ${network}`) + } +} \ No newline at end of file diff --git a/src/services/lnd/swaps/swaps.ts b/src/services/lnd/swaps/swaps.ts new file mode 100644 index 00000000..e53c8751 --- /dev/null +++ b/src/services/lnd/swaps/swaps.ts @@ -0,0 +1,226 @@ +import { ECPairFactory } from 'ecpair'; +import * as ecc from 'tiny-secp256k1'; +import { getLogger } from '../../helpers/logger.js'; +import SettingsManager from '../../main/settingsManager.js'; +import * as Types from '../../../../proto/autogenerated/ts/types.js'; +import Storage from '../../storage/index.js'; +import LND from '../lnd.js'; +import { UserInvoicePayment } from '../../storage/entity/UserInvoicePayment.js'; +import { ReverseSwaps, TransactionSwapData } from './reverseSwaps.js'; +import { SubmarineSwaps } from './submarineSwaps.js'; + + +export class Swaps { + settings: SettingsManager + revSwappers: Record + subSwappers: Record + storage: Storage + lnd: LND + log = getLogger({ component: 'swaps' }) + constructor(settings: SettingsManager, storage: Storage) { + this.settings = settings + this.revSwappers = {} + this.subSwappers = {} + const network = settings.getSettings().lndSettings.network + const { boltzHttpUrl, boltzWebSocketUrl, boltsHttpUrlAlt, boltsWebSocketUrlAlt } = settings.getSettings().swapsSettings + if (boltzHttpUrl && boltzWebSocketUrl) { + this.revSwappers[boltzHttpUrl] = new ReverseSwaps({ httpUrl: boltzHttpUrl, wsUrl: boltzWebSocketUrl, network }) + this.subSwappers[boltzHttpUrl] = new SubmarineSwaps({ httpUrl: boltzHttpUrl, wsUrl: boltzWebSocketUrl, network }) + } + if (boltsHttpUrlAlt && boltsWebSocketUrlAlt) { + this.revSwappers[boltsHttpUrlAlt] = new ReverseSwaps({ httpUrl: boltsHttpUrlAlt, wsUrl: boltsWebSocketUrlAlt, network }) + this.subSwappers[boltsHttpUrlAlt] = new SubmarineSwaps({ httpUrl: boltsHttpUrlAlt, wsUrl: boltsWebSocketUrlAlt, network }) + } + this.storage = storage + } + + SetLnd = (lnd: LND) => { + this.lnd = lnd + } + + Stop = () => { } + + GetKeys = (privateKey: string) => { + const keys = ECPairFactory(ecc).fromPrivateKey(Buffer.from(privateKey, 'hex')) + return keys + } + + GetInvoiceSwapQuotes = async (appUserId: string, payments: UserInvoicePayment[], getServiceFee: (amt: number) => number): Promise => { + if (!this.settings.getSettings().swapsSettings.enableSwaps) { + throw new Error("Swaps are not enabled") + } + const swappers = Object.values(this.subSwappers) + if (swappers.length === 0) { + throw new Error("No swap services available") + } + const res = await Promise.allSettled(swappers.map(sw => this.getInvoiceSwapQuote(sw, appUserId, payments, getServiceFee))) + const failures: string[] = [] + const success: Types.InvoiceSwapQuote[] = [] + for (const r of res) { } + } + + ListTxSwaps = async (appUserId: string, payments: UserInvoicePayment[], newOp: (p: UserInvoicePayment) => Types.UserOperation | undefined, getServiceFee: (amt: number) => number): Promise => { + const completedSwaps = await this.storage.paymentStorage.ListCompletedTxSwaps(appUserId, payments) + const pendingSwaps = await this.storage.paymentStorage.ListPendingTransactionSwaps(appUserId) + return { + swaps: completedSwaps.map(s => { + const p = s.payment + const op = p ? newOp(p) : undefined + return { + operation_payment: op, + swap_operation_id: s.swap.swap_operation_id, + address_paid: s.swap.address_paid, + failure_reason: s.swap.failure_reason, + } + }), + quotes: pendingSwaps.map(s => { + const serviceFee = getServiceFee(s.invoice_amount) + return { + swap_operation_id: s.swap_operation_id, + invoice_amount_sats: s.invoice_amount, + transaction_amount_sats: s.transaction_amount, + chain_fee_sats: s.chain_fee_sats, + service_fee_sats: serviceFee, + swap_fee_sats: s.swap_fee_sats, + service_url: s.service_url, + } + }) + } + } + GetTxSwapQuotes = async (appUserId: string, amt: number, getServiceFee: (decodedAmt: number) => number): Promise => { + if (!this.settings.getSettings().swapsSettings.enableSwaps) { + throw new Error("Swaps are not enabled") + } + const swappers = Object.values(this.revSwappers) + if (swappers.length === 0) { + throw new Error("No swap services available") + } + const res = await Promise.allSettled(swappers.map(sw => this.getTxSwapQuote(sw, appUserId, amt, getServiceFee))) + const failures: string[] = [] + const success: Types.TransactionSwapQuote[] = [] + for (const r of res) { + if (r.status === 'fulfilled') { + success.push(r.value) + } else { + failures.push(r.reason.message ? r.reason.message : r.reason.toString()) + } + } + if (success.length === 0) { + throw new Error(failures.join("\n")) + } + return success + } + + private async getTxSwapQuote(swapper: ReverseSwaps, appUserId: string, amt: number, getServiceFee: (decodedAmt: number) => number): Promise { + this.log("getting transaction swap quote") + const feesRes = await swapper.GetFees() + if (!feesRes.ok) { + throw new Error(feesRes.error) + } + const { claim, lockup } = feesRes.fees.minerFees + const minerFee = claim + lockup + const chainTotal = amt + minerFee + const res = await swapper.SwapTransaction(chainTotal) + if (!res.ok) { + throw new Error(res.error) + } + const decoded = await this.lnd.DecodeInvoice(res.createdResponse.invoice) + const swapFee = decoded.numSatoshis - chainTotal + const serviceFee = getServiceFee(decoded.numSatoshis) + const newSwap = await this.storage.paymentStorage.AddTransactionSwap({ + app_user_id: appUserId, + swap_quote_id: res.createdResponse.id, + swap_tree: JSON.stringify(res.createdResponse.swapTree), + lockup_address: res.createdResponse.lockupAddress, + refund_public_key: res.createdResponse.refundPublicKey, + timeout_block_height: res.createdResponse.timeoutBlockHeight, + invoice: res.createdResponse.invoice, + invoice_amount: decoded.numSatoshis, + transaction_amount: chainTotal, + swap_fee_sats: swapFee, + chain_fee_sats: minerFee, + preimage: res.preimage, + ephemeral_private_key: res.privKey, + ephemeral_public_key: res.pubkey, + service_url: swapper.getHttpUrl(), + }) + return { + swap_operation_id: newSwap.swap_operation_id, + swap_fee_sats: swapFee, + invoice_amount_sats: decoded.numSatoshis, + transaction_amount_sats: amt, + chain_fee_sats: minerFee, + service_fee_sats: serviceFee, + service_url: swapper.getHttpUrl(), + } + } + + async PayAddrWithSwap(appUserId: string, swapOpId: string, address: string, payInvoice: (invoice: string, amt: number) => Promise) { + if (!this.settings.getSettings().swapsSettings.enableSwaps) { + throw new Error("Swaps are not enabled") + } + this.log("paying address with swap", { appUserId, swapOpId, address }) + if (!swapOpId) { + throw new Error("request a swap quote before paying an external address") + } + const txSwap = await this.storage.paymentStorage.GetTransactionSwap(swapOpId, appUserId) + if (!txSwap) { + throw new Error("swap quote not found") + } + const info = await this.lnd.GetInfo() + if (info.blockHeight >= txSwap.timeout_block_height) { + throw new Error("swap timeout") + } + const swapper = this.revSwappers[txSwap.service_url] + if (!swapper) { + throw new Error("swapper service not found") + } + const keys = this.GetKeys(txSwap.ephemeral_private_key) + const data: TransactionSwapData = { + createdResponse: { + id: txSwap.swap_quote_id, + invoice: txSwap.invoice, + lockupAddress: txSwap.lockup_address, + refundPublicKey: txSwap.refund_public_key, + swapTree: txSwap.swap_tree, + timeoutBlockHeight: txSwap.timeout_block_height, + onchainAmount: txSwap.transaction_amount, + }, + info: { + destinationAddress: address, + keys, + chainFee: txSwap.chain_fee_sats, + preimage: Buffer.from(txSwap.preimage, 'hex'), + } + } + // the swap and the invoice payment are linked, swap will not start until the invoice payment is started, and will not complete once the invoice payment is completed + let swapResult = { ok: false, error: "swap never completed" } as { ok: true, txId: string } | { ok: false, error: string } + swapper.SubscribeToTransactionSwap(data, result => { + swapResult = result + }) + try { + await payInvoice(txSwap.invoice, txSwap.invoice_amount) + if (!swapResult.ok) { + this.log("invoice payment successful, but swap failed") + await this.storage.paymentStorage.FailTransactionSwap(swapOpId, address, swapResult.error) + throw new Error(swapResult.error) + } + this.log("swap completed successfully") + await this.storage.paymentStorage.FinalizeTransactionSwap(swapOpId, address, swapResult.txId) + } catch (err: any) { + if (swapResult.ok) { + this.log("failed to pay swap invoice, but swap completed successfully", swapResult.txId) + await this.storage.paymentStorage.FailTransactionSwap(swapOpId, address, err.message) + } else { + this.log("failed to pay swap invoice and swap failed", swapResult.error) + await this.storage.paymentStorage.FailTransactionSwap(swapOpId, address, swapResult.error) + } + throw err + } + const networkFeesTotal = txSwap.chain_fee_sats + txSwap.swap_fee_sats + return { + txId: swapResult.txId, + network_fee: networkFeesTotal + } + } +} \ No newline at end of file diff --git a/src/services/main/adminManager.ts b/src/services/main/adminManager.ts index 294635ed..1474707a 100644 --- a/src/services/main/adminManager.ts +++ b/src/services/main/adminManager.ts @@ -5,7 +5,7 @@ import Storage from "../storage/index.js"; import * as Types from '../../../proto/autogenerated/ts/types.js' import LND from "../lnd/lnd.js"; import SettingsManager from "./settingsManager.js"; -import { Swaps } from "../lnd/swaps.js"; +import { Swaps } from "../lnd/swaps/swaps.js"; export class AdminManager { settings: SettingsManager storage: Storage diff --git a/src/services/main/init.ts b/src/services/main/init.ts index 3cbba602..121750e3 100644 --- a/src/services/main/init.ts +++ b/src/services/main/init.ts @@ -11,7 +11,7 @@ import { AdminManager } from "./adminManager.js" import SettingsManager from "./settingsManager.js" import { LoadStorageSettingsFromEnv } from "../storage/index.js" import { NostrSender } from "../nostr/sender.js" -import { Swaps } from "../lnd/swaps.js" +import { Swaps } from "../lnd/swaps/swaps.js" export type AppData = { privateKey: string; publicKey: string; diff --git a/src/services/main/paymentManager.ts b/src/services/main/paymentManager.ts index 3c7812db..5fd04022 100644 --- a/src/services/main/paymentManager.ts +++ b/src/services/main/paymentManager.ts @@ -18,7 +18,7 @@ import { LiquidityManager } from './liquidityManager.js' import { Utils } from '../helpers/utilsWrapper.js' import { UserInvoicePayment } from '../storage/entity/UserInvoicePayment.js' import SettingsManager from './settingsManager.js' -import { Swaps, TransactionSwapData } from '../lnd/swaps.js' +import { Swaps, TransactionSwapData } from '../lnd/swaps/swaps.js' import { Transaction, OutputDetail } from '../../../proto/lnd/lightning.js' import { LndAddress } from '../lnd/lnd.js' import Metrics from '../metrics/index.js' @@ -618,10 +618,10 @@ export default class { } async ListSwaps(ctx: Types.UserContext): Promise { - const payments = await this.storage.paymentStorage.ListSwapPayments(ctx.app_user_id) + const payments = await this.storage.paymentStorage.ListTxSwapPayments(ctx.app_user_id) const app = await this.storage.applicationStorage.GetApplication(ctx.app_id) const isManagedUser = ctx.user_id !== app.owner.user_id - return this.swaps.ListSwaps(ctx.app_user_id, payments, p => { + return this.swaps.ListTxSwaps(ctx.app_user_id, payments, p => { const opId = `${Types.UserOperationType.OUTGOING_TX}-${p.serial_id}` return this.newInvoicePaymentOperation({ amount: p.paid_amount, confirmed: p.paid_at_unix !== 0, invoice: p.invoice, opId, networkFee: p.routing_fees, serviceFee: p.service_fees, paidAtUnix: p.paid_at_unix }) }, amt => this.getSendServiceFee(Types.UserOperationType.OUTGOING_INVOICE, amt, isManagedUser)) diff --git a/src/services/storage/db/db.ts b/src/services/storage/db/db.ts index 335f6848..63397c58 100644 --- a/src/services/storage/db/db.ts +++ b/src/services/storage/db/db.ts @@ -30,6 +30,7 @@ import * as fs from 'fs' import { UserAccess } from "../entity/UserAccess.js" import { AdminSettings } from "../entity/AdminSettings.js" import { TransactionSwap } from "../entity/TransactionSwap.js" +import { InvoiceSwap } from "../entity/InvoiceSwap.js" export type DbSettings = { @@ -76,7 +77,8 @@ export const MainDbEntities = { 'AppUserDevice': AppUserDevice, 'UserAccess': UserAccess, 'AdminSettings': AdminSettings, - 'TransactionSwap': TransactionSwap + 'TransactionSwap': TransactionSwap, + 'InvoiceSwap': InvoiceSwap } export type MainDbNames = keyof typeof MainDbEntities export const MainDbEntitiesNames = Object.keys(MainDbEntities) diff --git a/src/services/storage/entity/InvoiceSwap.ts b/src/services/storage/entity/InvoiceSwap.ts new file mode 100644 index 00000000..4548f042 --- /dev/null +++ b/src/services/storage/entity/InvoiceSwap.ts @@ -0,0 +1,74 @@ +import { Entity, PrimaryGeneratedColumn, Column, CreateDateColumn, ManyToOne, JoinColumn, UpdateDateColumn } from "typeorm"; +import { User } from "./User"; + +@Entity() +export class InvoiceSwap { + @PrimaryGeneratedColumn('uuid') + swap_operation_id: string + + @Column() + app_user_id: string + + @Column() + swap_quote_id: string + + @Column() + swap_tree: string + + @Column() + lockup_address: string + + @Column() + refund_public_key: string + + @Column() + timeout_block_height: number + + @Column() + invoice: string + + @Column() + invoice_amount: number + + @Column() + transaction_amount: number + + @Column() + swap_fee_sats: number + + @Column() + chain_fee_sats: number + + @Column() + preimage: string + + @Column() + ephemeral_public_key: string + + // the private key is used on to perform a swap, it does not hold any funds once the swap is completed + // the swap should only last a few seconds, so it is not a security risk to store the private key in the database + // the key is stored here mostly for recovery purposes, in case something goes wrong with the swap + @Column() + ephemeral_private_key: string + + @Column({ default: false }) + used: boolean + + @Column({ default: "" }) + failure_reason: string + + @Column({ default: "" }) + tx_id: string + + @Column({ default: "" }) + address_paid: string + + @Column({ default: "" }) + service_url: string + + @CreateDateColumn() + created_at: Date + + @UpdateDateColumn() + updated_at: Date +} \ No newline at end of file diff --git a/src/services/storage/paymentStorage.ts b/src/services/storage/paymentStorage.ts index ed3f84dd..090ae271 100644 --- a/src/services/storage/paymentStorage.ts +++ b/src/services/storage/paymentStorage.ts @@ -15,6 +15,7 @@ import TransactionsQueue from "./db/transactionsQueue.js"; import { LoggedEvent } from './eventsLog.js'; import { StorageInterface } from './db/storageInterface.js'; import { TransactionSwap } from './entity/TransactionSwap.js'; +import { InvoiceSwap } from './entity/InvoiceSwap.js'; export type InboundOptionals = { product?: Product, callbackUrl?: string, expiry: number, expectedPayer?: User, linkedApplication?: Application, zapInfo?: ZapInfo, offerId?: string, payerData?: Record, rejectUnauthorized?: boolean, token?: string, blind?: boolean, clinkRequesterPub?: string, clinkRequesterEventId?: string } export const defaultInvoiceExpiry = 60 * 60 export default class { @@ -500,11 +501,11 @@ export default class { return this.dbs.Find('TransactionSwap', { where: { used: false, app_user_id: appUserId } }, txId) } - async ListSwapPayments(userId: string, txId?: string) { + async ListTxSwapPayments(userId: string, txId?: string) { return this.dbs.Find('UserInvoicePayment', { where: { swap_operation_id: Not(IsNull()), user: { user_id: userId } } }, txId) } - async ListCompletedSwaps(appUserId: string, payments: UserInvoicePayment[], txId?: string) { + async ListCompletedTxSwaps(appUserId: string, payments: UserInvoicePayment[], txId?: string) { const completed = await this.dbs.Find('TransactionSwap', { where: { used: true, app_user_id: appUserId } }, txId) // const payments = await this.dbs.Find('UserInvoicePayment', { where: { swap_operation_id: Not(IsNull()), } }, txId) const paymentsMap = new Map() @@ -515,6 +516,15 @@ export default class { swap: c, payment: paymentsMap.get(c.swap_operation_id) })) } + + async AddInvoiceSwap(swap: Partial) { + return this.dbs.CreateAndSave('InvoiceSwap', swap) + } + + async GetInvoiceSwap(swapOperationId: string, appUserId: string, txId?: string) { + return this.dbs.FindOne('InvoiceSwap', { where: { swap_operation_id: swapOperationId, used: false, app_user_id: appUserId } }, txId) + } + } const orFail = async (resultPromise: Promise) => { From 03792f311117bd160bd9592b981e62b67373d7be Mon Sep 17 00:00:00 2001 From: "Sergey B." Date: Fri, 23 Jan 2026 15:30:52 +0300 Subject: [PATCH 02/66] fix: removing user ID from logs --- src/services/main/appUserManager.ts | 4 ++-- src/services/storage/userStorage.ts | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/services/main/appUserManager.ts b/src/services/main/appUserManager.ts index 9db8b5e6..168258f1 100644 --- a/src/services/main/appUserManager.ts +++ b/src/services/main/appUserManager.ts @@ -66,7 +66,7 @@ export default class { const appUser = await this.storage.applicationStorage.GetAppUserFromUser(app, user.user_id) if (!appUser) { - throw new Error(`app user ${ctx.user_id} not found`) // TODO: fix logs doxing + throw new Error("app user not found") } const nostrSettings = this.settings.getSettings().nostrRelaySettings const { max, serviceFeeFloor, serviceFeeBps } = this.applicationManager.paymentManager.GetMaxPayableInvoice(user.balance_sats) @@ -183,4 +183,4 @@ export default class { } this.log("Cleaned up inactive users") } -} \ No newline at end of file +} diff --git a/src/services/storage/userStorage.ts b/src/services/storage/userStorage.ts index 58dd6cf5..d3453346 100644 --- a/src/services/storage/userStorage.ts +++ b/src/services/storage/userStorage.ts @@ -42,7 +42,7 @@ export default class { async GetUser(userId: string, txId?: string): Promise { const user = await this.FindUser(userId, txId) if (!user) { - throw new Error(`user ${userId} not found`) // TODO: fix logs doxing + throw new Error(`user not found`) } return user } @@ -50,7 +50,7 @@ export default class { async UnbanUser(userId: string, txId?: string) { const affected = await this.dbs.Update('User', { user_id: userId }, { locked: false }, txId) if (!affected) { - throw new Error("unaffected user unlock for " + userId) // TODO: fix logs doxing + throw new Error("unaffected user unlock") } } @@ -58,7 +58,7 @@ export default class { const user = await this.GetUser(userId, txId) const affected = await this.dbs.Update('User', { user_id: userId }, { balance_sats: 0, locked: true }, txId) if (!affected) { - throw new Error("unaffected ban user for " + userId) // TODO: fix logs doxing + throw new Error("unaffected ban user") } if (user.balance_sats > 0) { this.eventsLog.LogEvent({ type: 'balance_decrement', userId, appId: "", appUserId: "", balance: user.balance_sats, data: 'ban', amount: user.balance_sats }) @@ -80,7 +80,7 @@ export default class { const affected = await this.dbs.Increment('User', { user_id: userId }, "balance_sats", increment, txId) if (!affected) { getLogger({ userId: userId, component: "balanceUpdates" })("user unaffected by increment") - throw new Error("unaffected balance increment for " + userId) // TODO: fix logs doxing + throw new Error("unaffected balance increment") } getLogger({ userId: userId, component: "balanceUpdates" })("incremented balance from", user.balance_sats, "sats, by", increment, "sats") this.eventsLog.LogEvent({ type: 'balance_increment', userId, appId: "", appUserId: "", balance: user.balance_sats, data: reason, amount: increment }) @@ -105,7 +105,7 @@ export default class { const affected = await this.dbs.Decrement('User', { user_id: userId }, "balance_sats", decrement, txId) if (!affected) { getLogger({ userId: userId, component: "balanceUpdates" })("user unaffected by decrement") - throw new Error("unaffected balance decrement for " + userId) // TODO: fix logs doxing + throw new Error("unaffected balance decrement") } getLogger({ userId: userId, component: "balanceUpdates" })("decremented balance from", user.balance_sats, "sats, by", decrement, "sats") this.eventsLog.LogEvent({ type: 'balance_decrement', userId, appId: "", appUserId: "", balance: user.balance_sats, data: reason, amount: decrement }) @@ -126,4 +126,4 @@ export default class { const lastSeenAtUnix = now - seconds return this.dbs.Find('UserAccess', { where: { last_seen_at_unix: LessThan(lastSeenAtUnix) } }) } -} \ No newline at end of file +} From d120ad7f998b2d7f6e27ca5c00608b18e9447823 Mon Sep 17 00:00:00 2001 From: boufni95 Date: Tue, 27 Jan 2026 16:08:52 +0000 Subject: [PATCH 03/66] admin swaps --- datasource.js | 8 +- proto/autogenerated/client.md | 120 ++++-- proto/autogenerated/go/http_client.go | 111 ++++- proto/autogenerated/go/types.go | 58 ++- proto/autogenerated/ts/express_server.ts | 93 +++- proto/autogenerated/ts/http_client.ts | 60 ++- proto/autogenerated/ts/nostr_client.ts | 60 ++- proto/autogenerated/ts/nostr_transport.ts | 65 ++- proto/autogenerated/ts/types.ts | 404 ++++++++++++++---- proto/service/methods.proto | 33 +- proto/service/structs.proto | 51 ++- src/services/lnd/swaps/submarineSwaps.ts | 71 ++- src/services/lnd/swaps/swaps.ts | 177 +++++++- src/services/main/adminManager.ts | 27 +- src/services/main/index.ts | 1 + src/services/main/init.ts | 1 + src/services/main/paymentManager.ts | 4 +- src/services/serverMethods/index.ts | 28 +- src/services/storage/entity/InvoiceSwap.ts | 23 +- .../migrations/1769529793283-invoice_swaps.ts | 30 ++ src/services/storage/migrations/runner.ts | 3 +- src/services/storage/paymentStorage.ts | 56 ++- 22 files changed, 1258 insertions(+), 226 deletions(-) create mode 100644 src/services/storage/migrations/1769529793283-invoice_swaps.ts diff --git a/datasource.js b/datasource.js index dfae53bf..ae243ada 100644 --- a/datasource.js +++ b/datasource.js @@ -22,6 +22,7 @@ import { AppUserDevice } from "./build/src/services/storage/entity/AppUserDevice import { UserAccess } from "./build/src/services/storage/entity/UserAccess.js" import { AdminSettings } from "./build/src/services/storage/entity/AdminSettings.js" import { TransactionSwap } from "./build/src/services/storage/entity/TransactionSwap.js" +import { InvoiceSwap } from "./build/src/services/storage/entity/InvoiceSwap.js" import { Initial1703170309875 } from './build/src/services/storage/migrations/1703170309875-initial.js' import { LspOrder1718387847693 } from './build/src/services/storage/migrations/1718387847693-lsp_order.js' @@ -47,6 +48,7 @@ import { TxSwap1762890527098 } from './build/src/services/storage/migrations/176 import { TxSwapAddress1764779178945 } from './build/src/services/storage/migrations/1764779178945-tx_swap_address.js' import { ClinkRequester1765497600000 } from './build/src/services/storage/migrations/1765497600000-clink_requester.js' import { TrackedProviderHeight1766504040000 } from './build/src/services/storage/migrations/1766504040000-tracked_provider_height.js' +import { SwapsServiceUrl1768413055036 } from './build/src/services/storage/migrations/1768413055036-swaps_service_url.js' export default new DataSource({ type: "better-sqlite3", @@ -56,11 +58,11 @@ export default new DataSource({ PaymentIndex1721760297610, DebitAccess1726496225078, DebitAccessFixes1726685229264, DebitToPub1727105758354, UserCbUrl1727112281043, UserOffer1733502626042, ManagementGrant1751307732346, InvoiceCallbackUrls1752425992291, OldSomethingLeftover1753106599604, UserReceivingInvoiceIdx1753109184611, AppUserDevice1753285173175, UserAccess1759426050669, AddBlindToUserOffer1760000000000, ApplicationAvatarUrl1761000001000, AdminSettings1761683639419, TxSwap1762890527098, - TxSwapAddress1764779178945, ClinkRequester1765497600000, TrackedProviderHeight1766504040000], + TxSwapAddress1764779178945, ClinkRequester1765497600000, TrackedProviderHeight1766504040000, SwapsServiceUrl1768413055036], entities: [User, UserReceivingInvoice, UserReceivingAddress, AddressReceivingTransaction, UserInvoicePayment, UserTransactionPayment, UserBasicAuth, UserEphemeralKey, Product, UserToUserPayment, Application, ApplicationUser, UserToUserPayment, LspOrder, LndNodeInfo, - TrackedProvider, InviteToken, DebitAccess, UserOffer, ManagementGrant, AppUserDevice, UserAccess, AdminSettings, TransactionSwap], + TrackedProvider, InviteToken, DebitAccess, UserOffer, ManagementGrant, AppUserDevice, UserAccess, AdminSettings, TransactionSwap, InvoiceSwap], // synchronize: true, }) -//npx typeorm migration:generate ./src/services/storage/migrations/swaps_service_url -d ./datasource.js \ No newline at end of file +//npx typeorm migration:generate ./src/services/storage/migrations/invoice_swaps -d ./datasource.js \ No newline at end of file diff --git a/proto/autogenerated/client.md b/proto/autogenerated/client.md index 99023c69..774ed9cd 100644 --- a/proto/autogenerated/client.md +++ b/proto/autogenerated/client.md @@ -93,6 +93,11 @@ The nostr server will send back a message response, and inside the body there wi - input: [MessagingToken](#MessagingToken) - This methods has an __empty__ __response__ body +- GetAdminInvoiceSwapQuotes + - auth type: __Admin__ + - input: [InvoiceSwapRequest](#InvoiceSwapRequest) + - output: [InvoiceSwapQuoteList](#InvoiceSwapQuoteList) + - GetAdminTransactionSwapQuotes - auth type: __Admin__ - input: [TransactionSwapRequest](#TransactionSwapRequest) @@ -243,20 +248,25 @@ The nostr server will send back a message response, and inside the body there wi - input: [LinkNPubThroughTokenRequest](#LinkNPubThroughTokenRequest) - This methods has an __empty__ __response__ body -- ListAdminSwaps +- ListAdminInvoiceSwaps - auth type: __Admin__ - This methods has an __empty__ __request__ body - - output: [SwapsList](#SwapsList) + - output: [InvoiceSwapsList](#InvoiceSwapsList) + +- ListAdminTxSwaps + - auth type: __Admin__ + - This methods has an __empty__ __request__ body + - output: [TxSwapsList](#TxSwapsList) - ListChannels - auth type: __Admin__ - This methods has an __empty__ __request__ body - output: [LndChannels](#LndChannels) -- ListSwaps +- ListTxSwaps - auth type: __User__ - This methods has an __empty__ __request__ body - - output: [SwapsList](#SwapsList) + - output: [TxSwapsList](#TxSwapsList) - LndGetInfo - auth type: __Admin__ @@ -290,10 +300,15 @@ The nostr server will send back a message response, and inside the body there wi - input: [PayAddressRequest](#PayAddressRequest) - output: [PayAddressResponse](#PayAddressResponse) +- PayAdminInvoiceSwap + - auth type: __Admin__ + - input: [PayAdminInvoiceSwapRequest](#PayAdminInvoiceSwapRequest) + - output: [AdminInvoiceSwapResponse](#AdminInvoiceSwapResponse) + - PayAdminTransactionSwap - auth type: __Admin__ - input: [PayAdminTransactionSwapRequest](#PayAdminTransactionSwapRequest) - - output: [AdminSwapResponse](#AdminSwapResponse) + - output: [AdminTxSwapResponse](#AdminTxSwapResponse) - PayInvoice - auth type: __User__ @@ -540,6 +555,13 @@ The nostr server will send back a message response, and inside the body there wi - input: [MessagingToken](#MessagingToken) - This methods has an __empty__ __response__ body +- GetAdminInvoiceSwapQuotes + - auth type: __Admin__ + - http method: __post__ + - http route: __/api/admin/swap/invoice/quote__ + - input: [InvoiceSwapRequest](#InvoiceSwapRequest) + - output: [InvoiceSwapQuoteList](#InvoiceSwapQuoteList) + - GetAdminTransactionSwapQuotes - auth type: __Admin__ - http method: __post__ @@ -743,7 +765,7 @@ The nostr server will send back a message response, and inside the body there wi - GetTransactionSwapQuotes - auth type: __User__ - http method: __post__ - - http route: __/api/user/swap/quote__ + - http route: __/api/user/swap/transaction/quote__ - input: [TransactionSwapRequest](#TransactionSwapRequest) - output: [TransactionSwapQuoteList](#TransactionSwapQuoteList) @@ -834,12 +856,19 @@ The nostr server will send back a message response, and inside the body there wi - input: [LinkNPubThroughTokenRequest](#LinkNPubThroughTokenRequest) - This methods has an __empty__ __response__ body -- ListAdminSwaps +- ListAdminInvoiceSwaps - auth type: __Admin__ - http method: __post__ - - http route: __/api/admin/swap/list__ + - http route: __/api/admin/swap/invoice/list__ - This methods has an __empty__ __request__ body - - output: [SwapsList](#SwapsList) + - output: [InvoiceSwapsList](#InvoiceSwapsList) + +- ListAdminTxSwaps + - auth type: __Admin__ + - http method: __post__ + - http route: __/api/admin/swap/transaction/list__ + - This methods has an __empty__ __request__ body + - output: [TxSwapsList](#TxSwapsList) - ListChannels - auth type: __Admin__ @@ -848,12 +877,12 @@ The nostr server will send back a message response, and inside the body there wi - This methods has an __empty__ __request__ body - output: [LndChannels](#LndChannels) -- ListSwaps +- ListTxSwaps - auth type: __User__ - http method: __post__ - - http route: __/api/user/swap/list__ + - http route: __/api/user/swap/transaction/list__ - This methods has an __empty__ __request__ body - - output: [SwapsList](#SwapsList) + - output: [TxSwapsList](#TxSwapsList) - LndGetInfo - auth type: __Admin__ @@ -899,12 +928,19 @@ The nostr server will send back a message response, and inside the body there wi - input: [PayAddressRequest](#PayAddressRequest) - output: [PayAddressResponse](#PayAddressResponse) +- PayAdminInvoiceSwap + - auth type: __Admin__ + - http method: __post__ + - http route: __/api/admin/swap/invoice/pay__ + - input: [PayAdminInvoiceSwapRequest](#PayAdminInvoiceSwapRequest) + - output: [AdminInvoiceSwapResponse](#AdminInvoiceSwapResponse) + - PayAdminTransactionSwap - auth type: __Admin__ - http method: __post__ - http route: __/api/admin/swap/transaction/pay__ - input: [PayAdminTransactionSwapRequest](#PayAdminTransactionSwapRequest) - - output: [AdminSwapResponse](#AdminSwapResponse) + - output: [AdminTxSwapResponse](#AdminTxSwapResponse) - PayAppUserInvoice - auth type: __App__ @@ -1098,7 +1134,10 @@ The nostr server will send back a message response, and inside the body there wi - __name__: _string_ - __price_sats__: _number_ -### AdminSwapResponse +### AdminInvoiceSwapResponse + - __tx_id__: _string_ + +### AdminTxSwapResponse - __network_fee__: _number_ - __tx_id__: _string_ @@ -1331,6 +1370,35 @@ The nostr server will send back a message response, and inside the body there wi - __token__: _string_ - __url__: _string_ +### InvoiceSwapOperation + - __failure_reason__: _string_ *this field is optional + - __invoice_paid__: _string_ + - __operation_payment__: _[UserOperation](#UserOperation)_ *this field is optional + - __swap_operation_id__: _string_ + - __tx_id__: _string_ + +### InvoiceSwapQuote + - __address__: _string_ + - __chain_fee_sats__: _number_ + - __invoice__: _string_ + - __invoice_amount_sats__: _number_ + - __service_fee_sats__: _number_ + - __service_url__: _string_ + - __swap_fee_sats__: _number_ + - __swap_operation_id__: _string_ + - __transaction_amount_sats__: _number_ + - __tx_id__: _string_ + +### InvoiceSwapQuoteList + - __quotes__: ARRAY of: _[InvoiceSwapQuote](#InvoiceSwapQuote)_ + +### InvoiceSwapRequest + - __invoice__: _string_ + +### InvoiceSwapsList + - __quotes__: ARRAY of: _[InvoiceSwapQuote](#InvoiceSwapQuote)_ + - __swaps__: ARRAY of: _[InvoiceSwapOperation](#InvoiceSwapOperation)_ + ### LatestBundleMetricReq - __limit__: _number_ *this field is optional @@ -1534,6 +1602,10 @@ The nostr server will send back a message response, and inside the body there wi - __service_fee__: _number_ - __txId__: _string_ +### PayAdminInvoiceSwapRequest + - __sat_per_v_byte__: _number_ + - __swap_operation_id__: _string_ + ### PayAdminTransactionSwapRequest - __address__: _string_ - __swap_operation_id__: _string_ @@ -1640,16 +1712,6 @@ The nostr server will send back a message response, and inside the body there wi - __page__: _number_ - __request_id__: _number_ *this field is optional -### SwapOperation - - __address_paid__: _string_ - - __failure_reason__: _string_ *this field is optional - - __operation_payment__: _[UserOperation](#UserOperation)_ *this field is optional - - __swap_operation_id__: _string_ - -### SwapsList - - __quotes__: ARRAY of: _[TransactionSwapQuote](#TransactionSwapQuote)_ - - __swaps__: ARRAY of: _[SwapOperation](#SwapOperation)_ - ### TransactionSwapQuote - __chain_fee_sats__: _number_ - __invoice_amount_sats__: _number_ @@ -1665,6 +1727,16 @@ The nostr server will send back a message response, and inside the body there wi ### TransactionSwapRequest - __transaction_amount_sats__: _number_ +### TxSwapOperation + - __address_paid__: _string_ + - __failure_reason__: _string_ *this field is optional + - __operation_payment__: _[UserOperation](#UserOperation)_ *this field is optional + - __swap_operation_id__: _string_ + +### TxSwapsList + - __quotes__: ARRAY of: _[TransactionSwapQuote](#TransactionSwapQuote)_ + - __swaps__: ARRAY of: _[TxSwapOperation](#TxSwapOperation)_ + ### UpdateChannelPolicyRequest - __policy__: _[ChannelPolicy](#ChannelPolicy)_ - __update__: _[UpdateChannelPolicyRequest_update](#UpdateChannelPolicyRequest_update)_ diff --git a/proto/autogenerated/go/http_client.go b/proto/autogenerated/go/http_client.go index a2b0ecb0..a010fd82 100644 --- a/proto/autogenerated/go/http_client.go +++ b/proto/autogenerated/go/http_client.go @@ -74,6 +74,7 @@ type Client struct { EncryptionExchange func(req EncryptionExchangeRequest) error EnrollAdminToken func(req EnrollAdminTokenRequest) error EnrollMessagingToken func(req MessagingToken) error + GetAdminInvoiceSwapQuotes func(req InvoiceSwapRequest) (*InvoiceSwapQuoteList, error) GetAdminTransactionSwapQuotes func(req TransactionSwapRequest) (*TransactionSwapQuoteList, error) GetApp func() (*Application, error) GetAppUser func(req GetAppUserRequest) (*AppUser, error) @@ -114,16 +115,18 @@ type Client struct { HandleLnurlWithdraw func(query HandleLnurlWithdraw_Query) error Health func() error LinkNPubThroughToken func(req LinkNPubThroughTokenRequest) error - ListAdminSwaps func() (*SwapsList, error) + ListAdminInvoiceSwaps func() (*InvoiceSwapsList, error) + ListAdminTxSwaps func() (*TxSwapsList, error) ListChannels func() (*LndChannels, error) - ListSwaps func() (*SwapsList, error) + ListTxSwaps func() (*TxSwapsList, error) LndGetInfo func(req LndGetInfoRequest) (*LndGetInfoResponse, error) NewAddress func(req NewAddressRequest) (*NewAddressResponse, error) NewInvoice func(req NewInvoiceRequest) (*NewInvoiceResponse, error) NewProductInvoice func(query NewProductInvoice_Query) (*NewInvoiceResponse, error) OpenChannel func(req OpenChannelRequest) (*OpenChannelResponse, error) PayAddress func(req PayAddressRequest) (*PayAddressResponse, error) - PayAdminTransactionSwap func(req PayAdminTransactionSwapRequest) (*AdminSwapResponse, error) + PayAdminInvoiceSwap func(req PayAdminInvoiceSwapRequest) (*AdminInvoiceSwapResponse, error) + PayAdminTransactionSwap func(req PayAdminTransactionSwapRequest) (*AdminTxSwapResponse, error) PayAppUserInvoice func(req PayAppUserInvoiceRequest) (*PayInvoiceResponse, error) PayInvoice func(req PayInvoiceRequest) (*PayInvoiceResponse, error) PingSubProcesses func() error @@ -667,6 +670,35 @@ func NewClient(params ClientParams) *Client { } return nil }, + GetAdminInvoiceSwapQuotes: func(req InvoiceSwapRequest) (*InvoiceSwapQuoteList, error) { + auth, err := params.RetrieveAdminAuth() + if err != nil { + return nil, err + } + finalRoute := "/api/admin/swap/invoice/quote" + body, err := json.Marshal(req) + if err != nil { + return nil, err + } + resBody, err := doPostRequest(params.BaseURL+finalRoute, body, auth) + if err != nil { + return nil, err + } + result := ResultError{} + err = json.Unmarshal(resBody, &result) + if err != nil { + return nil, err + } + if result.Status == "ERROR" { + return nil, fmt.Errorf(result.Reason) + } + res := InvoiceSwapQuoteList{} + err = json.Unmarshal(resBody, &res) + if err != nil { + return nil, err + } + return &res, nil + }, GetAdminTransactionSwapQuotes: func(req TransactionSwapRequest) (*TransactionSwapQuoteList, error) { auth, err := params.RetrieveAdminAuth() if err != nil { @@ -1324,7 +1356,7 @@ func NewClient(params ClientParams) *Client { if err != nil { return nil, err } - finalRoute := "/api/user/swap/quote" + finalRoute := "/api/user/swap/transaction/quote" body, err := json.Marshal(req) if err != nil { return nil, err @@ -1643,12 +1675,12 @@ func NewClient(params ClientParams) *Client { } return nil }, - ListAdminSwaps: func() (*SwapsList, error) { + ListAdminInvoiceSwaps: func() (*InvoiceSwapsList, error) { auth, err := params.RetrieveAdminAuth() if err != nil { return nil, err } - finalRoute := "/api/admin/swap/list" + finalRoute := "/api/admin/swap/invoice/list" body := []byte{} resBody, err := doPostRequest(params.BaseURL+finalRoute, body, auth) if err != nil { @@ -1662,7 +1694,33 @@ func NewClient(params ClientParams) *Client { if result.Status == "ERROR" { return nil, fmt.Errorf(result.Reason) } - res := SwapsList{} + res := InvoiceSwapsList{} + err = json.Unmarshal(resBody, &res) + if err != nil { + return nil, err + } + return &res, nil + }, + ListAdminTxSwaps: func() (*TxSwapsList, error) { + auth, err := params.RetrieveAdminAuth() + if err != nil { + return nil, err + } + finalRoute := "/api/admin/swap/transaction/list" + body := []byte{} + resBody, err := doPostRequest(params.BaseURL+finalRoute, body, auth) + if err != nil { + return nil, err + } + result := ResultError{} + err = json.Unmarshal(resBody, &result) + if err != nil { + return nil, err + } + if result.Status == "ERROR" { + return nil, fmt.Errorf(result.Reason) + } + res := TxSwapsList{} err = json.Unmarshal(resBody, &res) if err != nil { return nil, err @@ -1691,12 +1749,12 @@ func NewClient(params ClientParams) *Client { } return &res, nil }, - ListSwaps: func() (*SwapsList, error) { + ListTxSwaps: func() (*TxSwapsList, error) { auth, err := params.RetrieveUserAuth() if err != nil { return nil, err } - finalRoute := "/api/user/swap/list" + finalRoute := "/api/user/swap/transaction/list" body := []byte{} resBody, err := doPostRequest(params.BaseURL+finalRoute, body, auth) if err != nil { @@ -1710,7 +1768,7 @@ func NewClient(params ClientParams) *Client { if result.Status == "ERROR" { return nil, fmt.Errorf(result.Reason) } - res := SwapsList{} + res := TxSwapsList{} err = json.Unmarshal(resBody, &res) if err != nil { return nil, err @@ -1892,7 +1950,36 @@ func NewClient(params ClientParams) *Client { } return &res, nil }, - PayAdminTransactionSwap: func(req PayAdminTransactionSwapRequest) (*AdminSwapResponse, error) { + PayAdminInvoiceSwap: func(req PayAdminInvoiceSwapRequest) (*AdminInvoiceSwapResponse, error) { + auth, err := params.RetrieveAdminAuth() + if err != nil { + return nil, err + } + finalRoute := "/api/admin/swap/invoice/pay" + body, err := json.Marshal(req) + if err != nil { + return nil, err + } + resBody, err := doPostRequest(params.BaseURL+finalRoute, body, auth) + if err != nil { + return nil, err + } + result := ResultError{} + err = json.Unmarshal(resBody, &result) + if err != nil { + return nil, err + } + if result.Status == "ERROR" { + return nil, fmt.Errorf(result.Reason) + } + res := AdminInvoiceSwapResponse{} + err = json.Unmarshal(resBody, &res) + if err != nil { + return nil, err + } + return &res, nil + }, + PayAdminTransactionSwap: func(req PayAdminTransactionSwapRequest) (*AdminTxSwapResponse, error) { auth, err := params.RetrieveAdminAuth() if err != nil { return nil, err @@ -1914,7 +2001,7 @@ func NewClient(params ClientParams) *Client { if result.Status == "ERROR" { return nil, fmt.Errorf(result.Reason) } - res := AdminSwapResponse{} + res := AdminTxSwapResponse{} err = json.Unmarshal(resBody, &res) if err != nil { return nil, err diff --git a/proto/autogenerated/go/types.go b/proto/autogenerated/go/types.go index 841ced1d..f1d45300 100644 --- a/proto/autogenerated/go/types.go +++ b/proto/autogenerated/go/types.go @@ -123,7 +123,10 @@ type AddProductRequest struct { Name string `json:"name"` Price_sats int64 `json:"price_sats"` } -type AdminSwapResponse struct { +type AdminInvoiceSwapResponse struct { + Tx_id string `json:"tx_id"` +} +type AdminTxSwapResponse struct { Network_fee int64 `json:"network_fee"` Tx_id string `json:"tx_id"` } @@ -356,6 +359,35 @@ type HttpCreds struct { Token string `json:"token"` Url string `json:"url"` } +type InvoiceSwapOperation struct { + Failure_reason string `json:"failure_reason"` + Invoice_paid string `json:"invoice_paid"` + Operation_payment *UserOperation `json:"operation_payment"` + Swap_operation_id string `json:"swap_operation_id"` + Tx_id string `json:"tx_id"` +} +type InvoiceSwapQuote struct { + Address string `json:"address"` + Chain_fee_sats int64 `json:"chain_fee_sats"` + Invoice string `json:"invoice"` + Invoice_amount_sats int64 `json:"invoice_amount_sats"` + Service_fee_sats int64 `json:"service_fee_sats"` + Service_url string `json:"service_url"` + Swap_fee_sats int64 `json:"swap_fee_sats"` + Swap_operation_id string `json:"swap_operation_id"` + Transaction_amount_sats int64 `json:"transaction_amount_sats"` + Tx_id string `json:"tx_id"` +} +type InvoiceSwapQuoteList struct { + Quotes []InvoiceSwapQuote `json:"quotes"` +} +type InvoiceSwapRequest struct { + Invoice string `json:"invoice"` +} +type InvoiceSwapsList struct { + Quotes []InvoiceSwapQuote `json:"quotes"` + Swaps []InvoiceSwapOperation `json:"swaps"` +} type LatestBundleMetricReq struct { Limit int64 `json:"limit"` } @@ -559,6 +591,10 @@ type PayAddressResponse struct { Service_fee int64 `json:"service_fee"` Txid string `json:"txId"` } +type PayAdminInvoiceSwapRequest struct { + Sat_per_v_byte int64 `json:"sat_per_v_byte"` + Swap_operation_id string `json:"swap_operation_id"` +} type PayAdminTransactionSwapRequest struct { Address string `json:"address"` Swap_operation_id string `json:"swap_operation_id"` @@ -665,16 +701,6 @@ type SingleMetricReq struct { Page int64 `json:"page"` Request_id int64 `json:"request_id"` } -type SwapOperation struct { - Address_paid string `json:"address_paid"` - Failure_reason string `json:"failure_reason"` - Operation_payment *UserOperation `json:"operation_payment"` - Swap_operation_id string `json:"swap_operation_id"` -} -type SwapsList struct { - Quotes []TransactionSwapQuote `json:"quotes"` - Swaps []SwapOperation `json:"swaps"` -} type TransactionSwapQuote struct { Chain_fee_sats int64 `json:"chain_fee_sats"` Invoice_amount_sats int64 `json:"invoice_amount_sats"` @@ -690,6 +716,16 @@ type TransactionSwapQuoteList struct { type TransactionSwapRequest struct { Transaction_amount_sats int64 `json:"transaction_amount_sats"` } +type TxSwapOperation struct { + Address_paid string `json:"address_paid"` + Failure_reason string `json:"failure_reason"` + Operation_payment *UserOperation `json:"operation_payment"` + Swap_operation_id string `json:"swap_operation_id"` +} +type TxSwapsList struct { + Quotes []TransactionSwapQuote `json:"quotes"` + Swaps []TxSwapOperation `json:"swaps"` +} type UpdateChannelPolicyRequest struct { Policy *ChannelPolicy `json:"policy"` Update *UpdateChannelPolicyRequest_update `json:"update"` diff --git a/proto/autogenerated/ts/express_server.ts b/proto/autogenerated/ts/express_server.ts index c1740acd..8ce0aa96 100644 --- a/proto/autogenerated/ts/express_server.ts +++ b/proto/autogenerated/ts/express_server.ts @@ -545,12 +545,12 @@ export default (methods: Types.ServerMethods, opts: ServerOptions) => { callsMetrics.push({ ...opInfo, ...opStats, ...ctx }) } break - case 'ListSwaps': - if (!methods.ListSwaps) { - throw new Error('method ListSwaps not found' ) + case 'ListTxSwaps': + if (!methods.ListTxSwaps) { + throw new Error('method ListTxSwaps not found' ) } else { opStats.validate = opStats.guard - const res = await methods.ListSwaps({...operation, ctx}); responses.push({ status: 'OK', ...res }) + const res = await methods.ListTxSwaps({...operation, ctx}); responses.push({ status: 'OK', ...res }) opStats.handle = process.hrtime.bigint() callsMetrics.push({ ...opInfo, ...opStats, ...ctx }) } @@ -869,6 +869,28 @@ export default (methods: Types.ServerMethods, opts: ServerOptions) => { opts.metricsCallback([{ ...info, ...stats, ...authContext }]) } catch (ex) { const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback); if (opts.throwErrors) throw e } }) + if (!opts.allowNotImplementedMethods && !methods.GetAdminInvoiceSwapQuotes) throw new Error('method: GetAdminInvoiceSwapQuotes is not implemented') + app.post('/api/admin/swap/invoice/quote', async (req, res) => { + const info: Types.RequestInfo = { rpcName: 'GetAdminInvoiceSwapQuotes', batch: false, nostr: false, batchSize: 0} + const stats: Types.RequestStats = { startMs:req.startTimeMs || 0, start:req.startTime || 0n, parse: process.hrtime.bigint(), guard: 0n, validate: 0n, handle: 0n } + let authCtx: Types.AuthContext = {} + try { + if (!methods.GetAdminInvoiceSwapQuotes) throw new Error('method: GetAdminInvoiceSwapQuotes is not implemented') + const authContext = await opts.AdminAuthGuard(req.headers['authorization']) + authCtx = authContext + stats.guard = process.hrtime.bigint() + const request = req.body + const error = Types.InvoiceSwapRequestValidate(request) + stats.validate = process.hrtime.bigint() + if (error !== null) return logErrorAndReturnResponse(error, 'invalid request body', res, logger, { ...info, ...stats, ...authContext }, opts.metricsCallback) + const query = req.query + const params = req.params + const response = await methods.GetAdminInvoiceSwapQuotes({rpcName:'GetAdminInvoiceSwapQuotes', ctx:authContext , req: request}) + stats.handle = process.hrtime.bigint() + res.json({status: 'OK', ...response}) + opts.metricsCallback([{ ...info, ...stats, ...authContext }]) + } catch (ex) { const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback); if (opts.throwErrors) throw e } + }) if (!opts.allowNotImplementedMethods && !methods.GetAdminTransactionSwapQuotes) throw new Error('method: GetAdminTransactionSwapQuotes is not implemented') app.post('/api/admin/swap/transaction/quote', async (req, res) => { const info: Types.RequestInfo = { rpcName: 'GetAdminTransactionSwapQuotes', batch: false, nostr: false, batchSize: 0} @@ -1362,7 +1384,7 @@ export default (methods: Types.ServerMethods, opts: ServerOptions) => { } catch (ex) { const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback); if (opts.throwErrors) throw e } }) if (!opts.allowNotImplementedMethods && !methods.GetTransactionSwapQuotes) throw new Error('method: GetTransactionSwapQuotes is not implemented') - app.post('/api/user/swap/quote', async (req, res) => { + app.post('/api/user/swap/transaction/quote', async (req, res) => { const info: Types.RequestInfo = { rpcName: 'GetTransactionSwapQuotes', batch: false, nostr: false, batchSize: 0} const stats: Types.RequestStats = { startMs:req.startTimeMs || 0, start:req.startTime || 0n, parse: process.hrtime.bigint(), guard: 0n, validate: 0n, handle: 0n } let authCtx: Types.AuthContext = {} @@ -1607,20 +1629,39 @@ export default (methods: Types.ServerMethods, opts: ServerOptions) => { opts.metricsCallback([{ ...info, ...stats, ...authContext }]) } catch (ex) { const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback); if (opts.throwErrors) throw e } }) - if (!opts.allowNotImplementedMethods && !methods.ListAdminSwaps) throw new Error('method: ListAdminSwaps is not implemented') - app.post('/api/admin/swap/list', async (req, res) => { - const info: Types.RequestInfo = { rpcName: 'ListAdminSwaps', batch: false, nostr: false, batchSize: 0} + if (!opts.allowNotImplementedMethods && !methods.ListAdminInvoiceSwaps) throw new Error('method: ListAdminInvoiceSwaps is not implemented') + app.post('/api/admin/swap/invoice/list', async (req, res) => { + const info: Types.RequestInfo = { rpcName: 'ListAdminInvoiceSwaps', batch: false, nostr: false, batchSize: 0} const stats: Types.RequestStats = { startMs:req.startTimeMs || 0, start:req.startTime || 0n, parse: process.hrtime.bigint(), guard: 0n, validate: 0n, handle: 0n } let authCtx: Types.AuthContext = {} try { - if (!methods.ListAdminSwaps) throw new Error('method: ListAdminSwaps is not implemented') + if (!methods.ListAdminInvoiceSwaps) throw new Error('method: ListAdminInvoiceSwaps is not implemented') const authContext = await opts.AdminAuthGuard(req.headers['authorization']) authCtx = authContext stats.guard = process.hrtime.bigint() stats.validate = stats.guard const query = req.query const params = req.params - const response = await methods.ListAdminSwaps({rpcName:'ListAdminSwaps', ctx:authContext }) + const response = await methods.ListAdminInvoiceSwaps({rpcName:'ListAdminInvoiceSwaps', ctx:authContext }) + stats.handle = process.hrtime.bigint() + res.json({status: 'OK', ...response}) + opts.metricsCallback([{ ...info, ...stats, ...authContext }]) + } catch (ex) { const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback); if (opts.throwErrors) throw e } + }) + if (!opts.allowNotImplementedMethods && !methods.ListAdminTxSwaps) throw new Error('method: ListAdminTxSwaps is not implemented') + app.post('/api/admin/swap/transaction/list', async (req, res) => { + const info: Types.RequestInfo = { rpcName: 'ListAdminTxSwaps', batch: false, nostr: false, batchSize: 0} + const stats: Types.RequestStats = { startMs:req.startTimeMs || 0, start:req.startTime || 0n, parse: process.hrtime.bigint(), guard: 0n, validate: 0n, handle: 0n } + let authCtx: Types.AuthContext = {} + try { + if (!methods.ListAdminTxSwaps) throw new Error('method: ListAdminTxSwaps is not implemented') + const authContext = await opts.AdminAuthGuard(req.headers['authorization']) + authCtx = authContext + stats.guard = process.hrtime.bigint() + stats.validate = stats.guard + const query = req.query + const params = req.params + const response = await methods.ListAdminTxSwaps({rpcName:'ListAdminTxSwaps', ctx:authContext }) stats.handle = process.hrtime.bigint() res.json({status: 'OK', ...response}) opts.metricsCallback([{ ...info, ...stats, ...authContext }]) @@ -1645,20 +1686,20 @@ export default (methods: Types.ServerMethods, opts: ServerOptions) => { opts.metricsCallback([{ ...info, ...stats, ...authContext }]) } catch (ex) { const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback); if (opts.throwErrors) throw e } }) - if (!opts.allowNotImplementedMethods && !methods.ListSwaps) throw new Error('method: ListSwaps is not implemented') - app.post('/api/user/swap/list', async (req, res) => { - const info: Types.RequestInfo = { rpcName: 'ListSwaps', batch: false, nostr: false, batchSize: 0} + if (!opts.allowNotImplementedMethods && !methods.ListTxSwaps) throw new Error('method: ListTxSwaps is not implemented') + app.post('/api/user/swap/transaction/list', async (req, res) => { + const info: Types.RequestInfo = { rpcName: 'ListTxSwaps', batch: false, nostr: false, batchSize: 0} const stats: Types.RequestStats = { startMs:req.startTimeMs || 0, start:req.startTime || 0n, parse: process.hrtime.bigint(), guard: 0n, validate: 0n, handle: 0n } let authCtx: Types.AuthContext = {} try { - if (!methods.ListSwaps) throw new Error('method: ListSwaps is not implemented') + if (!methods.ListTxSwaps) throw new Error('method: ListTxSwaps is not implemented') const authContext = await opts.UserAuthGuard(req.headers['authorization']) authCtx = authContext stats.guard = process.hrtime.bigint() stats.validate = stats.guard const query = req.query const params = req.params - const response = await methods.ListSwaps({rpcName:'ListSwaps', ctx:authContext }) + const response = await methods.ListTxSwaps({rpcName:'ListTxSwaps', ctx:authContext }) stats.handle = process.hrtime.bigint() res.json({status: 'OK', ...response}) opts.metricsCallback([{ ...info, ...stats, ...authContext }]) @@ -1793,6 +1834,28 @@ export default (methods: Types.ServerMethods, opts: ServerOptions) => { opts.metricsCallback([{ ...info, ...stats, ...authContext }]) } catch (ex) { const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback); if (opts.throwErrors) throw e } }) + if (!opts.allowNotImplementedMethods && !methods.PayAdminInvoiceSwap) throw new Error('method: PayAdminInvoiceSwap is not implemented') + app.post('/api/admin/swap/invoice/pay', async (req, res) => { + const info: Types.RequestInfo = { rpcName: 'PayAdminInvoiceSwap', batch: false, nostr: false, batchSize: 0} + const stats: Types.RequestStats = { startMs:req.startTimeMs || 0, start:req.startTime || 0n, parse: process.hrtime.bigint(), guard: 0n, validate: 0n, handle: 0n } + let authCtx: Types.AuthContext = {} + try { + if (!methods.PayAdminInvoiceSwap) throw new Error('method: PayAdminInvoiceSwap is not implemented') + const authContext = await opts.AdminAuthGuard(req.headers['authorization']) + authCtx = authContext + stats.guard = process.hrtime.bigint() + const request = req.body + const error = Types.PayAdminInvoiceSwapRequestValidate(request) + stats.validate = process.hrtime.bigint() + if (error !== null) return logErrorAndReturnResponse(error, 'invalid request body', res, logger, { ...info, ...stats, ...authContext }, opts.metricsCallback) + const query = req.query + const params = req.params + const response = await methods.PayAdminInvoiceSwap({rpcName:'PayAdminInvoiceSwap', ctx:authContext , req: request}) + stats.handle = process.hrtime.bigint() + res.json({status: 'OK', ...response}) + opts.metricsCallback([{ ...info, ...stats, ...authContext }]) + } catch (ex) { const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback); if (opts.throwErrors) throw e } + }) if (!opts.allowNotImplementedMethods && !methods.PayAdminTransactionSwap) throw new Error('method: PayAdminTransactionSwap is not implemented') app.post('/api/admin/swap/transaction/pay', async (req, res) => { const info: Types.RequestInfo = { rpcName: 'PayAdminTransactionSwap', batch: false, nostr: false, batchSize: 0} diff --git a/proto/autogenerated/ts/http_client.ts b/proto/autogenerated/ts/http_client.ts index a24ff3e6..e84470eb 100644 --- a/proto/autogenerated/ts/http_client.ts +++ b/proto/autogenerated/ts/http_client.ts @@ -273,6 +273,20 @@ export default (params: ClientParams) => ({ } return { status: 'ERROR', reason: 'invalid response' } }, + GetAdminInvoiceSwapQuotes: async (request: Types.InvoiceSwapRequest): Promise => { + const auth = await params.retrieveAdminAuth() + if (auth === null) throw new Error('retrieveAdminAuth() returned null') + let finalRoute = '/api/admin/swap/invoice/quote' + const { data } = await axios.post(params.baseUrl + finalRoute, request, { headers: { 'authorization': auth } }) + if (data.status === 'ERROR' && typeof data.reason === 'string') return data + if (data.status === 'OK') { + const result = data + if(!params.checkResult) return { status: 'OK', ...result } + const error = Types.InvoiceSwapQuoteListValidate(result) + if (error === null) { return { status: 'OK', ...result } } else return { status: 'ERROR', reason: error.message } + } + return { status: 'ERROR', reason: 'invalid response' } + }, GetAdminTransactionSwapQuotes: async (request: Types.TransactionSwapRequest): Promise => { const auth = await params.retrieveAdminAuth() if (auth === null) throw new Error('retrieveAdminAuth() returned null') @@ -620,7 +634,7 @@ export default (params: ClientParams) => ({ GetTransactionSwapQuotes: async (request: Types.TransactionSwapRequest): Promise => { const auth = await params.retrieveUserAuth() if (auth === null) throw new Error('retrieveUserAuth() returned null') - let finalRoute = '/api/user/swap/quote' + let finalRoute = '/api/user/swap/transaction/quote' const { data } = await axios.post(params.baseUrl + finalRoute, request, { headers: { 'authorization': auth } }) if (data.status === 'ERROR' && typeof data.reason === 'string') return data if (data.status === 'OK') { @@ -781,16 +795,30 @@ export default (params: ClientParams) => ({ } return { status: 'ERROR', reason: 'invalid response' } }, - ListAdminSwaps: async (): Promise => { + ListAdminInvoiceSwaps: async (): Promise => { const auth = await params.retrieveAdminAuth() if (auth === null) throw new Error('retrieveAdminAuth() returned null') - let finalRoute = '/api/admin/swap/list' + let finalRoute = '/api/admin/swap/invoice/list' const { data } = await axios.post(params.baseUrl + finalRoute, {}, { headers: { 'authorization': auth } }) if (data.status === 'ERROR' && typeof data.reason === 'string') return data if (data.status === 'OK') { const result = data if(!params.checkResult) return { status: 'OK', ...result } - const error = Types.SwapsListValidate(result) + const error = Types.InvoiceSwapsListValidate(result) + if (error === null) { return { status: 'OK', ...result } } else return { status: 'ERROR', reason: error.message } + } + return { status: 'ERROR', reason: 'invalid response' } + }, + ListAdminTxSwaps: async (): Promise => { + const auth = await params.retrieveAdminAuth() + if (auth === null) throw new Error('retrieveAdminAuth() returned null') + let finalRoute = '/api/admin/swap/transaction/list' + const { data } = await axios.post(params.baseUrl + finalRoute, {}, { headers: { 'authorization': auth } }) + if (data.status === 'ERROR' && typeof data.reason === 'string') return data + if (data.status === 'OK') { + const result = data + if(!params.checkResult) return { status: 'OK', ...result } + const error = Types.TxSwapsListValidate(result) if (error === null) { return { status: 'OK', ...result } } else return { status: 'ERROR', reason: error.message } } return { status: 'ERROR', reason: 'invalid response' } @@ -809,16 +837,16 @@ export default (params: ClientParams) => ({ } return { status: 'ERROR', reason: 'invalid response' } }, - ListSwaps: async (): Promise => { + ListTxSwaps: async (): Promise => { const auth = await params.retrieveUserAuth() if (auth === null) throw new Error('retrieveUserAuth() returned null') - let finalRoute = '/api/user/swap/list' + let finalRoute = '/api/user/swap/transaction/list' const { data } = await axios.post(params.baseUrl + finalRoute, {}, { headers: { 'authorization': auth } }) if (data.status === 'ERROR' && typeof data.reason === 'string') return data if (data.status === 'OK') { const result = data if(!params.checkResult) return { status: 'OK', ...result } - const error = Types.SwapsListValidate(result) + const error = Types.TxSwapsListValidate(result) if (error === null) { return { status: 'OK', ...result } } else return { status: 'ERROR', reason: error.message } } return { status: 'ERROR', reason: 'invalid response' } @@ -909,7 +937,21 @@ export default (params: ClientParams) => ({ } return { status: 'ERROR', reason: 'invalid response' } }, - PayAdminTransactionSwap: async (request: Types.PayAdminTransactionSwapRequest): Promise => { + PayAdminInvoiceSwap: async (request: Types.PayAdminInvoiceSwapRequest): Promise => { + const auth = await params.retrieveAdminAuth() + if (auth === null) throw new Error('retrieveAdminAuth() returned null') + let finalRoute = '/api/admin/swap/invoice/pay' + const { data } = await axios.post(params.baseUrl + finalRoute, request, { headers: { 'authorization': auth } }) + if (data.status === 'ERROR' && typeof data.reason === 'string') return data + if (data.status === 'OK') { + const result = data + if(!params.checkResult) return { status: 'OK', ...result } + const error = Types.AdminInvoiceSwapResponseValidate(result) + if (error === null) { return { status: 'OK', ...result } } else return { status: 'ERROR', reason: error.message } + } + return { status: 'ERROR', reason: 'invalid response' } + }, + PayAdminTransactionSwap: async (request: Types.PayAdminTransactionSwapRequest): Promise => { const auth = await params.retrieveAdminAuth() if (auth === null) throw new Error('retrieveAdminAuth() returned null') let finalRoute = '/api/admin/swap/transaction/pay' @@ -918,7 +960,7 @@ export default (params: ClientParams) => ({ if (data.status === 'OK') { const result = data if(!params.checkResult) return { status: 'OK', ...result } - const error = Types.AdminSwapResponseValidate(result) + const error = Types.AdminTxSwapResponseValidate(result) if (error === null) { return { status: 'OK', ...result } } else return { status: 'ERROR', reason: error.message } } return { status: 'ERROR', reason: 'invalid response' } diff --git a/proto/autogenerated/ts/nostr_client.ts b/proto/autogenerated/ts/nostr_client.ts index df969c7b..2db7e8ce 100644 --- a/proto/autogenerated/ts/nostr_client.ts +++ b/proto/autogenerated/ts/nostr_client.ts @@ -230,6 +230,21 @@ export default (params: NostrClientParams, send: (to:string, message: NostrRequ } return { status: 'ERROR', reason: 'invalid response' } }, + GetAdminInvoiceSwapQuotes: async (request: Types.InvoiceSwapRequest): Promise => { + const auth = await params.retrieveNostrAdminAuth() + if (auth === null) throw new Error('retrieveNostrAdminAuth() returned null') + const nostrRequest: NostrRequest = {} + nostrRequest.body = request + const data = await send(params.pubDestination, {rpcName:'GetAdminInvoiceSwapQuotes',authIdentifier:auth, ...nostrRequest }) + if (data.status === 'ERROR' && typeof data.reason === 'string') return data + if (data.status === 'OK') { + const result = data + if(!params.checkResult) return { status: 'OK', ...result } + const error = Types.InvoiceSwapQuoteListValidate(result) + if (error === null) { return { status: 'OK', ...result } } else return { status: 'ERROR', reason: error.message } + } + return { status: 'ERROR', reason: 'invalid response' } + }, GetAdminTransactionSwapQuotes: async (request: Types.TransactionSwapRequest): Promise => { const auth = await params.retrieveNostrAdminAuth() if (auth === null) throw new Error('retrieveNostrAdminAuth() returned null') @@ -666,16 +681,30 @@ export default (params: NostrClientParams, send: (to:string, message: NostrRequ } return { status: 'ERROR', reason: 'invalid response' } }, - ListAdminSwaps: async (): Promise => { + ListAdminInvoiceSwaps: async (): Promise => { const auth = await params.retrieveNostrAdminAuth() if (auth === null) throw new Error('retrieveNostrAdminAuth() returned null') const nostrRequest: NostrRequest = {} - const data = await send(params.pubDestination, {rpcName:'ListAdminSwaps',authIdentifier:auth, ...nostrRequest }) + const data = await send(params.pubDestination, {rpcName:'ListAdminInvoiceSwaps',authIdentifier:auth, ...nostrRequest }) if (data.status === 'ERROR' && typeof data.reason === 'string') return data if (data.status === 'OK') { const result = data if(!params.checkResult) return { status: 'OK', ...result } - const error = Types.SwapsListValidate(result) + const error = Types.InvoiceSwapsListValidate(result) + if (error === null) { return { status: 'OK', ...result } } else return { status: 'ERROR', reason: error.message } + } + return { status: 'ERROR', reason: 'invalid response' } + }, + ListAdminTxSwaps: async (): Promise => { + const auth = await params.retrieveNostrAdminAuth() + if (auth === null) throw new Error('retrieveNostrAdminAuth() returned null') + const nostrRequest: NostrRequest = {} + const data = await send(params.pubDestination, {rpcName:'ListAdminTxSwaps',authIdentifier:auth, ...nostrRequest }) + if (data.status === 'ERROR' && typeof data.reason === 'string') return data + if (data.status === 'OK') { + const result = data + if(!params.checkResult) return { status: 'OK', ...result } + const error = Types.TxSwapsListValidate(result) if (error === null) { return { status: 'OK', ...result } } else return { status: 'ERROR', reason: error.message } } return { status: 'ERROR', reason: 'invalid response' } @@ -694,16 +723,16 @@ export default (params: NostrClientParams, send: (to:string, message: NostrRequ } return { status: 'ERROR', reason: 'invalid response' } }, - ListSwaps: async (): Promise => { + ListTxSwaps: async (): Promise => { const auth = await params.retrieveNostrUserAuth() if (auth === null) throw new Error('retrieveNostrUserAuth() returned null') const nostrRequest: NostrRequest = {} - const data = await send(params.pubDestination, {rpcName:'ListSwaps',authIdentifier:auth, ...nostrRequest }) + const data = await send(params.pubDestination, {rpcName:'ListTxSwaps',authIdentifier:auth, ...nostrRequest }) if (data.status === 'ERROR' && typeof data.reason === 'string') return data if (data.status === 'OK') { const result = data if(!params.checkResult) return { status: 'OK', ...result } - const error = Types.SwapsListValidate(result) + const error = Types.TxSwapsListValidate(result) if (error === null) { return { status: 'OK', ...result } } else return { status: 'ERROR', reason: error.message } } return { status: 'ERROR', reason: 'invalid response' } @@ -798,7 +827,22 @@ export default (params: NostrClientParams, send: (to:string, message: NostrRequ } return { status: 'ERROR', reason: 'invalid response' } }, - PayAdminTransactionSwap: async (request: Types.PayAdminTransactionSwapRequest): Promise => { + PayAdminInvoiceSwap: async (request: Types.PayAdminInvoiceSwapRequest): Promise => { + const auth = await params.retrieveNostrAdminAuth() + if (auth === null) throw new Error('retrieveNostrAdminAuth() returned null') + const nostrRequest: NostrRequest = {} + nostrRequest.body = request + const data = await send(params.pubDestination, {rpcName:'PayAdminInvoiceSwap',authIdentifier:auth, ...nostrRequest }) + if (data.status === 'ERROR' && typeof data.reason === 'string') return data + if (data.status === 'OK') { + const result = data + if(!params.checkResult) return { status: 'OK', ...result } + const error = Types.AdminInvoiceSwapResponseValidate(result) + if (error === null) { return { status: 'OK', ...result } } else return { status: 'ERROR', reason: error.message } + } + return { status: 'ERROR', reason: 'invalid response' } + }, + PayAdminTransactionSwap: async (request: Types.PayAdminTransactionSwapRequest): Promise => { const auth = await params.retrieveNostrAdminAuth() if (auth === null) throw new Error('retrieveNostrAdminAuth() returned null') const nostrRequest: NostrRequest = {} @@ -808,7 +852,7 @@ export default (params: NostrClientParams, send: (to:string, message: NostrRequ if (data.status === 'OK') { const result = data if(!params.checkResult) return { status: 'OK', ...result } - const error = Types.AdminSwapResponseValidate(result) + const error = Types.AdminTxSwapResponseValidate(result) if (error === null) { return { status: 'OK', ...result } } else return { status: 'ERROR', reason: error.message } } return { status: 'ERROR', reason: 'invalid response' } diff --git a/proto/autogenerated/ts/nostr_transport.ts b/proto/autogenerated/ts/nostr_transport.ts index 24a96cd6..8a586d5b 100644 --- a/proto/autogenerated/ts/nostr_transport.ts +++ b/proto/autogenerated/ts/nostr_transport.ts @@ -427,12 +427,12 @@ export default (methods: Types.ServerMethods, opts: NostrOptions) => { callsMetrics.push({ ...opInfo, ...opStats, ...ctx }) } break - case 'ListSwaps': - if (!methods.ListSwaps) { - throw new Error('method not defined: ListSwaps') + case 'ListTxSwaps': + if (!methods.ListTxSwaps) { + throw new Error('method not defined: ListTxSwaps') } else { opStats.validate = opStats.guard - const res = await methods.ListSwaps({...operation, ctx}); responses.push({ status: 'OK', ...res }) + const res = await methods.ListTxSwaps({...operation, ctx}); responses.push({ status: 'OK', ...res }) opStats.handle = process.hrtime.bigint() callsMetrics.push({ ...opInfo, ...opStats, ...ctx }) } @@ -687,6 +687,22 @@ export default (methods: Types.ServerMethods, opts: NostrOptions) => { opts.metricsCallback([{ ...info, ...stats, ...authContext }]) }catch(ex){ const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback); if (opts.throwErrors) throw e } break + case 'GetAdminInvoiceSwapQuotes': + try { + if (!methods.GetAdminInvoiceSwapQuotes) throw new Error('method: GetAdminInvoiceSwapQuotes is not implemented') + const authContext = await opts.NostrAdminAuthGuard(req.appId, req.authIdentifier) + stats.guard = process.hrtime.bigint() + authCtx = authContext + const request = req.body + const error = Types.InvoiceSwapRequestValidate(request) + stats.validate = process.hrtime.bigint() + if (error !== null) return logErrorAndReturnResponse(error, 'invalid request body', res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback) + const response = await methods.GetAdminInvoiceSwapQuotes({rpcName:'GetAdminInvoiceSwapQuotes', ctx:authContext , req: request}) + stats.handle = process.hrtime.bigint() + res({status: 'OK', ...response}) + opts.metricsCallback([{ ...info, ...stats, ...authContext }]) + }catch(ex){ const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback); if (opts.throwErrors) throw e } + break case 'GetAdminTransactionSwapQuotes': try { if (!methods.GetAdminTransactionSwapQuotes) throw new Error('method: GetAdminTransactionSwapQuotes is not implemented') @@ -1122,14 +1138,27 @@ export default (methods: Types.ServerMethods, opts: NostrOptions) => { opts.metricsCallback([{ ...info, ...stats, ...authContext }]) }catch(ex){ const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback); if (opts.throwErrors) throw e } break - case 'ListAdminSwaps': + case 'ListAdminInvoiceSwaps': try { - if (!methods.ListAdminSwaps) throw new Error('method: ListAdminSwaps is not implemented') + if (!methods.ListAdminInvoiceSwaps) throw new Error('method: ListAdminInvoiceSwaps is not implemented') const authContext = await opts.NostrAdminAuthGuard(req.appId, req.authIdentifier) stats.guard = process.hrtime.bigint() authCtx = authContext stats.validate = stats.guard - const response = await methods.ListAdminSwaps({rpcName:'ListAdminSwaps', ctx:authContext }) + const response = await methods.ListAdminInvoiceSwaps({rpcName:'ListAdminInvoiceSwaps', ctx:authContext }) + stats.handle = process.hrtime.bigint() + res({status: 'OK', ...response}) + opts.metricsCallback([{ ...info, ...stats, ...authContext }]) + }catch(ex){ const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback); if (opts.throwErrors) throw e } + break + case 'ListAdminTxSwaps': + try { + if (!methods.ListAdminTxSwaps) throw new Error('method: ListAdminTxSwaps is not implemented') + const authContext = await opts.NostrAdminAuthGuard(req.appId, req.authIdentifier) + stats.guard = process.hrtime.bigint() + authCtx = authContext + stats.validate = stats.guard + const response = await methods.ListAdminTxSwaps({rpcName:'ListAdminTxSwaps', ctx:authContext }) stats.handle = process.hrtime.bigint() res({status: 'OK', ...response}) opts.metricsCallback([{ ...info, ...stats, ...authContext }]) @@ -1148,14 +1177,14 @@ export default (methods: Types.ServerMethods, opts: NostrOptions) => { opts.metricsCallback([{ ...info, ...stats, ...authContext }]) }catch(ex){ const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback); if (opts.throwErrors) throw e } break - case 'ListSwaps': + case 'ListTxSwaps': try { - if (!methods.ListSwaps) throw new Error('method: ListSwaps is not implemented') + if (!methods.ListTxSwaps) throw new Error('method: ListTxSwaps is not implemented') const authContext = await opts.NostrUserAuthGuard(req.appId, req.authIdentifier) stats.guard = process.hrtime.bigint() authCtx = authContext stats.validate = stats.guard - const response = await methods.ListSwaps({rpcName:'ListSwaps', ctx:authContext }) + const response = await methods.ListTxSwaps({rpcName:'ListTxSwaps', ctx:authContext }) stats.handle = process.hrtime.bigint() res({status: 'OK', ...response}) opts.metricsCallback([{ ...info, ...stats, ...authContext }]) @@ -1254,6 +1283,22 @@ export default (methods: Types.ServerMethods, opts: NostrOptions) => { opts.metricsCallback([{ ...info, ...stats, ...authContext }]) }catch(ex){ const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback); if (opts.throwErrors) throw e } break + case 'PayAdminInvoiceSwap': + try { + if (!methods.PayAdminInvoiceSwap) throw new Error('method: PayAdminInvoiceSwap is not implemented') + const authContext = await opts.NostrAdminAuthGuard(req.appId, req.authIdentifier) + stats.guard = process.hrtime.bigint() + authCtx = authContext + const request = req.body + const error = Types.PayAdminInvoiceSwapRequestValidate(request) + stats.validate = process.hrtime.bigint() + if (error !== null) return logErrorAndReturnResponse(error, 'invalid request body', res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback) + const response = await methods.PayAdminInvoiceSwap({rpcName:'PayAdminInvoiceSwap', ctx:authContext , req: request}) + stats.handle = process.hrtime.bigint() + res({status: 'OK', ...response}) + opts.metricsCallback([{ ...info, ...stats, ...authContext }]) + }catch(ex){ const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback); if (opts.throwErrors) throw e } + break case 'PayAdminTransactionSwap': try { if (!methods.PayAdminTransactionSwap) throw new Error('method: PayAdminTransactionSwap is not implemented') diff --git a/proto/autogenerated/ts/types.ts b/proto/autogenerated/ts/types.ts index e397cd94..78add454 100644 --- a/proto/autogenerated/ts/types.ts +++ b/proto/autogenerated/ts/types.ts @@ -7,8 +7,8 @@ export type RequestMetric = AuthContext & RequestInfo & RequestStats & { error?: export type AdminContext = { admin_id: string } -export type AdminMethodInputs = AddApp_Input | AddPeer_Input | AuthApp_Input | BanUser_Input | CloseChannel_Input | CreateOneTimeInviteLink_Input | GetAdminTransactionSwapQuotes_Input | GetInviteLinkState_Input | GetSeed_Input | ListAdminSwaps_Input | ListChannels_Input | LndGetInfo_Input | OpenChannel_Input | PayAdminTransactionSwap_Input | UpdateChannelPolicy_Input -export type AdminMethodOutputs = AddApp_Output | AddPeer_Output | AuthApp_Output | BanUser_Output | CloseChannel_Output | CreateOneTimeInviteLink_Output | GetAdminTransactionSwapQuotes_Output | GetInviteLinkState_Output | GetSeed_Output | ListAdminSwaps_Output | ListChannels_Output | LndGetInfo_Output | OpenChannel_Output | PayAdminTransactionSwap_Output | UpdateChannelPolicy_Output +export type AdminMethodInputs = AddApp_Input | AddPeer_Input | AuthApp_Input | BanUser_Input | CloseChannel_Input | CreateOneTimeInviteLink_Input | GetAdminInvoiceSwapQuotes_Input | GetAdminTransactionSwapQuotes_Input | GetInviteLinkState_Input | GetSeed_Input | ListAdminInvoiceSwaps_Input | ListAdminTxSwaps_Input | ListChannels_Input | LndGetInfo_Input | OpenChannel_Input | PayAdminInvoiceSwap_Input | PayAdminTransactionSwap_Input | UpdateChannelPolicy_Input +export type AdminMethodOutputs = AddApp_Output | AddPeer_Output | AuthApp_Output | BanUser_Output | CloseChannel_Output | CreateOneTimeInviteLink_Output | GetAdminInvoiceSwapQuotes_Output | GetAdminTransactionSwapQuotes_Output | GetInviteLinkState_Output | GetSeed_Output | ListAdminInvoiceSwaps_Output | ListAdminTxSwaps_Output | ListChannels_Output | LndGetInfo_Output | OpenChannel_Output | PayAdminInvoiceSwap_Output | PayAdminTransactionSwap_Output | UpdateChannelPolicy_Output export type AppContext = { app_id: string } @@ -35,8 +35,8 @@ export type UserContext = { app_user_id: string user_id: string } -export type UserMethodInputs = AddProduct_Input | AddUserOffer_Input | AuthorizeManage_Input | BanDebit_Input | DecodeInvoice_Input | DeleteUserOffer_Input | EditDebit_Input | EnrollAdminToken_Input | EnrollMessagingToken_Input | GetDebitAuthorizations_Input | GetHttpCreds_Input | GetLNURLChannelLink_Input | GetLnurlPayLink_Input | GetLnurlWithdrawLink_Input | GetManageAuthorizations_Input | GetPaymentState_Input | GetTransactionSwapQuotes_Input | GetUserInfo_Input | GetUserOffer_Input | GetUserOfferInvoices_Input | GetUserOffers_Input | GetUserOperations_Input | ListSwaps_Input | NewAddress_Input | NewInvoice_Input | NewProductInvoice_Input | PayAddress_Input | PayInvoice_Input | ResetDebit_Input | ResetManage_Input | RespondToDebit_Input | UpdateCallbackUrl_Input | UpdateUserOffer_Input | UserHealth_Input -export type UserMethodOutputs = AddProduct_Output | AddUserOffer_Output | AuthorizeManage_Output | BanDebit_Output | DecodeInvoice_Output | DeleteUserOffer_Output | EditDebit_Output | EnrollAdminToken_Output | EnrollMessagingToken_Output | GetDebitAuthorizations_Output | GetHttpCreds_Output | GetLNURLChannelLink_Output | GetLnurlPayLink_Output | GetLnurlWithdrawLink_Output | GetManageAuthorizations_Output | GetPaymentState_Output | GetTransactionSwapQuotes_Output | GetUserInfo_Output | GetUserOffer_Output | GetUserOfferInvoices_Output | GetUserOffers_Output | GetUserOperations_Output | ListSwaps_Output | NewAddress_Output | NewInvoice_Output | NewProductInvoice_Output | PayAddress_Output | PayInvoice_Output | ResetDebit_Output | ResetManage_Output | RespondToDebit_Output | UpdateCallbackUrl_Output | UpdateUserOffer_Output | UserHealth_Output +export type UserMethodInputs = AddProduct_Input | AddUserOffer_Input | AuthorizeManage_Input | BanDebit_Input | DecodeInvoice_Input | DeleteUserOffer_Input | EditDebit_Input | EnrollAdminToken_Input | EnrollMessagingToken_Input | GetDebitAuthorizations_Input | GetHttpCreds_Input | GetLNURLChannelLink_Input | GetLnurlPayLink_Input | GetLnurlWithdrawLink_Input | GetManageAuthorizations_Input | GetPaymentState_Input | GetTransactionSwapQuotes_Input | GetUserInfo_Input | GetUserOffer_Input | GetUserOfferInvoices_Input | GetUserOffers_Input | GetUserOperations_Input | ListTxSwaps_Input | NewAddress_Input | NewInvoice_Input | NewProductInvoice_Input | PayAddress_Input | PayInvoice_Input | ResetDebit_Input | ResetManage_Input | RespondToDebit_Input | UpdateCallbackUrl_Input | UpdateUserOffer_Input | UserHealth_Input +export type UserMethodOutputs = AddProduct_Output | AddUserOffer_Output | AuthorizeManage_Output | BanDebit_Output | DecodeInvoice_Output | DeleteUserOffer_Output | EditDebit_Output | EnrollAdminToken_Output | EnrollMessagingToken_Output | GetDebitAuthorizations_Output | GetHttpCreds_Output | GetLNURLChannelLink_Output | GetLnurlPayLink_Output | GetLnurlWithdrawLink_Output | GetManageAuthorizations_Output | GetPaymentState_Output | GetTransactionSwapQuotes_Output | GetUserInfo_Output | GetUserOffer_Output | GetUserOfferInvoices_Output | GetUserOffers_Output | GetUserOperations_Output | ListTxSwaps_Output | NewAddress_Output | NewInvoice_Output | NewProductInvoice_Output | PayAddress_Output | PayInvoice_Output | ResetDebit_Output | ResetManage_Output | RespondToDebit_Output | UpdateCallbackUrl_Output | UpdateUserOffer_Output | UserHealth_Output export type AuthContext = AdminContext | AppContext | GuestContext | GuestWithPubContext | MetricsContext | UserContext export type AddApp_Input = {rpcName:'AddApp', req: AddAppRequest} @@ -99,6 +99,9 @@ export type EnrollAdminToken_Output = ResultError | { status: 'OK' } export type EnrollMessagingToken_Input = {rpcName:'EnrollMessagingToken', req: MessagingToken} export type EnrollMessagingToken_Output = ResultError | { status: 'OK' } +export type GetAdminInvoiceSwapQuotes_Input = {rpcName:'GetAdminInvoiceSwapQuotes', req: InvoiceSwapRequest} +export type GetAdminInvoiceSwapQuotes_Output = ResultError | ({ status: 'OK' } & InvoiceSwapQuoteList) + export type GetAdminTransactionSwapQuotes_Input = {rpcName:'GetAdminTransactionSwapQuotes', req: TransactionSwapRequest} export type GetAdminTransactionSwapQuotes_Output = ResultError | ({ status: 'OK' } & TransactionSwapQuoteList) @@ -238,14 +241,17 @@ export type Health_Output = ResultError | { status: 'OK' } export type LinkNPubThroughToken_Input = {rpcName:'LinkNPubThroughToken', req: LinkNPubThroughTokenRequest} export type LinkNPubThroughToken_Output = ResultError | { status: 'OK' } -export type ListAdminSwaps_Input = {rpcName:'ListAdminSwaps'} -export type ListAdminSwaps_Output = ResultError | ({ status: 'OK' } & SwapsList) +export type ListAdminInvoiceSwaps_Input = {rpcName:'ListAdminInvoiceSwaps'} +export type ListAdminInvoiceSwaps_Output = ResultError | ({ status: 'OK' } & InvoiceSwapsList) + +export type ListAdminTxSwaps_Input = {rpcName:'ListAdminTxSwaps'} +export type ListAdminTxSwaps_Output = ResultError | ({ status: 'OK' } & TxSwapsList) export type ListChannels_Input = {rpcName:'ListChannels'} export type ListChannels_Output = ResultError | ({ status: 'OK' } & LndChannels) -export type ListSwaps_Input = {rpcName:'ListSwaps'} -export type ListSwaps_Output = ResultError | ({ status: 'OK' } & SwapsList) +export type ListTxSwaps_Input = {rpcName:'ListTxSwaps'} +export type ListTxSwaps_Output = ResultError | ({ status: 'OK' } & TxSwapsList) export type LndGetInfo_Input = {rpcName:'LndGetInfo', req: LndGetInfoRequest} export type LndGetInfo_Output = ResultError | ({ status: 'OK' } & LndGetInfoResponse) @@ -268,8 +274,11 @@ export type OpenChannel_Output = ResultError | ({ status: 'OK' } & OpenChannelRe export type PayAddress_Input = {rpcName:'PayAddress', req: PayAddressRequest} export type PayAddress_Output = ResultError | ({ status: 'OK' } & PayAddressResponse) +export type PayAdminInvoiceSwap_Input = {rpcName:'PayAdminInvoiceSwap', req: PayAdminInvoiceSwapRequest} +export type PayAdminInvoiceSwap_Output = ResultError | ({ status: 'OK' } & AdminInvoiceSwapResponse) + export type PayAdminTransactionSwap_Input = {rpcName:'PayAdminTransactionSwap', req: PayAdminTransactionSwapRequest} -export type PayAdminTransactionSwap_Output = ResultError | ({ status: 'OK' } & AdminSwapResponse) +export type PayAdminTransactionSwap_Output = ResultError | ({ status: 'OK' } & AdminTxSwapResponse) export type PayAppUserInvoice_Input = {rpcName:'PayAppUserInvoice', req: PayAppUserInvoiceRequest} export type PayAppUserInvoice_Output = ResultError | ({ status: 'OK' } & PayInvoiceResponse) @@ -357,6 +366,7 @@ export type ServerMethods = { EncryptionExchange?: (req: EncryptionExchange_Input & {ctx: GuestContext }) => Promise EnrollAdminToken?: (req: EnrollAdminToken_Input & {ctx: UserContext }) => Promise EnrollMessagingToken?: (req: EnrollMessagingToken_Input & {ctx: UserContext }) => Promise + GetAdminInvoiceSwapQuotes?: (req: GetAdminInvoiceSwapQuotes_Input & {ctx: AdminContext }) => Promise GetAdminTransactionSwapQuotes?: (req: GetAdminTransactionSwapQuotes_Input & {ctx: AdminContext }) => Promise GetApp?: (req: GetApp_Input & {ctx: AppContext }) => Promise GetAppUser?: (req: GetAppUser_Input & {ctx: AppContext }) => Promise @@ -397,16 +407,18 @@ export type ServerMethods = { HandleLnurlWithdraw?: (req: HandleLnurlWithdraw_Input & {ctx: GuestContext }) => Promise Health?: (req: Health_Input & {ctx: GuestContext }) => Promise LinkNPubThroughToken?: (req: LinkNPubThroughToken_Input & {ctx: GuestWithPubContext }) => Promise - ListAdminSwaps?: (req: ListAdminSwaps_Input & {ctx: AdminContext }) => Promise + ListAdminInvoiceSwaps?: (req: ListAdminInvoiceSwaps_Input & {ctx: AdminContext }) => Promise + ListAdminTxSwaps?: (req: ListAdminTxSwaps_Input & {ctx: AdminContext }) => Promise ListChannels?: (req: ListChannels_Input & {ctx: AdminContext }) => Promise - ListSwaps?: (req: ListSwaps_Input & {ctx: UserContext }) => Promise + ListTxSwaps?: (req: ListTxSwaps_Input & {ctx: UserContext }) => Promise LndGetInfo?: (req: LndGetInfo_Input & {ctx: AdminContext }) => Promise NewAddress?: (req: NewAddress_Input & {ctx: UserContext }) => Promise NewInvoice?: (req: NewInvoice_Input & {ctx: UserContext }) => Promise NewProductInvoice?: (req: NewProductInvoice_Input & {ctx: UserContext }) => Promise OpenChannel?: (req: OpenChannel_Input & {ctx: AdminContext }) => Promise PayAddress?: (req: PayAddress_Input & {ctx: UserContext }) => Promise - PayAdminTransactionSwap?: (req: PayAdminTransactionSwap_Input & {ctx: AdminContext }) => Promise + PayAdminInvoiceSwap?: (req: PayAdminInvoiceSwap_Input & {ctx: AdminContext }) => Promise + PayAdminTransactionSwap?: (req: PayAdminTransactionSwap_Input & {ctx: AdminContext }) => Promise PayAppUserInvoice?: (req: PayAppUserInvoice_Input & {ctx: AppContext }) => Promise PayInvoice?: (req: PayInvoice_Input & {ctx: UserContext }) => Promise PingSubProcesses?: (req: PingSubProcesses_Input & {ctx: MetricsContext }) => Promise @@ -671,17 +683,35 @@ export const AddProductRequestValidate = (o?: AddProductRequest, opts: AddProduc return null } -export type AdminSwapResponse = { +export type AdminInvoiceSwapResponse = { + tx_id: string +} +export const AdminInvoiceSwapResponseOptionalFields: [] = [] +export type AdminInvoiceSwapResponseOptions = OptionsBaseMessage & { + checkOptionalsAreSet?: [] + tx_id_CustomCheck?: (v: string) => boolean +} +export const AdminInvoiceSwapResponseValidate = (o?: AdminInvoiceSwapResponse, opts: AdminInvoiceSwapResponseOptions = {}, path: string = 'AdminInvoiceSwapResponse::root.'): Error | null => { + if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message') + if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null') + + if (typeof o.tx_id !== 'string') return new Error(`${path}.tx_id: is not a string`) + if (opts.tx_id_CustomCheck && !opts.tx_id_CustomCheck(o.tx_id)) return new Error(`${path}.tx_id: custom check failed`) + + return null +} + +export type AdminTxSwapResponse = { network_fee: number tx_id: string } -export const AdminSwapResponseOptionalFields: [] = [] -export type AdminSwapResponseOptions = OptionsBaseMessage & { +export const AdminTxSwapResponseOptionalFields: [] = [] +export type AdminTxSwapResponseOptions = OptionsBaseMessage & { checkOptionalsAreSet?: [] network_fee_CustomCheck?: (v: number) => boolean tx_id_CustomCheck?: (v: string) => boolean } -export const AdminSwapResponseValidate = (o?: AdminSwapResponse, opts: AdminSwapResponseOptions = {}, path: string = 'AdminSwapResponse::root.'): Error | null => { +export const AdminTxSwapResponseValidate = (o?: AdminTxSwapResponse, opts: AdminTxSwapResponseOptions = {}, path: string = 'AdminTxSwapResponse::root.'): Error | null => { if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message') if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null') @@ -2088,6 +2118,185 @@ export const HttpCredsValidate = (o?: HttpCreds, opts: HttpCredsOptions = {}, pa return null } +export type InvoiceSwapOperation = { + failure_reason?: string + invoice_paid: string + operation_payment?: UserOperation + swap_operation_id: string + tx_id: string +} +export type InvoiceSwapOperationOptionalField = 'failure_reason' | 'operation_payment' +export const InvoiceSwapOperationOptionalFields: InvoiceSwapOperationOptionalField[] = ['failure_reason', 'operation_payment'] +export type InvoiceSwapOperationOptions = OptionsBaseMessage & { + checkOptionalsAreSet?: InvoiceSwapOperationOptionalField[] + failure_reason_CustomCheck?: (v?: string) => boolean + invoice_paid_CustomCheck?: (v: string) => boolean + operation_payment_Options?: UserOperationOptions + swap_operation_id_CustomCheck?: (v: string) => boolean + tx_id_CustomCheck?: (v: string) => boolean +} +export const InvoiceSwapOperationValidate = (o?: InvoiceSwapOperation, opts: InvoiceSwapOperationOptions = {}, path: string = 'InvoiceSwapOperation::root.'): Error | null => { + if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message') + if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null') + + if ((o.failure_reason || opts.allOptionalsAreSet || opts.checkOptionalsAreSet?.includes('failure_reason')) && typeof o.failure_reason !== 'string') return new Error(`${path}.failure_reason: is not a string`) + if (opts.failure_reason_CustomCheck && !opts.failure_reason_CustomCheck(o.failure_reason)) return new Error(`${path}.failure_reason: custom check failed`) + + if (typeof o.invoice_paid !== 'string') return new Error(`${path}.invoice_paid: is not a string`) + if (opts.invoice_paid_CustomCheck && !opts.invoice_paid_CustomCheck(o.invoice_paid)) return new Error(`${path}.invoice_paid: custom check failed`) + + if (typeof o.operation_payment === 'object' || opts.allOptionalsAreSet || opts.checkOptionalsAreSet?.includes('operation_payment')) { + const operation_paymentErr = UserOperationValidate(o.operation_payment, opts.operation_payment_Options, `${path}.operation_payment`) + if (operation_paymentErr !== null) return operation_paymentErr + } + + + if (typeof o.swap_operation_id !== 'string') return new Error(`${path}.swap_operation_id: is not a string`) + if (opts.swap_operation_id_CustomCheck && !opts.swap_operation_id_CustomCheck(o.swap_operation_id)) return new Error(`${path}.swap_operation_id: custom check failed`) + + if (typeof o.tx_id !== 'string') return new Error(`${path}.tx_id: is not a string`) + if (opts.tx_id_CustomCheck && !opts.tx_id_CustomCheck(o.tx_id)) return new Error(`${path}.tx_id: custom check failed`) + + return null +} + +export type InvoiceSwapQuote = { + address: string + chain_fee_sats: number + invoice: string + invoice_amount_sats: number + service_fee_sats: number + service_url: string + swap_fee_sats: number + swap_operation_id: string + transaction_amount_sats: number + tx_id: string +} +export const InvoiceSwapQuoteOptionalFields: [] = [] +export type InvoiceSwapQuoteOptions = OptionsBaseMessage & { + checkOptionalsAreSet?: [] + address_CustomCheck?: (v: string) => boolean + chain_fee_sats_CustomCheck?: (v: number) => boolean + invoice_CustomCheck?: (v: string) => boolean + invoice_amount_sats_CustomCheck?: (v: number) => boolean + service_fee_sats_CustomCheck?: (v: number) => boolean + service_url_CustomCheck?: (v: string) => boolean + swap_fee_sats_CustomCheck?: (v: number) => boolean + swap_operation_id_CustomCheck?: (v: string) => boolean + transaction_amount_sats_CustomCheck?: (v: number) => boolean + tx_id_CustomCheck?: (v: string) => boolean +} +export const InvoiceSwapQuoteValidate = (o?: InvoiceSwapQuote, opts: InvoiceSwapQuoteOptions = {}, path: string = 'InvoiceSwapQuote::root.'): Error | null => { + if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message') + if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null') + + if (typeof o.address !== 'string') return new Error(`${path}.address: is not a string`) + if (opts.address_CustomCheck && !opts.address_CustomCheck(o.address)) return new Error(`${path}.address: custom check failed`) + + if (typeof o.chain_fee_sats !== 'number') return new Error(`${path}.chain_fee_sats: is not a number`) + if (opts.chain_fee_sats_CustomCheck && !opts.chain_fee_sats_CustomCheck(o.chain_fee_sats)) return new Error(`${path}.chain_fee_sats: custom check failed`) + + if (typeof o.invoice !== 'string') return new Error(`${path}.invoice: is not a string`) + if (opts.invoice_CustomCheck && !opts.invoice_CustomCheck(o.invoice)) return new Error(`${path}.invoice: custom check failed`) + + if (typeof o.invoice_amount_sats !== 'number') return new Error(`${path}.invoice_amount_sats: is not a number`) + if (opts.invoice_amount_sats_CustomCheck && !opts.invoice_amount_sats_CustomCheck(o.invoice_amount_sats)) return new Error(`${path}.invoice_amount_sats: custom check failed`) + + if (typeof o.service_fee_sats !== 'number') return new Error(`${path}.service_fee_sats: is not a number`) + if (opts.service_fee_sats_CustomCheck && !opts.service_fee_sats_CustomCheck(o.service_fee_sats)) return new Error(`${path}.service_fee_sats: custom check failed`) + + if (typeof o.service_url !== 'string') return new Error(`${path}.service_url: is not a string`) + if (opts.service_url_CustomCheck && !opts.service_url_CustomCheck(o.service_url)) return new Error(`${path}.service_url: custom check failed`) + + if (typeof o.swap_fee_sats !== 'number') return new Error(`${path}.swap_fee_sats: is not a number`) + if (opts.swap_fee_sats_CustomCheck && !opts.swap_fee_sats_CustomCheck(o.swap_fee_sats)) return new Error(`${path}.swap_fee_sats: custom check failed`) + + if (typeof o.swap_operation_id !== 'string') return new Error(`${path}.swap_operation_id: is not a string`) + if (opts.swap_operation_id_CustomCheck && !opts.swap_operation_id_CustomCheck(o.swap_operation_id)) return new Error(`${path}.swap_operation_id: custom check failed`) + + if (typeof o.transaction_amount_sats !== 'number') return new Error(`${path}.transaction_amount_sats: is not a number`) + if (opts.transaction_amount_sats_CustomCheck && !opts.transaction_amount_sats_CustomCheck(o.transaction_amount_sats)) return new Error(`${path}.transaction_amount_sats: custom check failed`) + + if (typeof o.tx_id !== 'string') return new Error(`${path}.tx_id: is not a string`) + if (opts.tx_id_CustomCheck && !opts.tx_id_CustomCheck(o.tx_id)) return new Error(`${path}.tx_id: custom check failed`) + + return null +} + +export type InvoiceSwapQuoteList = { + quotes: InvoiceSwapQuote[] +} +export const InvoiceSwapQuoteListOptionalFields: [] = [] +export type InvoiceSwapQuoteListOptions = OptionsBaseMessage & { + checkOptionalsAreSet?: [] + quotes_ItemOptions?: InvoiceSwapQuoteOptions + quotes_CustomCheck?: (v: InvoiceSwapQuote[]) => boolean +} +export const InvoiceSwapQuoteListValidate = (o?: InvoiceSwapQuoteList, opts: InvoiceSwapQuoteListOptions = {}, path: string = 'InvoiceSwapQuoteList::root.'): Error | null => { + if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message') + if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null') + + if (!Array.isArray(o.quotes)) return new Error(`${path}.quotes: is not an array`) + for (let index = 0; index < o.quotes.length; index++) { + const quotesErr = InvoiceSwapQuoteValidate(o.quotes[index], opts.quotes_ItemOptions, `${path}.quotes[${index}]`) + if (quotesErr !== null) return quotesErr + } + if (opts.quotes_CustomCheck && !opts.quotes_CustomCheck(o.quotes)) return new Error(`${path}.quotes: custom check failed`) + + return null +} + +export type InvoiceSwapRequest = { + invoice: string +} +export const InvoiceSwapRequestOptionalFields: [] = [] +export type InvoiceSwapRequestOptions = OptionsBaseMessage & { + checkOptionalsAreSet?: [] + invoice_CustomCheck?: (v: string) => boolean +} +export const InvoiceSwapRequestValidate = (o?: InvoiceSwapRequest, opts: InvoiceSwapRequestOptions = {}, path: string = 'InvoiceSwapRequest::root.'): Error | null => { + if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message') + if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null') + + if (typeof o.invoice !== 'string') return new Error(`${path}.invoice: is not a string`) + if (opts.invoice_CustomCheck && !opts.invoice_CustomCheck(o.invoice)) return new Error(`${path}.invoice: custom check failed`) + + return null +} + +export type InvoiceSwapsList = { + quotes: InvoiceSwapQuote[] + swaps: InvoiceSwapOperation[] +} +export const InvoiceSwapsListOptionalFields: [] = [] +export type InvoiceSwapsListOptions = OptionsBaseMessage & { + checkOptionalsAreSet?: [] + quotes_ItemOptions?: InvoiceSwapQuoteOptions + quotes_CustomCheck?: (v: InvoiceSwapQuote[]) => boolean + swaps_ItemOptions?: InvoiceSwapOperationOptions + swaps_CustomCheck?: (v: InvoiceSwapOperation[]) => boolean +} +export const InvoiceSwapsListValidate = (o?: InvoiceSwapsList, opts: InvoiceSwapsListOptions = {}, path: string = 'InvoiceSwapsList::root.'): Error | null => { + if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message') + if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null') + + if (!Array.isArray(o.quotes)) return new Error(`${path}.quotes: is not an array`) + for (let index = 0; index < o.quotes.length; index++) { + const quotesErr = InvoiceSwapQuoteValidate(o.quotes[index], opts.quotes_ItemOptions, `${path}.quotes[${index}]`) + if (quotesErr !== null) return quotesErr + } + if (opts.quotes_CustomCheck && !opts.quotes_CustomCheck(o.quotes)) return new Error(`${path}.quotes: custom check failed`) + + if (!Array.isArray(o.swaps)) return new Error(`${path}.swaps: is not an array`) + for (let index = 0; index < o.swaps.length; index++) { + const swapsErr = InvoiceSwapOperationValidate(o.swaps[index], opts.swaps_ItemOptions, `${path}.swaps[${index}]`) + if (swapsErr !== null) return swapsErr + } + if (opts.swaps_CustomCheck && !opts.swaps_CustomCheck(o.swaps)) return new Error(`${path}.swaps: custom check failed`) + + return null +} + export type LatestBundleMetricReq = { limit?: number } @@ -3308,6 +3517,29 @@ export const PayAddressResponseValidate = (o?: PayAddressResponse, opts: PayAddr return null } +export type PayAdminInvoiceSwapRequest = { + sat_per_v_byte: number + swap_operation_id: string +} +export const PayAdminInvoiceSwapRequestOptionalFields: [] = [] +export type PayAdminInvoiceSwapRequestOptions = OptionsBaseMessage & { + checkOptionalsAreSet?: [] + sat_per_v_byte_CustomCheck?: (v: number) => boolean + swap_operation_id_CustomCheck?: (v: string) => boolean +} +export const PayAdminInvoiceSwapRequestValidate = (o?: PayAdminInvoiceSwapRequest, opts: PayAdminInvoiceSwapRequestOptions = {}, path: string = 'PayAdminInvoiceSwapRequest::root.'): Error | null => { + if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message') + if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null') + + if (typeof o.sat_per_v_byte !== 'number') return new Error(`${path}.sat_per_v_byte: is not a number`) + if (opts.sat_per_v_byte_CustomCheck && !opts.sat_per_v_byte_CustomCheck(o.sat_per_v_byte)) return new Error(`${path}.sat_per_v_byte: custom check failed`) + + if (typeof o.swap_operation_id !== 'string') return new Error(`${path}.swap_operation_id: is not a string`) + if (opts.swap_operation_id_CustomCheck && !opts.swap_operation_id_CustomCheck(o.swap_operation_id)) return new Error(`${path}.swap_operation_id: custom check failed`) + + return null +} + export type PayAdminTransactionSwapRequest = { address: string swap_operation_id: string @@ -3917,76 +4149,6 @@ export const SingleMetricReqValidate = (o?: SingleMetricReq, opts: SingleMetricR return null } -export type SwapOperation = { - address_paid: string - failure_reason?: string - operation_payment?: UserOperation - swap_operation_id: string -} -export type SwapOperationOptionalField = 'failure_reason' | 'operation_payment' -export const SwapOperationOptionalFields: SwapOperationOptionalField[] = ['failure_reason', 'operation_payment'] -export type SwapOperationOptions = OptionsBaseMessage & { - checkOptionalsAreSet?: SwapOperationOptionalField[] - address_paid_CustomCheck?: (v: string) => boolean - failure_reason_CustomCheck?: (v?: string) => boolean - operation_payment_Options?: UserOperationOptions - swap_operation_id_CustomCheck?: (v: string) => boolean -} -export const SwapOperationValidate = (o?: SwapOperation, opts: SwapOperationOptions = {}, path: string = 'SwapOperation::root.'): Error | null => { - if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message') - if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null') - - if (typeof o.address_paid !== 'string') return new Error(`${path}.address_paid: is not a string`) - if (opts.address_paid_CustomCheck && !opts.address_paid_CustomCheck(o.address_paid)) return new Error(`${path}.address_paid: custom check failed`) - - if ((o.failure_reason || opts.allOptionalsAreSet || opts.checkOptionalsAreSet?.includes('failure_reason')) && typeof o.failure_reason !== 'string') return new Error(`${path}.failure_reason: is not a string`) - if (opts.failure_reason_CustomCheck && !opts.failure_reason_CustomCheck(o.failure_reason)) return new Error(`${path}.failure_reason: custom check failed`) - - if (typeof o.operation_payment === 'object' || opts.allOptionalsAreSet || opts.checkOptionalsAreSet?.includes('operation_payment')) { - const operation_paymentErr = UserOperationValidate(o.operation_payment, opts.operation_payment_Options, `${path}.operation_payment`) - if (operation_paymentErr !== null) return operation_paymentErr - } - - - if (typeof o.swap_operation_id !== 'string') return new Error(`${path}.swap_operation_id: is not a string`) - if (opts.swap_operation_id_CustomCheck && !opts.swap_operation_id_CustomCheck(o.swap_operation_id)) return new Error(`${path}.swap_operation_id: custom check failed`) - - return null -} - -export type SwapsList = { - quotes: TransactionSwapQuote[] - swaps: SwapOperation[] -} -export const SwapsListOptionalFields: [] = [] -export type SwapsListOptions = OptionsBaseMessage & { - checkOptionalsAreSet?: [] - quotes_ItemOptions?: TransactionSwapQuoteOptions - quotes_CustomCheck?: (v: TransactionSwapQuote[]) => boolean - swaps_ItemOptions?: SwapOperationOptions - swaps_CustomCheck?: (v: SwapOperation[]) => boolean -} -export const SwapsListValidate = (o?: SwapsList, opts: SwapsListOptions = {}, path: string = 'SwapsList::root.'): Error | null => { - if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message') - if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null') - - if (!Array.isArray(o.quotes)) return new Error(`${path}.quotes: is not an array`) - for (let index = 0; index < o.quotes.length; index++) { - const quotesErr = TransactionSwapQuoteValidate(o.quotes[index], opts.quotes_ItemOptions, `${path}.quotes[${index}]`) - if (quotesErr !== null) return quotesErr - } - if (opts.quotes_CustomCheck && !opts.quotes_CustomCheck(o.quotes)) return new Error(`${path}.quotes: custom check failed`) - - if (!Array.isArray(o.swaps)) return new Error(`${path}.swaps: is not an array`) - for (let index = 0; index < o.swaps.length; index++) { - const swapsErr = SwapOperationValidate(o.swaps[index], opts.swaps_ItemOptions, `${path}.swaps[${index}]`) - if (swapsErr !== null) return swapsErr - } - if (opts.swaps_CustomCheck && !opts.swaps_CustomCheck(o.swaps)) return new Error(`${path}.swaps: custom check failed`) - - return null -} - export type TransactionSwapQuote = { chain_fee_sats: number invoice_amount_sats: number @@ -4076,6 +4238,76 @@ export const TransactionSwapRequestValidate = (o?: TransactionSwapRequest, opts: return null } +export type TxSwapOperation = { + address_paid: string + failure_reason?: string + operation_payment?: UserOperation + swap_operation_id: string +} +export type TxSwapOperationOptionalField = 'failure_reason' | 'operation_payment' +export const TxSwapOperationOptionalFields: TxSwapOperationOptionalField[] = ['failure_reason', 'operation_payment'] +export type TxSwapOperationOptions = OptionsBaseMessage & { + checkOptionalsAreSet?: TxSwapOperationOptionalField[] + address_paid_CustomCheck?: (v: string) => boolean + failure_reason_CustomCheck?: (v?: string) => boolean + operation_payment_Options?: UserOperationOptions + swap_operation_id_CustomCheck?: (v: string) => boolean +} +export const TxSwapOperationValidate = (o?: TxSwapOperation, opts: TxSwapOperationOptions = {}, path: string = 'TxSwapOperation::root.'): Error | null => { + if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message') + if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null') + + if (typeof o.address_paid !== 'string') return new Error(`${path}.address_paid: is not a string`) + if (opts.address_paid_CustomCheck && !opts.address_paid_CustomCheck(o.address_paid)) return new Error(`${path}.address_paid: custom check failed`) + + if ((o.failure_reason || opts.allOptionalsAreSet || opts.checkOptionalsAreSet?.includes('failure_reason')) && typeof o.failure_reason !== 'string') return new Error(`${path}.failure_reason: is not a string`) + if (opts.failure_reason_CustomCheck && !opts.failure_reason_CustomCheck(o.failure_reason)) return new Error(`${path}.failure_reason: custom check failed`) + + if (typeof o.operation_payment === 'object' || opts.allOptionalsAreSet || opts.checkOptionalsAreSet?.includes('operation_payment')) { + const operation_paymentErr = UserOperationValidate(o.operation_payment, opts.operation_payment_Options, `${path}.operation_payment`) + if (operation_paymentErr !== null) return operation_paymentErr + } + + + if (typeof o.swap_operation_id !== 'string') return new Error(`${path}.swap_operation_id: is not a string`) + if (opts.swap_operation_id_CustomCheck && !opts.swap_operation_id_CustomCheck(o.swap_operation_id)) return new Error(`${path}.swap_operation_id: custom check failed`) + + return null +} + +export type TxSwapsList = { + quotes: TransactionSwapQuote[] + swaps: TxSwapOperation[] +} +export const TxSwapsListOptionalFields: [] = [] +export type TxSwapsListOptions = OptionsBaseMessage & { + checkOptionalsAreSet?: [] + quotes_ItemOptions?: TransactionSwapQuoteOptions + quotes_CustomCheck?: (v: TransactionSwapQuote[]) => boolean + swaps_ItemOptions?: TxSwapOperationOptions + swaps_CustomCheck?: (v: TxSwapOperation[]) => boolean +} +export const TxSwapsListValidate = (o?: TxSwapsList, opts: TxSwapsListOptions = {}, path: string = 'TxSwapsList::root.'): Error | null => { + if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message') + if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null') + + if (!Array.isArray(o.quotes)) return new Error(`${path}.quotes: is not an array`) + for (let index = 0; index < o.quotes.length; index++) { + const quotesErr = TransactionSwapQuoteValidate(o.quotes[index], opts.quotes_ItemOptions, `${path}.quotes[${index}]`) + if (quotesErr !== null) return quotesErr + } + if (opts.quotes_CustomCheck && !opts.quotes_CustomCheck(o.quotes)) return new Error(`${path}.quotes: custom check failed`) + + if (!Array.isArray(o.swaps)) return new Error(`${path}.swaps: is not an array`) + for (let index = 0; index < o.swaps.length; index++) { + const swapsErr = TxSwapOperationValidate(o.swaps[index], opts.swaps_ItemOptions, `${path}.swaps[${index}]`) + if (swapsErr !== null) return swapsErr + } + if (opts.swaps_CustomCheck && !opts.swaps_CustomCheck(o.swaps)) return new Error(`${path}.swaps: custom check failed`) + + return null +} + export type UpdateChannelPolicyRequest = { policy: ChannelPolicy update: UpdateChannelPolicyRequest_update diff --git a/proto/service/methods.proto b/proto/service/methods.proto index feaf3e97..15292e37 100644 --- a/proto/service/methods.proto +++ b/proto/service/methods.proto @@ -175,6 +175,27 @@ service LightningPub { option (nostr) = true; } + rpc GetAdminInvoiceSwapQuotes(structs.InvoiceSwapRequest) returns (structs.InvoiceSwapQuoteList) { + option (auth_type) = "Admin"; + option (http_method) = "post"; + option (http_route) = "/api/admin/swap/invoice/quote"; + option (nostr) = true; + } + + rpc ListAdminInvoiceSwaps(structs.Empty) returns (structs.InvoiceSwapsList) { + option (auth_type) = "Admin"; + option (http_method) = "post"; + option (http_route) = "/api/admin/swap/invoice/list"; + option (nostr) = true; + } + + rpc PayAdminInvoiceSwap(structs.PayAdminInvoiceSwapRequest) returns (structs.AdminInvoiceSwapResponse) { + option (auth_type) = "Admin"; + option (http_method) = "post"; + option (http_route) = "/api/admin/swap/invoice/pay"; + option (nostr) = true; + } + rpc GetAdminTransactionSwapQuotes(structs.TransactionSwapRequest) returns (structs.TransactionSwapQuoteList) { option (auth_type) = "Admin"; option (http_method) = "post"; @@ -182,17 +203,17 @@ service LightningPub { option (nostr) = true; } - rpc PayAdminTransactionSwap(structs.PayAdminTransactionSwapRequest) returns (structs.AdminSwapResponse) { + rpc PayAdminTransactionSwap(structs.PayAdminTransactionSwapRequest) returns (structs.AdminTxSwapResponse) { option (auth_type) = "Admin"; option (http_method) = "post"; option (http_route) = "/api/admin/swap/transaction/pay"; option (nostr) = true; } - rpc ListAdminSwaps(structs.Empty) returns (structs.SwapsList) { + rpc ListAdminTxSwaps(structs.Empty) returns (structs.TxSwapsList) { option (auth_type) = "Admin"; option (http_method) = "post"; - option (http_route) = "/api/admin/swap/list"; + option (http_route) = "/api/admin/swap/transaction/list"; option (nostr) = true; } @@ -520,14 +541,14 @@ service LightningPub { rpc GetTransactionSwapQuotes(structs.TransactionSwapRequest) returns (structs.TransactionSwapQuoteList){ option (auth_type) = "User"; option (http_method) = "post"; - option (http_route) = "/api/user/swap/quote"; + option (http_route) = "/api/user/swap/transaction/quote"; option (nostr) = true; } - rpc ListSwaps(structs.Empty) returns (structs.SwapsList){ + rpc ListTxSwaps(structs.Empty) returns (structs.TxSwapsList){ option (auth_type) = "User"; option (http_method) = "post"; - option (http_route) = "/api/user/swap/list"; + option (http_route) = "/api/user/swap/transaction/list"; option (nostr) = true; } diff --git a/proto/service/structs.proto b/proto/service/structs.proto index 00552fdd..e93e6691 100644 --- a/proto/service/structs.proto +++ b/proto/service/structs.proto @@ -833,6 +833,49 @@ message MessagingToken { string firebase_messaging_token = 2; } +message InvoiceSwapRequest { + string invoice = 1; +} + +message InvoiceSwapQuote { + string swap_operation_id = 1; + string invoice = 2; + int64 invoice_amount_sats = 3; + string address = 4; + int64 transaction_amount_sats = 5; + int64 chain_fee_sats = 6; + int64 service_fee_sats = 7; + string service_url = 8; + int64 swap_fee_sats = 9; + string tx_id = 10; +} + +message InvoiceSwapQuoteList { + repeated InvoiceSwapQuote quotes = 1; +} + +message InvoiceSwapOperation { + string swap_operation_id = 1; + optional UserOperation operation_payment = 2; + optional string failure_reason = 3; + string invoice_paid = 4; + string tx_id = 5; +} + +message InvoiceSwapsList { + repeated InvoiceSwapOperation swaps = 1; + repeated InvoiceSwapQuote quotes = 2; +} + +message PayAdminInvoiceSwapRequest { + string swap_operation_id = 1; + int64 sat_per_v_byte = 2; +} + +message AdminInvoiceSwapResponse { + string tx_id = 1; +} + message TransactionSwapRequest { int64 transaction_amount_sats = 2; } @@ -857,20 +900,20 @@ message TransactionSwapQuoteList { repeated TransactionSwapQuote quotes = 1; } -message AdminSwapResponse { +message AdminTxSwapResponse { string tx_id = 1; int64 network_fee = 2; } -message SwapOperation { +message TxSwapOperation { string swap_operation_id = 1; optional UserOperation operation_payment = 2; optional string failure_reason = 3; string address_paid = 4; } -message SwapsList { - repeated SwapOperation swaps = 1; +message TxSwapsList { + repeated TxSwapOperation swaps = 1; repeated TransactionSwapQuote quotes = 2; } diff --git a/src/services/lnd/swaps/submarineSwaps.ts b/src/services/lnd/swaps/submarineSwaps.ts index 0c7de08c..ffbb8545 100644 --- a/src/services/lnd/swaps/submarineSwaps.ts +++ b/src/services/lnd/swaps/submarineSwaps.ts @@ -11,10 +11,38 @@ import { getLogger, PubLogger, ERROR } from '../../helpers/logger.js'; import { loggedGet, loggedPost } from './swapHelpers.js'; import { BTCNetwork } from '../../main/settings.js'; -type InvoiceSwapResponse = { id: string, claimPublicKey: string, swapTree: string } -type InvoiceSwapInfo = { paymentHash: string, keys: ECPairInterface } -type InvoiceSwapData = { createdResponse: InvoiceSwapResponse, info: InvoiceSwapInfo } +/* type InvoiceSwapFees = { + hash: string, + rate: number, + limits: { + maximal: number, + minimal: number, + maximalZeroConf: number + }, + fees: { + percentage: number, + minerFees: number, + } +} */ +type InvoiceSwapFees = { + percentage: number, + minerFees: number, +} + +type InvoiceSwapFeesRes = { + BTC?: { + BTC?: { + fees: InvoiceSwapFees + } + } +} +type InvoiceSwapResponse = { + id: string, claimPublicKey: string, swapTree: string, timeoutBlockHeight: number, + expectedAmount: number, address: string +} +type InvoiceSwapInfo = { paymentHash: string, keys: ECPairInterface } +export type InvoiceSwapData = { createdResponse: InvoiceSwapResponse, info: InvoiceSwapInfo } export class SubmarineSwaps { private httpUrl: string @@ -33,8 +61,23 @@ export class SubmarineSwaps { return this.wsUrl } - SwapInvoice = async (invoice: string, paymentHash: string) => { + GetFees = async (): Promise<{ ok: true, fees: InvoiceSwapFees, } | { ok: false, error: string }> => { + const url = `${this.httpUrl}/v2/swap/submarine` + const feesRes = await loggedGet(this.log, url) + if (!feesRes.ok) { + return { ok: false, error: feesRes.error } + } + if (!feesRes.data.BTC?.BTC?.fees) { + return { ok: false, error: 'No fees found for BTC to BTC swap' } + } + return { ok: true, fees: feesRes.data.BTC.BTC.fees } + } + + SwapInvoice = async (invoice: string): Promise<{ ok: true, createdResponse: InvoiceSwapResponse, pubkey: string, privKey: string } | { ok: false, error: string }> => { const keys = ECPairFactory(ecc).makeRandom() + if (!keys.privateKey) { + return { ok: false, error: 'Failed to generate keys' } + } const refundPublicKey = Buffer.from(keys.publicKey).toString('hex') const req = { invoice, to: 'BTC', from: 'BTC', refundPublicKey } const url = `${this.httpUrl}/v2/swap/submarine` @@ -46,21 +89,25 @@ export class SubmarineSwaps { const createdResponse = createdResponseRes.data this.log('Created invoice swap'); this.log(createdResponse); - + return { + ok: true, createdResponse, + pubkey: refundPublicKey, + privKey: Buffer.from(keys.privateKey).toString('hex') + } } - SubscribeToInvoiceSwap = async (data: InvoiceSwapData, swapDone: (result: { ok: true, txId: string } | { ok: false, error: string }) => void) => { + SubscribeToInvoiceSwap = (data: InvoiceSwapData, swapDone: (result: { ok: true } | { ok: false, error: string }) => void, waitingTx: () => void) => { const webSocket = new ws(`${this.wsUrl}/v2/ws`) const subReq = { op: 'subscribe', channel: 'swap.update', args: [data.createdResponse.id] } webSocket.on('open', () => { webSocket.send(JSON.stringify(subReq)) }) - let txId = "", isDone = false + let isDone = false const done = () => { isDone = true webSocket.close() - swapDone({ ok: true, txId }) + swapDone({ ok: true }) } webSocket.on('error', (err) => { this.log(ERROR, 'Error in WebSocket', err.message) @@ -73,16 +120,19 @@ export class SubmarineSwaps { }) webSocket.on('message', async (rawMsg) => { try { - await this.handleSwapInvoiceMessage(rawMsg, data, done) + await this.handleSwapInvoiceMessage(rawMsg, data, done, waitingTx) } catch (err: any) { this.log(ERROR, 'Error handling invoice WebSocket message', err.message) webSocket.close() return } }); + return () => { + webSocket.close() + } } - handleSwapInvoiceMessage = async (rawMsg: ws.RawData, data: InvoiceSwapData, closeWebSocket: () => void) => { + handleSwapInvoiceMessage = async (rawMsg: ws.RawData, data: InvoiceSwapData, closeWebSocket: () => void, waitingTx: () => void) => { const msg = JSON.parse(rawMsg.toString('utf-8')); if (msg.event !== 'update') { return; @@ -94,6 +144,7 @@ export class SubmarineSwaps { // "invoice.set" means Boltz is waiting for an onchain transaction to be sent case 'invoice.set': this.log('Waiting for onchain transaction'); + waitingTx() return; // Create a partial signature to allow Boltz to do a key path spend to claim the mainchain coins case 'transaction.claim.pending': diff --git a/src/services/lnd/swaps/swaps.ts b/src/services/lnd/swaps/swaps.ts index e53c8751..381e0690 100644 --- a/src/services/lnd/swaps/swaps.ts +++ b/src/services/lnd/swaps/swaps.ts @@ -7,7 +7,8 @@ import Storage from '../../storage/index.js'; import LND from '../lnd.js'; import { UserInvoicePayment } from '../../storage/entity/UserInvoicePayment.js'; import { ReverseSwaps, TransactionSwapData } from './reverseSwaps.js'; -import { SubmarineSwaps } from './submarineSwaps.js'; +import { SubmarineSwaps, InvoiceSwapData } from './submarineSwaps.js'; +import { InvoiceSwap } from '../../storage/entity/InvoiceSwap.js'; export class Swaps { @@ -16,6 +17,7 @@ export class Swaps { subSwappers: Record storage: Storage lnd: LND + waitingSwaps: Record = {} log = getLogger({ component: 'swaps' }) constructor(settings: SettingsManager, storage: Storage) { this.settings = settings @@ -45,7 +47,7 @@ export class Swaps { return keys } - GetInvoiceSwapQuotes = async (appUserId: string, payments: UserInvoicePayment[], getServiceFee: (amt: number) => number): Promise => { + GetInvoiceSwapQuotes = async (appUserId: string, invoice: string): Promise => { if (!this.settings.getSettings().swapsSettings.enableSwaps) { throw new Error("Swaps are not enabled") } @@ -53,13 +55,178 @@ export class Swaps { if (swappers.length === 0) { throw new Error("No swap services available") } - const res = await Promise.allSettled(swappers.map(sw => this.getInvoiceSwapQuote(sw, appUserId, payments, getServiceFee))) + const res = await Promise.allSettled(swappers.map(sw => this.getInvoiceSwapQuote(sw, appUserId, invoice))) const failures: string[] = [] const success: Types.InvoiceSwapQuote[] = [] - for (const r of res) { } + for (const r of res) { + if (r.status === 'fulfilled') { + success.push(r.value) + } else { + failures.push(r.reason.message ? r.reason.message : r.reason.toString()) + } + } + if (success.length === 0) { + throw new Error(failures.join("\n")) + } + return success } - ListTxSwaps = async (appUserId: string, payments: UserInvoicePayment[], newOp: (p: UserInvoicePayment) => Types.UserOperation | undefined, getServiceFee: (amt: number) => number): Promise => { + ListInvoiceSwaps = async (appUserId: string): Promise => { + const completedSwaps = await this.storage.paymentStorage.ListCompletedInvoiceSwaps(appUserId) + const pendingSwaps = await this.storage.paymentStorage.ListPendingInvoiceSwaps(appUserId) + return { + swaps: completedSwaps.map(s => { + return { + invoice_paid: s.invoice, + swap_operation_id: s.swap_operation_id, + failure_reason: s.failure_reason, + tx_id: s.tx_id, + } + }), + quotes: pendingSwaps.map(s => { + return { + swap_operation_id: s.swap_operation_id, + invoice: s.invoice, + invoice_amount_sats: s.invoice_amount, + address: s.address, + transaction_amount_sats: s.transaction_amount, + chain_fee_sats: s.chain_fee_sats, + service_fee_sats: 0, + service_url: s.service_url, + swap_fee_sats: s.swap_fee_sats, + tx_id: s.tx_id, + } + }) + } + } + + PayInvoiceSwap = async (appUserId: string, swapOpId: string, satPerVByte: number, payAddress: (address: string, amt: number) => Promise<{ txId: string }>): Promise => { + if (!this.settings.getSettings().swapsSettings.enableSwaps) { + throw new Error("Swaps are not enabled") + } + if (!swapOpId) { + throw new Error("swap operation id is required") + } + if (!satPerVByte) { + throw new Error("sat per v byte is required") + } + const swap = await this.storage.paymentStorage.GetInvoiceSwap(swapOpId, appUserId) + if (!swap) { + throw new Error("swap not found") + } + const swapper = this.subSwappers[swap.service_url] + if (!swapper) { + throw new Error("swapper service not found") + } + if (this.waitingSwaps[swapOpId]) { + throw new Error("swap already in progress") + } + this.waitingSwaps[swapOpId] = true + const data = this.getInvoiceSwapData(swap) + let txId = "" + const close = swapper.SubscribeToInvoiceSwap(data, async (result) => { + if (result.ok) { + await this.storage.paymentStorage.FinalizeInvoiceSwap(swapOpId) + this.log("invoice swap completed", { swapOpId, txId }) + } else { + await this.storage.paymentStorage.FailInvoiceSwap(swapOpId, result.error, txId) + this.log("invoice swap failed", { swapOpId, error: result.error }) + } + }, () => payAddress(swap.address, swap.transaction_amount).then(res => { txId = res.txId }).catch(err => { close(); this.log("error paying address", err) })) + } + + ResumeInvoiceSwaps = async () => { + this.log("resuming invoice swaps") + const swaps = await this.storage.paymentStorage.ListUnfinishedInvoiceSwaps() + this.log("resuming", swaps.length, "invoice swaps") + for (const swap of swaps) { + this.resumeInvoiceSwap(swap) + } + } + + + private resumeInvoiceSwap = (swap: InvoiceSwap) => { + // const swap = await this.storage.paymentStorage.GetInvoiceSwap(swapOpId, appUserId) + if (!swap || !swap.tx_id || swap.used) { + throw new Error("swap to resume not found, or does not have a tx id") + } + const swapper = this.subSwappers[swap.service_url] + if (!swapper) { + throw new Error("swapper service not found") + } + const data = this.getInvoiceSwapData(swap) + swapper.SubscribeToInvoiceSwap(data, async (result) => { + if (result.ok) { + await this.storage.paymentStorage.FinalizeInvoiceSwap(swap.swap_operation_id) + this.log("invoice swap completed", { swapOpId: swap.swap_operation_id, txId: swap.tx_id }) + } else { + await this.storage.paymentStorage.FailInvoiceSwap(swap.swap_operation_id, result.error) + this.log("invoice swap failed", { swapOpId: swap.swap_operation_id, error: result.error }) + } + }, () => { throw new Error("swap tx already paid") }) + } + + private getInvoiceSwapData = (swap: InvoiceSwap) => { + return { + createdResponse: { + address: swap.address, + claimPublicKey: swap.claim_public_key, + id: swap.swap_quote_id, + swapTree: swap.swap_tree, + timeoutBlockHeight: swap.timeout_block_height, + expectedAmount: swap.transaction_amount, + }, + info: { + keys: this.GetKeys(swap.ephemeral_private_key), + paymentHash: swap.payment_hash, + } + } + } + + private async getInvoiceSwapQuote(swapper: SubmarineSwaps, appUserId: string, invoice: string): Promise { + const feesRes = await swapper.GetFees() + if (!feesRes.ok) { + throw new Error(feesRes.error) + } + const decoded = await this.lnd.DecodeInvoice(invoice) + const amt = decoded.numSatoshis + const fee = Math.ceil((feesRes.fees.percentage / 100) * amt) + feesRes.fees.minerFees + const res = await swapper.SwapInvoice(invoice) + if (!res.ok) { + throw new Error(res.error) + } + const newSwap = await this.storage.paymentStorage.AddInvoiceSwap({ + app_user_id: appUserId, + swap_quote_id: res.createdResponse.id, + swap_tree: JSON.stringify(res.createdResponse.swapTree), + timeout_block_height: res.createdResponse.timeoutBlockHeight, + ephemeral_public_key: res.pubkey, + ephemeral_private_key: res.privKey, + invoice: invoice, + invoice_amount: amt, + transaction_amount: res.createdResponse.expectedAmount, + swap_fee_sats: fee, + chain_fee_sats: 0, + service_url: swapper.getHttpUrl(), + address: res.createdResponse.address, + claim_public_key: res.createdResponse.claimPublicKey, + payment_hash: decoded.paymentHash, + }) + return { + swap_operation_id: newSwap.swap_operation_id, + invoice: invoice, + invoice_amount_sats: amt, + address: res.createdResponse.address, + transaction_amount_sats: res.createdResponse.expectedAmount, + chain_fee_sats: 0, + service_fee_sats: 0, + service_url: swapper.getHttpUrl(), + swap_fee_sats: fee, + tx_id: newSwap.tx_id, + } + } + + ListTxSwaps = async (appUserId: string, payments: UserInvoicePayment[], newOp: (p: UserInvoicePayment) => Types.UserOperation | undefined, getServiceFee: (amt: number) => number): Promise => { const completedSwaps = await this.storage.paymentStorage.ListCompletedTxSwaps(appUserId, payments) const pendingSwaps = await this.storage.paymentStorage.ListPendingTransactionSwaps(appUserId) return { diff --git a/src/services/main/adminManager.ts b/src/services/main/adminManager.ts index 1474707a..8284b253 100644 --- a/src/services/main/adminManager.ts +++ b/src/services/main/adminManager.ts @@ -260,15 +260,36 @@ export class AdminManager { } } - async ListAdminSwaps(): Promise { - return this.swaps.ListSwaps("admin", [], p => undefined, amt => 0) + async ListAdminInvoiceSwaps(): Promise { + return this.swaps.ListInvoiceSwaps("admin") + } + + async GetAdminInvoiceSwapQuotes(req: Types.InvoiceSwapRequest): Promise { + const quotes = await this.swaps.GetInvoiceSwapQuotes("admin", req.invoice) + return { quotes } + } + + async PayAdminInvoiceSwap(req: Types.PayAdminInvoiceSwapRequest): Promise { + const txId = await new Promise(res => { + this.swaps.PayInvoiceSwap("admin", req.swap_operation_id, req.sat_per_v_byte, async (addr, amt) => { + const tx = await this.lnd.PayAddress(addr, amt, req.sat_per_v_byte, "", { useProvider: false, from: 'system' }) + this.log("paid admin invoice swap", { swapOpId: req.swap_operation_id, txId: tx.txid }) + res(tx.txid) + return { txId: tx.txid } + }) + }) + return { tx_id: txId } + } + + async ListAdminTxSwaps(): Promise { + return this.swaps.ListTxSwaps("admin", [], p => undefined, amt => 0) } async GetAdminTransactionSwapQuotes(req: Types.TransactionSwapRequest): Promise { const quotes = await this.swaps.GetTxSwapQuotes("admin", req.transaction_amount_sats, () => 0) return { quotes } } - async PayAdminTransactionSwap(req: Types.PayAdminTransactionSwapRequest): Promise { + async PayAdminTransactionSwap(req: Types.PayAdminTransactionSwapRequest): Promise { const routingFloor = this.settings.getSettings().lndSettings.routingFeeFloor const routingLimit = this.settings.getSettings().lndSettings.routingFeeLimitBps / 10000 diff --git a/src/services/main/index.ts b/src/services/main/index.ts index ab528b84..6f610878 100644 --- a/src/services/main/index.ts +++ b/src/services/main/index.ts @@ -394,6 +394,7 @@ export default class { const j = JSON.stringify(op) const encrypted = nip44.encrypt(j, ck) const encryptedData: { encrypted: string, app_npub_hex: string } = { encrypted, app_npub_hex: app.nostr_public_key } + this.notificationsManager.SendNotification(JSON.stringify(encryptedData), tokens, { pubkey: app.nostr_public_key!, privateKey: app.nostr_private_key! diff --git a/src/services/main/init.ts b/src/services/main/init.ts index 121750e3..946061fb 100644 --- a/src/services/main/init.ts +++ b/src/services/main/init.ts @@ -79,6 +79,7 @@ export const initMainHandler = async (log: PubLogger, settingsManager: SettingsM await mainHandler.paymentManager.CleanupOldUnpaidInvoices() await mainHandler.appUserManager.CleanupInactiveUsers() await mainHandler.appUserManager.CleanupNeverActiveUsers() + await swaps.ResumeInvoiceSwaps() await mainHandler.paymentManager.watchDog.Start() return { mainHandler, apps, localProviderClient, wizard, adminManager } } diff --git a/src/services/main/paymentManager.ts b/src/services/main/paymentManager.ts index 5fd04022..82610061 100644 --- a/src/services/main/paymentManager.ts +++ b/src/services/main/paymentManager.ts @@ -18,7 +18,7 @@ import { LiquidityManager } from './liquidityManager.js' import { Utils } from '../helpers/utilsWrapper.js' import { UserInvoicePayment } from '../storage/entity/UserInvoicePayment.js' import SettingsManager from './settingsManager.js' -import { Swaps, TransactionSwapData } from '../lnd/swaps/swaps.js' +import { Swaps } from '../lnd/swaps/swaps.js' import { Transaction, OutputDetail } from '../../../proto/lnd/lightning.js' import { LndAddress } from '../lnd/lnd.js' import Metrics from '../metrics/index.js' @@ -617,7 +617,7 @@ export default class { } } - async ListSwaps(ctx: Types.UserContext): Promise { + async ListTxSwaps(ctx: Types.UserContext): Promise { const payments = await this.storage.paymentStorage.ListTxSwapPayments(ctx.app_user_id) const app = await this.storage.applicationStorage.GetApplication(ctx.app_id) const isManagedUser = ctx.user_id !== app.owner.user_id diff --git a/src/services/serverMethods/index.ts b/src/services/serverMethods/index.ts index 8b9b80a3..47624db7 100644 --- a/src/services/serverMethods/index.ts +++ b/src/services/serverMethods/index.ts @@ -106,6 +106,26 @@ export default (mainHandler: Main): Types.ServerMethods => { if (err != null) throw new Error(err.message) return mainHandler.adminManager.PayAdminTransactionSwap(req) }, + ListAdminTxSwaps: async ({ ctx }) => { + return mainHandler.adminManager.ListAdminTxSwaps() + }, + GetAdminInvoiceSwapQuotes: async ({ ctx, req }) => { + const err = Types.InvoiceSwapRequestValidate(req, { + invoice_CustomCheck: invoice => invoice !== '' + }) + if (err != null) throw new Error(err.message) + return mainHandler.adminManager.GetAdminInvoiceSwapQuotes(req) + }, + ListAdminInvoiceSwaps: async ({ ctx }) => { + return mainHandler.adminManager.ListAdminInvoiceSwaps() + }, + PayAdminInvoiceSwap: async ({ ctx, req }) => { + const err = Types.PayAdminInvoiceSwapRequestValidate(req, { + swap_operation_id_CustomCheck: id => id !== '', + }) + if (err != null) throw new Error(err.message) + return mainHandler.adminManager.PayAdminInvoiceSwap(req) + }, GetProvidersDisruption: async () => { return mainHandler.metricsManager.GetProvidersDisruption() }, @@ -145,9 +165,7 @@ export default (mainHandler: Main): Types.ServerMethods => { GetUserOperations: async ({ ctx, req }) => { return mainHandler.paymentManager.GetUserOperations(ctx.user_id, req) }, - ListAdminSwaps: async ({ ctx }) => { - return mainHandler.adminManager.ListAdminSwaps() - }, + GetPaymentState: async ({ ctx, req }) => { const err = Types.GetPaymentStateRequestValidate(req, { invoice_CustomCheck: invoice => invoice !== "" @@ -165,8 +183,8 @@ export default (mainHandler: Main): Types.ServerMethods => { if (err != null) throw new Error(err.message) return mainHandler.paymentManager.PayAddress(ctx, req) }, - ListSwaps: async ({ ctx }) => { - return mainHandler.paymentManager.ListSwaps(ctx) + ListTxSwaps: async ({ ctx }) => { + return mainHandler.paymentManager.ListTxSwaps(ctx) }, GetTransactionSwapQuotes: async ({ ctx, req }) => { return mainHandler.paymentManager.GetTransactionSwapQuotes(ctx, req) diff --git a/src/services/storage/entity/InvoiceSwap.ts b/src/services/storage/entity/InvoiceSwap.ts index 4548f042..2ab18347 100644 --- a/src/services/storage/entity/InvoiceSwap.ts +++ b/src/services/storage/entity/InvoiceSwap.ts @@ -16,10 +16,16 @@ export class InvoiceSwap { swap_tree: string @Column() - lockup_address: string + claim_public_key: string @Column() - refund_public_key: string + payment_hash: string + + /* @Column() + lockup_address: string */ + + /* @Column() + refund_public_key: string */ @Column() timeout_block_height: number @@ -39,12 +45,14 @@ export class InvoiceSwap { @Column() chain_fee_sats: number - @Column() - preimage: string + @Column() ephemeral_public_key: string + @Column() + address: string + // the private key is used on to perform a swap, it does not hold any funds once the swap is completed // the swap should only last a few seconds, so it is not a security risk to store the private key in the database // the key is stored here mostly for recovery purposes, in case something goes wrong with the swap @@ -54,14 +62,17 @@ export class InvoiceSwap { @Column({ default: false }) used: boolean + @Column({ default: "" }) + preimage: string + @Column({ default: "" }) failure_reason: string @Column({ default: "" }) tx_id: string - @Column({ default: "" }) - address_paid: string + /* @Column({ default: "" }) + address_paid: string */ @Column({ default: "" }) service_url: string diff --git a/src/services/storage/migrations/1769529793283-invoice_swaps.ts b/src/services/storage/migrations/1769529793283-invoice_swaps.ts new file mode 100644 index 00000000..b32cc1de --- /dev/null +++ b/src/services/storage/migrations/1769529793283-invoice_swaps.ts @@ -0,0 +1,30 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class InvoiceSwaps1769529793283 implements MigrationInterface { + name = 'InvoiceSwaps1769529793283' + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(`CREATE TABLE "invoice_swap" ("swap_operation_id" varchar PRIMARY KEY NOT NULL, "app_user_id" varchar NOT NULL, "swap_quote_id" varchar NOT NULL, "swap_tree" varchar NOT NULL, "claim_public_key" varchar NOT NULL, "payment_hash" varchar NOT NULL, "timeout_block_height" integer NOT NULL, "invoice" varchar NOT NULL, "invoice_amount" integer NOT NULL, "transaction_amount" integer NOT NULL, "swap_fee_sats" integer NOT NULL, "chain_fee_sats" integer NOT NULL, "ephemeral_public_key" varchar NOT NULL, "address" varchar NOT NULL, "ephemeral_private_key" varchar NOT NULL, "used" boolean NOT NULL DEFAULT (0), "preimage" varchar NOT NULL DEFAULT (''), "failure_reason" varchar NOT NULL DEFAULT (''), "tx_id" varchar NOT NULL DEFAULT (''), "service_url" varchar NOT NULL DEFAULT (''), "created_at" datetime NOT NULL DEFAULT (datetime('now')), "updated_at" datetime NOT NULL DEFAULT (datetime('now')))`); + await queryRunner.query(`DROP INDEX "recv_invoice_paid_serial"`); + await queryRunner.query(`DROP INDEX "IDX_a131e6b58f084f1340538681b5"`); + await queryRunner.query(`CREATE TABLE "temporary_user_receiving_invoice" ("serial_id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "invoice" varchar NOT NULL, "expires_at_unix" integer NOT NULL, "paid_at_unix" integer NOT NULL DEFAULT (0), "internal" boolean NOT NULL DEFAULT (0), "paidByLnd" boolean NOT NULL DEFAULT (0), "callbackUrl" varchar NOT NULL DEFAULT (''), "paid_amount" integer NOT NULL DEFAULT (0), "service_fee" integer NOT NULL DEFAULT (0), "zap_info" text, "created_at" datetime NOT NULL DEFAULT (datetime('now')), "updated_at" datetime NOT NULL DEFAULT (datetime('now')), "userSerialId" integer, "productProductId" varchar, "payerSerialId" integer, "linkedApplicationSerialId" integer, "liquidityProvider" varchar, "payer_data" text, "offer_id" varchar NOT NULL DEFAULT (''), "rejectUnauthorized" boolean NOT NULL DEFAULT (1), "bearer_token" varchar NOT NULL DEFAULT (''), "clink_requester_pub" varchar, "clink_requester_event_id" varchar, CONSTRAINT "FK_2c0dfb3483f3e5e7e3cdd5dc71f" FOREIGN KEY ("userSerialId") REFERENCES "user" ("serial_id") ON DELETE NO ACTION ON UPDATE NO ACTION, CONSTRAINT "FK_5263bde2a519db9ea608b702ec8" FOREIGN KEY ("productProductId") REFERENCES "product" ("product_id") ON DELETE NO ACTION ON UPDATE NO ACTION, CONSTRAINT "FK_d4bb1e4c60e8a869f1f43ca2e31" FOREIGN KEY ("payerSerialId") REFERENCES "user" ("serial_id") ON DELETE NO ACTION ON UPDATE NO ACTION, CONSTRAINT "FK_714a8b7d4f89f8a802ca181b789" FOREIGN KEY ("linkedApplicationSerialId") REFERENCES "application" ("serial_id") ON DELETE NO ACTION ON UPDATE NO ACTION)`); + await queryRunner.query(`INSERT INTO "temporary_user_receiving_invoice"("serial_id", "invoice", "expires_at_unix", "paid_at_unix", "internal", "paidByLnd", "callbackUrl", "paid_amount", "service_fee", "zap_info", "created_at", "updated_at", "userSerialId", "productProductId", "payerSerialId", "linkedApplicationSerialId", "liquidityProvider", "payer_data", "offer_id", "rejectUnauthorized", "bearer_token", "clink_requester_pub", "clink_requester_event_id") SELECT "serial_id", "invoice", "expires_at_unix", "paid_at_unix", "internal", "paidByLnd", "callbackUrl", "paid_amount", "service_fee", "zap_info", "created_at", "updated_at", "userSerialId", "productProductId", "payerSerialId", "linkedApplicationSerialId", "liquidityProvider", "payer_data", "offer_id", "rejectUnauthorized", "bearer_token", "clink_requester_pub", "clink_requester_event_id" FROM "user_receiving_invoice"`); + await queryRunner.query(`DROP TABLE "user_receiving_invoice"`); + await queryRunner.query(`ALTER TABLE "temporary_user_receiving_invoice" RENAME TO "user_receiving_invoice"`); + await queryRunner.query(`CREATE INDEX "recv_invoice_paid_serial" ON "user_receiving_invoice" ("userSerialId", "paid_at_unix", "serial_id") WHERE paid_at_unix > 0`); + await queryRunner.query(`CREATE UNIQUE INDEX "IDX_a131e6b58f084f1340538681b5" ON "user_receiving_invoice" ("invoice") `); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`DROP INDEX "IDX_a131e6b58f084f1340538681b5"`); + await queryRunner.query(`DROP INDEX "recv_invoice_paid_serial"`); + await queryRunner.query(`ALTER TABLE "user_receiving_invoice" RENAME TO "temporary_user_receiving_invoice"`); + await queryRunner.query(`CREATE TABLE "user_receiving_invoice" ("serial_id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "invoice" varchar NOT NULL, "expires_at_unix" integer NOT NULL, "paid_at_unix" integer NOT NULL DEFAULT (0), "internal" boolean NOT NULL DEFAULT (0), "paidByLnd" boolean NOT NULL DEFAULT (0), "callbackUrl" varchar NOT NULL DEFAULT (''), "paid_amount" integer NOT NULL DEFAULT (0), "service_fee" integer NOT NULL DEFAULT (0), "zap_info" text, "created_at" datetime NOT NULL DEFAULT (datetime('now')), "updated_at" datetime NOT NULL DEFAULT (datetime('now')), "userSerialId" integer, "productProductId" varchar, "payerSerialId" integer, "linkedApplicationSerialId" integer, "liquidityProvider" varchar, "payer_data" text, "offer_id" varchar NOT NULL DEFAULT (''), "rejectUnauthorized" boolean NOT NULL DEFAULT (1), "bearer_token" varchar NOT NULL DEFAULT (''), "clink_requester_pub" varchar(64), "clink_requester_event_id" varchar(64), CONSTRAINT "FK_2c0dfb3483f3e5e7e3cdd5dc71f" FOREIGN KEY ("userSerialId") REFERENCES "user" ("serial_id") ON DELETE NO ACTION ON UPDATE NO ACTION, CONSTRAINT "FK_5263bde2a519db9ea608b702ec8" FOREIGN KEY ("productProductId") REFERENCES "product" ("product_id") ON DELETE NO ACTION ON UPDATE NO ACTION, CONSTRAINT "FK_d4bb1e4c60e8a869f1f43ca2e31" FOREIGN KEY ("payerSerialId") REFERENCES "user" ("serial_id") ON DELETE NO ACTION ON UPDATE NO ACTION, CONSTRAINT "FK_714a8b7d4f89f8a802ca181b789" FOREIGN KEY ("linkedApplicationSerialId") REFERENCES "application" ("serial_id") ON DELETE NO ACTION ON UPDATE NO ACTION)`); + await queryRunner.query(`INSERT INTO "user_receiving_invoice"("serial_id", "invoice", "expires_at_unix", "paid_at_unix", "internal", "paidByLnd", "callbackUrl", "paid_amount", "service_fee", "zap_info", "created_at", "updated_at", "userSerialId", "productProductId", "payerSerialId", "linkedApplicationSerialId", "liquidityProvider", "payer_data", "offer_id", "rejectUnauthorized", "bearer_token", "clink_requester_pub", "clink_requester_event_id") SELECT "serial_id", "invoice", "expires_at_unix", "paid_at_unix", "internal", "paidByLnd", "callbackUrl", "paid_amount", "service_fee", "zap_info", "created_at", "updated_at", "userSerialId", "productProductId", "payerSerialId", "linkedApplicationSerialId", "liquidityProvider", "payer_data", "offer_id", "rejectUnauthorized", "bearer_token", "clink_requester_pub", "clink_requester_event_id" FROM "temporary_user_receiving_invoice"`); + await queryRunner.query(`DROP TABLE "temporary_user_receiving_invoice"`); + await queryRunner.query(`CREATE UNIQUE INDEX "IDX_a131e6b58f084f1340538681b5" ON "user_receiving_invoice" ("invoice") `); + await queryRunner.query(`CREATE INDEX "recv_invoice_paid_serial" ON "user_receiving_invoice" ("userSerialId", "paid_at_unix", "serial_id") WHERE paid_at_unix > 0`); + await queryRunner.query(`DROP TABLE "invoice_swap"`); + } + +} diff --git a/src/services/storage/migrations/runner.ts b/src/services/storage/migrations/runner.ts index d14b8381..ce3f7e8d 100644 --- a/src/services/storage/migrations/runner.ts +++ b/src/services/storage/migrations/runner.ts @@ -32,6 +32,7 @@ import { TxSwapAddress1764779178945 } from './1764779178945-tx_swap_address.js' import { ClinkRequester1765497600000 } from './1765497600000-clink_requester.js' import { TrackedProviderHeight1766504040000 } from './1766504040000-tracked_provider_height.js' import { SwapsServiceUrl1768413055036 } from './1768413055036-swaps_service_url.js' +import { InvoiceSwaps1769529793283 } from './1769529793283-invoice_swaps.js' export const allMigrations = [Initial1703170309875, LspOrder1718387847693, LiquidityProvider1719335699480, LndNodeInfo1720187506189, @@ -39,7 +40,7 @@ export const allMigrations = [Initial1703170309875, LspOrder1718387847693, Liqui DebitToPub1727105758354, UserCbUrl1727112281043, UserOffer1733502626042, ManagementGrant1751307732346, ManagementGrantBanned1751989251513, InvoiceCallbackUrls1752425992291, OldSomethingLeftover1753106599604, UserReceivingInvoiceIdx1753109184611, AppUserDevice1753285173175, UserAccess1759426050669, AddBlindToUserOffer1760000000000, ApplicationAvatarUrl1761000001000, AdminSettings1761683639419, TxSwap1762890527098, - TxSwapAddress1764779178945, ClinkRequester1765497600000, TrackedProviderHeight1766504040000, SwapsServiceUrl1768413055036] + TxSwapAddress1764779178945, ClinkRequester1765497600000, TrackedProviderHeight1766504040000, SwapsServiceUrl1768413055036, InvoiceSwaps1769529793283] export const allMetricsMigrations = [LndMetrics1703170330183, ChannelRouting1709316653538, HtlcCount1724266887195, BalanceEvents1724860966825, RootOps1732566440447, RootOpsTime1745428134124, ChannelEvents1750777346411] /* export const TypeOrmMigrationRunner = async (log: PubLogger, storageManager: Storage, settings: DbSettings, arg: string | undefined): Promise => { diff --git a/src/services/storage/paymentStorage.ts b/src/services/storage/paymentStorage.ts index 090ae271..a1ffa3d1 100644 --- a/src/services/storage/paymentStorage.ts +++ b/src/services/storage/paymentStorage.ts @@ -473,20 +473,20 @@ export default class { return this.dbs.FindOne('TransactionSwap', { where: { swap_operation_id: swapOperationId, used: false, app_user_id: appUserId } }, txId) } - async FinalizeTransactionSwap(swapOperationId: string, address: string, txId: string) { + async FinalizeTransactionSwap(swapOperationId: string, address: string, chainTxId: string, txId?: string) { return this.dbs.Update('TransactionSwap', { swap_operation_id: swapOperationId }, { used: true, - tx_id: txId, + tx_id: chainTxId, address_paid: address, - }) + }, txId) } - async FailTransactionSwap(swapOperationId: string, address: string, failureReason: string) { + async FailTransactionSwap(swapOperationId: string, address: string, failureReason: string, txId?: string) { return this.dbs.Update('TransactionSwap', { swap_operation_id: swapOperationId }, { used: true, failure_reason: failureReason, address_paid: address, - }) + }, txId) } async DeleteTransactionSwap(swapOperationId: string, txId?: string) { @@ -522,7 +522,51 @@ export default class { } async GetInvoiceSwap(swapOperationId: string, appUserId: string, txId?: string) { - return this.dbs.FindOne('InvoiceSwap', { where: { swap_operation_id: swapOperationId, used: false, app_user_id: appUserId } }, txId) + const swap = await this.dbs.FindOne('InvoiceSwap', { where: { swap_operation_id: swapOperationId, used: false, app_user_id: appUserId } }, txId) + if (!swap || swap.tx_id) { + return null + } + return swap + } + + async FinalizeInvoiceSwap(swapOperationId: string, txId?: string) { + return this.dbs.Update('InvoiceSwap', { swap_operation_id: swapOperationId }, { + used: true, + }, txId) + } + + async SetInvoiceSwapTxId(swapOperationId: string, chainTxId: string, txId?: string) { + return this.dbs.Update('InvoiceSwap', { swap_operation_id: swapOperationId }, { + tx_id: chainTxId, + }, txId) + } + + async FailInvoiceSwap(swapOperationId: string, failureReason: string, txId?: string) { + return this.dbs.Update('InvoiceSwap', { swap_operation_id: swapOperationId }, { + used: true, + failure_reason: failureReason, + }, txId) + } + + async DeleteInvoiceSwap(swapOperationId: string, txId?: string) { + return this.dbs.Delete('InvoiceSwap', { swap_operation_id: swapOperationId }, txId) + } + + async DeleteExpiredInvoiceSwaps(currentHeight: number, txId?: string) { + return this.dbs.Delete('InvoiceSwap', { timeout_block_height: LessThan(currentHeight) }, txId) + } + + async ListCompletedInvoiceSwaps(appUserId: string, txId?: string) { + return this.dbs.Find('InvoiceSwap', { where: { used: true, app_user_id: appUserId } }, txId) + } + + async ListPendingInvoiceSwaps(appUserId: string, txId?: string) { + return this.dbs.Find('InvoiceSwap', { where: { used: false, app_user_id: appUserId } }, txId) + } + + async ListUnfinishedInvoiceSwaps(txId?: string) { + const swaps = await this.dbs.Find('InvoiceSwap', { where: { used: false } }, txId) + return swaps.filter(s => !s.tx_id) } } From 3b827626a6dd661096fb4cd891cf868d7da40c48 Mon Sep 17 00:00:00 2001 From: boufni95 Date: Wed, 28 Jan 2026 15:53:57 +0000 Subject: [PATCH 04/66] handle exit signal when code is null --- src/services/nostr/index.ts | 10 +++++----- src/services/storage/db/storageInterface.ts | 14 +++++++------- src/services/storage/tlv/tlvFilesStorageFactory.ts | 10 +++++----- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/services/nostr/index.ts b/src/services/nostr/index.ts index 3dce7b41..3cd90e88 100644 --- a/src/services/nostr/index.ts +++ b/src/services/nostr/index.ts @@ -18,12 +18,12 @@ export default class NostrSubprocess { this.log(ERROR, "nostr subprocess error", error) }) - this.childProcess.on("exit", (code) => { - this.log(ERROR, `nostr subprocess exited with code ${code}`) - if (!code) { + this.childProcess.on("exit", (code, signal) => { + this.log(ERROR, `nostr subprocess exited with code ${code} and signal ${signal}`) + if (code === 0) { return } - throw new Error(`nostr subprocess exited with code ${code}`) + throw new Error(`nostr subprocess exited with code ${code} and signal ${signal}`) }) this.childProcess.on("message", (message: ChildProcessResponse) => { @@ -69,6 +69,6 @@ export default class NostrSubprocess { this.sendToChildProcess({ type: 'send', data, initiator, relays }) } Stop() { - this.childProcess.kill() + this.childProcess.kill(0) } } diff --git a/src/services/storage/db/storageInterface.ts b/src/services/storage/db/storageInterface.ts index 941d9533..85b757f5 100644 --- a/src/services/storage/db/storageInterface.ts +++ b/src/services/storage/db/storageInterface.ts @@ -29,7 +29,7 @@ export class StorageInterface extends EventEmitter { private debug: boolean = false; private utils: Utils private dbType: 'main' | 'metrics' - private log = getLogger({component: 'StorageInterface'}) + private log = getLogger({ component: 'StorageInterface' }) constructor(utils: Utils) { super(); this.initializeSubprocess(); @@ -61,13 +61,13 @@ export class StorageInterface extends EventEmitter { this.isConnected = false; }); - this.process.on('exit', (code: number) => { - this.log(ERROR, `Storage processor exited with code ${code}`); + this.process.on('exit', (code: number, signal: string) => { + this.log(ERROR, `Storage processor exited with code ${code} and signal ${signal}`); this.isConnected = false; - if (!code) { + if (code === 0) { return } - throw new Error(`Storage processor exited with code ${code}`) + throw new Error(`Storage processor exited with code ${code} and signal ${signal}`) }); this.isConnected = true; @@ -179,7 +179,7 @@ export class StorageInterface extends EventEmitter { reject(new Error('Invalid storage response type')); return } - resolve(deserializeResponseData(response.data)); + resolve(deserializeResponseData(response.data)); } this.once(op.opId, responseHandler) this.process.send(this.serializeOperation(op)) @@ -205,7 +205,7 @@ export class StorageInterface extends EventEmitter { public disconnect() { if (this.process) { - this.process.kill(); + this.process.kill(0); this.isConnected = false; this.debug = false; } diff --git a/src/services/storage/tlv/tlvFilesStorageFactory.ts b/src/services/storage/tlv/tlvFilesStorageFactory.ts index 0e396703..3eb2d117 100644 --- a/src/services/storage/tlv/tlvFilesStorageFactory.ts +++ b/src/services/storage/tlv/tlvFilesStorageFactory.ts @@ -53,13 +53,13 @@ export class TlvStorageFactory extends EventEmitter { this.isConnected = false; }); - this.process.on('exit', (code: number) => { - this.log(ERROR, `Tlv Storage processor exited with code ${code}`); + this.process.on('exit', (code: number, signal: string) => { + this.log(ERROR, `Tlv Storage processor exited with code ${code} and signal ${signal}`); this.isConnected = false; - if (!code) { + if (code === 0) { return } - throw new Error(`Tlv Storage processor exited with code ${code}`) + throw new Error(`Tlv Storage processor exited with code ${code} and signal ${signal}`) }); this.isConnected = true; @@ -173,7 +173,7 @@ export class TlvStorageFactory extends EventEmitter { public disconnect() { if (this.process) { - this.process.kill(); + this.process.kill(0); this.isConnected = false; this.debug = false; } From 3255730ae22030b6e7086860408dfaed66e6c4b1 Mon Sep 17 00:00:00 2001 From: boufni95 Date: Fri, 30 Jan 2026 20:37:44 +0000 Subject: [PATCH 05/66] swap refunds --- datasource.js | 5 +- proto/autogenerated/client.md | 17 ++ proto/autogenerated/go/http_client.go | 30 ++ proto/autogenerated/go/types.go | 5 + proto/autogenerated/ts/express_server.ts | 22 ++ proto/autogenerated/ts/http_client.ts | 14 + proto/autogenerated/ts/nostr_client.ts | 15 + proto/autogenerated/ts/nostr_transport.ts | 16 + proto/autogenerated/ts/types.ts | 41 ++- proto/service/methods.proto | 7 + proto/service/structs.proto | 6 + src/services/lnd/lnd.ts | 9 +- src/services/lnd/swaps/reverseSwaps.ts | 2 +- src/services/lnd/swaps/submarineSwaps.ts | 277 +++++++++++++++++- src/services/lnd/swaps/swaps.ts | 30 ++ src/services/main/adminManager.ts | 24 ++ src/services/storage/entity/InvoiceSwap.ts | 3 + .../migrations/1769529793283-invoice_swaps.ts | 16 - .../1769805357459-invoice_swaps_fixes.ts | 21 ++ src/services/storage/migrations/runner.ts | 4 +- src/services/storage/paymentStorage.ts | 23 +- 21 files changed, 554 insertions(+), 33 deletions(-) create mode 100644 src/services/storage/migrations/1769805357459-invoice_swaps_fixes.ts diff --git a/datasource.js b/datasource.js index ae243ada..081634d8 100644 --- a/datasource.js +++ b/datasource.js @@ -49,6 +49,7 @@ import { TxSwapAddress1764779178945 } from './build/src/services/storage/migrati import { ClinkRequester1765497600000 } from './build/src/services/storage/migrations/1765497600000-clink_requester.js' import { TrackedProviderHeight1766504040000 } from './build/src/services/storage/migrations/1766504040000-tracked_provider_height.js' import { SwapsServiceUrl1768413055036 } from './build/src/services/storage/migrations/1768413055036-swaps_service_url.js' +import { InvoiceSwaps1769529793283 } from './build/src/services/storage/migrations/1769529793283-invoice_swaps.js' export default new DataSource({ type: "better-sqlite3", @@ -58,11 +59,11 @@ export default new DataSource({ PaymentIndex1721760297610, DebitAccess1726496225078, DebitAccessFixes1726685229264, DebitToPub1727105758354, UserCbUrl1727112281043, UserOffer1733502626042, ManagementGrant1751307732346, InvoiceCallbackUrls1752425992291, OldSomethingLeftover1753106599604, UserReceivingInvoiceIdx1753109184611, AppUserDevice1753285173175, UserAccess1759426050669, AddBlindToUserOffer1760000000000, ApplicationAvatarUrl1761000001000, AdminSettings1761683639419, TxSwap1762890527098, - TxSwapAddress1764779178945, ClinkRequester1765497600000, TrackedProviderHeight1766504040000, SwapsServiceUrl1768413055036], + TxSwapAddress1764779178945, ClinkRequester1765497600000, TrackedProviderHeight1766504040000, SwapsServiceUrl1768413055036, InvoiceSwaps1769529793283], entities: [User, UserReceivingInvoice, UserReceivingAddress, AddressReceivingTransaction, UserInvoicePayment, UserTransactionPayment, UserBasicAuth, UserEphemeralKey, Product, UserToUserPayment, Application, ApplicationUser, UserToUserPayment, LspOrder, LndNodeInfo, TrackedProvider, InviteToken, DebitAccess, UserOffer, ManagementGrant, AppUserDevice, UserAccess, AdminSettings, TransactionSwap, InvoiceSwap], // synchronize: true, }) -//npx typeorm migration:generate ./src/services/storage/migrations/invoice_swaps -d ./datasource.js \ No newline at end of file +//npx typeorm migration:generate ./src/services/storage/migrations/invoice_swaps_fixes -d ./datasource.js \ No newline at end of file diff --git a/proto/autogenerated/client.md b/proto/autogenerated/client.md index 774ed9cd..60dd284e 100644 --- a/proto/autogenerated/client.md +++ b/proto/autogenerated/client.md @@ -320,6 +320,11 @@ The nostr server will send back a message response, and inside the body there wi - This methods has an __empty__ __request__ body - This methods has an __empty__ __response__ body +- RefundAdminInvoiceSwap + - auth type: __Admin__ + - input: [RefundAdminInvoiceSwapRequest](#RefundAdminInvoiceSwapRequest) + - output: [AdminInvoiceSwapResponse](#AdminInvoiceSwapResponse) + - ResetDebit - auth type: __User__ - input: [DebitOperation](#DebitOperation) @@ -963,6 +968,13 @@ The nostr server will send back a message response, and inside the body there wi - This methods has an __empty__ __request__ body - This methods has an __empty__ __response__ body +- RefundAdminInvoiceSwap + - auth type: __Admin__ + - http method: __post__ + - http route: __/api/admin/swap/invoice/refund__ + - input: [RefundAdminInvoiceSwapRequest](#RefundAdminInvoiceSwapRequest) + - output: [AdminInvoiceSwapResponse](#AdminInvoiceSwapResponse) + - RequestNPubLinkingToken - auth type: __App__ - http method: __post__ @@ -1603,6 +1615,7 @@ The nostr server will send back a message response, and inside the body there wi - __txId__: _string_ ### PayAdminInvoiceSwapRequest + - __no_claim__: _boolean_ *this field is optional - __sat_per_v_byte__: _number_ - __swap_operation_id__: _string_ @@ -1656,6 +1669,10 @@ The nostr server will send back a message response, and inside the body there wi ### ProvidersDisruption - __disruptions__: ARRAY of: _[ProviderDisruption](#ProviderDisruption)_ +### RefundAdminInvoiceSwapRequest + - __sat_per_v_byte__: _number_ + - __swap_operation_id__: _string_ + ### RelaysMigration - __relays__: ARRAY of: _string_ diff --git a/proto/autogenerated/go/http_client.go b/proto/autogenerated/go/http_client.go index a010fd82..98c9c648 100644 --- a/proto/autogenerated/go/http_client.go +++ b/proto/autogenerated/go/http_client.go @@ -130,6 +130,7 @@ type Client struct { PayAppUserInvoice func(req PayAppUserInvoiceRequest) (*PayInvoiceResponse, error) PayInvoice func(req PayInvoiceRequest) (*PayInvoiceResponse, error) PingSubProcesses func() error + RefundAdminInvoiceSwap func(req RefundAdminInvoiceSwapRequest) (*AdminInvoiceSwapResponse, error) RequestNPubLinkingToken func(req RequestNPubLinkingTokenRequest) (*RequestNPubLinkingTokenResponse, error) ResetDebit func(req DebitOperation) error ResetManage func(req ManageOperation) error @@ -2087,6 +2088,35 @@ func NewClient(params ClientParams) *Client { } return nil }, + RefundAdminInvoiceSwap: func(req RefundAdminInvoiceSwapRequest) (*AdminInvoiceSwapResponse, error) { + auth, err := params.RetrieveAdminAuth() + if err != nil { + return nil, err + } + finalRoute := "/api/admin/swap/invoice/refund" + body, err := json.Marshal(req) + if err != nil { + return nil, err + } + resBody, err := doPostRequest(params.BaseURL+finalRoute, body, auth) + if err != nil { + return nil, err + } + result := ResultError{} + err = json.Unmarshal(resBody, &result) + if err != nil { + return nil, err + } + if result.Status == "ERROR" { + return nil, fmt.Errorf(result.Reason) + } + res := AdminInvoiceSwapResponse{} + err = json.Unmarshal(resBody, &res) + if err != nil { + return nil, err + } + return &res, nil + }, RequestNPubLinkingToken: func(req RequestNPubLinkingTokenRequest) (*RequestNPubLinkingTokenResponse, error) { auth, err := params.RetrieveAppAuth() if err != nil { diff --git a/proto/autogenerated/go/types.go b/proto/autogenerated/go/types.go index f1d45300..d5b21b2f 100644 --- a/proto/autogenerated/go/types.go +++ b/proto/autogenerated/go/types.go @@ -592,6 +592,7 @@ type PayAddressResponse struct { Txid string `json:"txId"` } type PayAdminInvoiceSwapRequest struct { + No_claim bool `json:"no_claim"` Sat_per_v_byte int64 `json:"sat_per_v_byte"` Swap_operation_id string `json:"swap_operation_id"` } @@ -645,6 +646,10 @@ type ProviderDisruption struct { type ProvidersDisruption struct { Disruptions []ProviderDisruption `json:"disruptions"` } +type RefundAdminInvoiceSwapRequest struct { + Sat_per_v_byte int64 `json:"sat_per_v_byte"` + Swap_operation_id string `json:"swap_operation_id"` +} type RelaysMigration struct { Relays []string `json:"relays"` } diff --git a/proto/autogenerated/ts/express_server.ts b/proto/autogenerated/ts/express_server.ts index 8ce0aa96..03ff728a 100644 --- a/proto/autogenerated/ts/express_server.ts +++ b/proto/autogenerated/ts/express_server.ts @@ -1941,6 +1941,28 @@ export default (methods: Types.ServerMethods, opts: ServerOptions) => { opts.metricsCallback([{ ...info, ...stats, ...authContext }]) } catch (ex) { const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback); if (opts.throwErrors) throw e } }) + if (!opts.allowNotImplementedMethods && !methods.RefundAdminInvoiceSwap) throw new Error('method: RefundAdminInvoiceSwap is not implemented') + app.post('/api/admin/swap/invoice/refund', async (req, res) => { + const info: Types.RequestInfo = { rpcName: 'RefundAdminInvoiceSwap', batch: false, nostr: false, batchSize: 0} + const stats: Types.RequestStats = { startMs:req.startTimeMs || 0, start:req.startTime || 0n, parse: process.hrtime.bigint(), guard: 0n, validate: 0n, handle: 0n } + let authCtx: Types.AuthContext = {} + try { + if (!methods.RefundAdminInvoiceSwap) throw new Error('method: RefundAdminInvoiceSwap is not implemented') + const authContext = await opts.AdminAuthGuard(req.headers['authorization']) + authCtx = authContext + stats.guard = process.hrtime.bigint() + const request = req.body + const error = Types.RefundAdminInvoiceSwapRequestValidate(request) + stats.validate = process.hrtime.bigint() + if (error !== null) return logErrorAndReturnResponse(error, 'invalid request body', res, logger, { ...info, ...stats, ...authContext }, opts.metricsCallback) + const query = req.query + const params = req.params + const response = await methods.RefundAdminInvoiceSwap({rpcName:'RefundAdminInvoiceSwap', ctx:authContext , req: request}) + stats.handle = process.hrtime.bigint() + res.json({status: 'OK', ...response}) + opts.metricsCallback([{ ...info, ...stats, ...authContext }]) + } catch (ex) { const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback); if (opts.throwErrors) throw e } + }) if (!opts.allowNotImplementedMethods && !methods.RequestNPubLinkingToken) throw new Error('method: RequestNPubLinkingToken is not implemented') app.post('/api/app/user/npub/token', async (req, res) => { const info: Types.RequestInfo = { rpcName: 'RequestNPubLinkingToken', batch: false, nostr: false, batchSize: 0} diff --git a/proto/autogenerated/ts/http_client.ts b/proto/autogenerated/ts/http_client.ts index e84470eb..195737be 100644 --- a/proto/autogenerated/ts/http_client.ts +++ b/proto/autogenerated/ts/http_client.ts @@ -1004,6 +1004,20 @@ export default (params: ClientParams) => ({ } return { status: 'ERROR', reason: 'invalid response' } }, + RefundAdminInvoiceSwap: async (request: Types.RefundAdminInvoiceSwapRequest): Promise => { + const auth = await params.retrieveAdminAuth() + if (auth === null) throw new Error('retrieveAdminAuth() returned null') + let finalRoute = '/api/admin/swap/invoice/refund' + const { data } = await axios.post(params.baseUrl + finalRoute, request, { headers: { 'authorization': auth } }) + if (data.status === 'ERROR' && typeof data.reason === 'string') return data + if (data.status === 'OK') { + const result = data + if(!params.checkResult) return { status: 'OK', ...result } + const error = Types.AdminInvoiceSwapResponseValidate(result) + if (error === null) { return { status: 'OK', ...result } } else return { status: 'ERROR', reason: error.message } + } + return { status: 'ERROR', reason: 'invalid response' } + }, RequestNPubLinkingToken: async (request: Types.RequestNPubLinkingTokenRequest): Promise => { const auth = await params.retrieveAppAuth() if (auth === null) throw new Error('retrieveAppAuth() returned null') diff --git a/proto/autogenerated/ts/nostr_client.ts b/proto/autogenerated/ts/nostr_client.ts index 2db7e8ce..d174d247 100644 --- a/proto/autogenerated/ts/nostr_client.ts +++ b/proto/autogenerated/ts/nostr_client.ts @@ -883,6 +883,21 @@ export default (params: NostrClientParams, send: (to:string, message: NostrRequ } return { status: 'ERROR', reason: 'invalid response' } }, + RefundAdminInvoiceSwap: async (request: Types.RefundAdminInvoiceSwapRequest): Promise => { + const auth = await params.retrieveNostrAdminAuth() + if (auth === null) throw new Error('retrieveNostrAdminAuth() returned null') + const nostrRequest: NostrRequest = {} + nostrRequest.body = request + const data = await send(params.pubDestination, {rpcName:'RefundAdminInvoiceSwap',authIdentifier:auth, ...nostrRequest }) + if (data.status === 'ERROR' && typeof data.reason === 'string') return data + if (data.status === 'OK') { + const result = data + if(!params.checkResult) return { status: 'OK', ...result } + const error = Types.AdminInvoiceSwapResponseValidate(result) + if (error === null) { return { status: 'OK', ...result } } else return { status: 'ERROR', reason: error.message } + } + return { status: 'ERROR', reason: 'invalid response' } + }, ResetDebit: async (request: Types.DebitOperation): Promise => { const auth = await params.retrieveNostrUserAuth() if (auth === null) throw new Error('retrieveNostrUserAuth() returned null') diff --git a/proto/autogenerated/ts/nostr_transport.ts b/proto/autogenerated/ts/nostr_transport.ts index 8a586d5b..4f9307b3 100644 --- a/proto/autogenerated/ts/nostr_transport.ts +++ b/proto/autogenerated/ts/nostr_transport.ts @@ -1344,6 +1344,22 @@ export default (methods: Types.ServerMethods, opts: NostrOptions) => { opts.metricsCallback([{ ...info, ...stats, ...authContext }]) }catch(ex){ const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback); if (opts.throwErrors) throw e } break + case 'RefundAdminInvoiceSwap': + try { + if (!methods.RefundAdminInvoiceSwap) throw new Error('method: RefundAdminInvoiceSwap is not implemented') + const authContext = await opts.NostrAdminAuthGuard(req.appId, req.authIdentifier) + stats.guard = process.hrtime.bigint() + authCtx = authContext + const request = req.body + const error = Types.RefundAdminInvoiceSwapRequestValidate(request) + stats.validate = process.hrtime.bigint() + if (error !== null) return logErrorAndReturnResponse(error, 'invalid request body', res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback) + const response = await methods.RefundAdminInvoiceSwap({rpcName:'RefundAdminInvoiceSwap', ctx:authContext , req: request}) + stats.handle = process.hrtime.bigint() + res({status: 'OK', ...response}) + opts.metricsCallback([{ ...info, ...stats, ...authContext }]) + }catch(ex){ const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback); if (opts.throwErrors) throw e } + break case 'ResetDebit': try { if (!methods.ResetDebit) throw new Error('method: ResetDebit is not implemented') diff --git a/proto/autogenerated/ts/types.ts b/proto/autogenerated/ts/types.ts index 78add454..a738a06c 100644 --- a/proto/autogenerated/ts/types.ts +++ b/proto/autogenerated/ts/types.ts @@ -7,8 +7,8 @@ export type RequestMetric = AuthContext & RequestInfo & RequestStats & { error?: export type AdminContext = { admin_id: string } -export type AdminMethodInputs = AddApp_Input | AddPeer_Input | AuthApp_Input | BanUser_Input | CloseChannel_Input | CreateOneTimeInviteLink_Input | GetAdminInvoiceSwapQuotes_Input | GetAdminTransactionSwapQuotes_Input | GetInviteLinkState_Input | GetSeed_Input | ListAdminInvoiceSwaps_Input | ListAdminTxSwaps_Input | ListChannels_Input | LndGetInfo_Input | OpenChannel_Input | PayAdminInvoiceSwap_Input | PayAdminTransactionSwap_Input | UpdateChannelPolicy_Input -export type AdminMethodOutputs = AddApp_Output | AddPeer_Output | AuthApp_Output | BanUser_Output | CloseChannel_Output | CreateOneTimeInviteLink_Output | GetAdminInvoiceSwapQuotes_Output | GetAdminTransactionSwapQuotes_Output | GetInviteLinkState_Output | GetSeed_Output | ListAdminInvoiceSwaps_Output | ListAdminTxSwaps_Output | ListChannels_Output | LndGetInfo_Output | OpenChannel_Output | PayAdminInvoiceSwap_Output | PayAdminTransactionSwap_Output | UpdateChannelPolicy_Output +export type AdminMethodInputs = AddApp_Input | AddPeer_Input | AuthApp_Input | BanUser_Input | CloseChannel_Input | CreateOneTimeInviteLink_Input | GetAdminInvoiceSwapQuotes_Input | GetAdminTransactionSwapQuotes_Input | GetInviteLinkState_Input | GetSeed_Input | ListAdminInvoiceSwaps_Input | ListAdminTxSwaps_Input | ListChannels_Input | LndGetInfo_Input | OpenChannel_Input | PayAdminInvoiceSwap_Input | PayAdminTransactionSwap_Input | RefundAdminInvoiceSwap_Input | UpdateChannelPolicy_Input +export type AdminMethodOutputs = AddApp_Output | AddPeer_Output | AuthApp_Output | BanUser_Output | CloseChannel_Output | CreateOneTimeInviteLink_Output | GetAdminInvoiceSwapQuotes_Output | GetAdminTransactionSwapQuotes_Output | GetInviteLinkState_Output | GetSeed_Output | ListAdminInvoiceSwaps_Output | ListAdminTxSwaps_Output | ListChannels_Output | LndGetInfo_Output | OpenChannel_Output | PayAdminInvoiceSwap_Output | PayAdminTransactionSwap_Output | RefundAdminInvoiceSwap_Output | UpdateChannelPolicy_Output export type AppContext = { app_id: string } @@ -289,6 +289,9 @@ export type PayInvoice_Output = ResultError | ({ status: 'OK' } & PayInvoiceResp export type PingSubProcesses_Input = {rpcName:'PingSubProcesses'} export type PingSubProcesses_Output = ResultError | { status: 'OK' } +export type RefundAdminInvoiceSwap_Input = {rpcName:'RefundAdminInvoiceSwap', req: RefundAdminInvoiceSwapRequest} +export type RefundAdminInvoiceSwap_Output = ResultError | ({ status: 'OK' } & AdminInvoiceSwapResponse) + export type RequestNPubLinkingToken_Input = {rpcName:'RequestNPubLinkingToken', req: RequestNPubLinkingTokenRequest} export type RequestNPubLinkingToken_Output = ResultError | ({ status: 'OK' } & RequestNPubLinkingTokenResponse) @@ -422,6 +425,7 @@ export type ServerMethods = { PayAppUserInvoice?: (req: PayAppUserInvoice_Input & {ctx: AppContext }) => Promise PayInvoice?: (req: PayInvoice_Input & {ctx: UserContext }) => Promise PingSubProcesses?: (req: PingSubProcesses_Input & {ctx: MetricsContext }) => Promise + RefundAdminInvoiceSwap?: (req: RefundAdminInvoiceSwap_Input & {ctx: AdminContext }) => Promise RequestNPubLinkingToken?: (req: RequestNPubLinkingToken_Input & {ctx: AppContext }) => Promise ResetDebit?: (req: ResetDebit_Input & {ctx: UserContext }) => Promise ResetManage?: (req: ResetManage_Input & {ctx: UserContext }) => Promise @@ -3518,12 +3522,15 @@ export const PayAddressResponseValidate = (o?: PayAddressResponse, opts: PayAddr } export type PayAdminInvoiceSwapRequest = { + no_claim?: boolean sat_per_v_byte: number swap_operation_id: string } -export const PayAdminInvoiceSwapRequestOptionalFields: [] = [] +export type PayAdminInvoiceSwapRequestOptionalField = 'no_claim' +export const PayAdminInvoiceSwapRequestOptionalFields: PayAdminInvoiceSwapRequestOptionalField[] = ['no_claim'] export type PayAdminInvoiceSwapRequestOptions = OptionsBaseMessage & { - checkOptionalsAreSet?: [] + checkOptionalsAreSet?: PayAdminInvoiceSwapRequestOptionalField[] + no_claim_CustomCheck?: (v?: boolean) => boolean sat_per_v_byte_CustomCheck?: (v: number) => boolean swap_operation_id_CustomCheck?: (v: string) => boolean } @@ -3531,6 +3538,9 @@ export const PayAdminInvoiceSwapRequestValidate = (o?: PayAdminInvoiceSwapReques if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message') if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null') + if ((o.no_claim || opts.allOptionalsAreSet || opts.checkOptionalsAreSet?.includes('no_claim')) && typeof o.no_claim !== 'boolean') return new Error(`${path}.no_claim: is not a boolean`) + if (opts.no_claim_CustomCheck && !opts.no_claim_CustomCheck(o.no_claim)) return new Error(`${path}.no_claim: custom check failed`) + if (typeof o.sat_per_v_byte !== 'number') return new Error(`${path}.sat_per_v_byte: is not a number`) if (opts.sat_per_v_byte_CustomCheck && !opts.sat_per_v_byte_CustomCheck(o.sat_per_v_byte)) return new Error(`${path}.sat_per_v_byte: custom check failed`) @@ -3832,6 +3842,29 @@ export const ProvidersDisruptionValidate = (o?: ProvidersDisruption, opts: Provi return null } +export type RefundAdminInvoiceSwapRequest = { + sat_per_v_byte: number + swap_operation_id: string +} +export const RefundAdminInvoiceSwapRequestOptionalFields: [] = [] +export type RefundAdminInvoiceSwapRequestOptions = OptionsBaseMessage & { + checkOptionalsAreSet?: [] + sat_per_v_byte_CustomCheck?: (v: number) => boolean + swap_operation_id_CustomCheck?: (v: string) => boolean +} +export const RefundAdminInvoiceSwapRequestValidate = (o?: RefundAdminInvoiceSwapRequest, opts: RefundAdminInvoiceSwapRequestOptions = {}, path: string = 'RefundAdminInvoiceSwapRequest::root.'): Error | null => { + if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message') + if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null') + + if (typeof o.sat_per_v_byte !== 'number') return new Error(`${path}.sat_per_v_byte: is not a number`) + if (opts.sat_per_v_byte_CustomCheck && !opts.sat_per_v_byte_CustomCheck(o.sat_per_v_byte)) return new Error(`${path}.sat_per_v_byte: custom check failed`) + + if (typeof o.swap_operation_id !== 'string') return new Error(`${path}.swap_operation_id: is not a string`) + if (opts.swap_operation_id_CustomCheck && !opts.swap_operation_id_CustomCheck(o.swap_operation_id)) return new Error(`${path}.swap_operation_id: custom check failed`) + + return null +} + export type RelaysMigration = { relays: string[] } diff --git a/proto/service/methods.proto b/proto/service/methods.proto index 15292e37..3eeef126 100644 --- a/proto/service/methods.proto +++ b/proto/service/methods.proto @@ -196,6 +196,13 @@ service LightningPub { option (nostr) = true; } + rpc RefundAdminInvoiceSwap(structs.RefundAdminInvoiceSwapRequest) returns (structs.AdminInvoiceSwapResponse) { + option (auth_type) = "Admin"; + option (http_method) = "post"; + option (http_route) = "/api/admin/swap/invoice/refund"; + option (nostr) = true; + } + rpc GetAdminTransactionSwapQuotes(structs.TransactionSwapRequest) returns (structs.TransactionSwapQuoteList) { option (auth_type) = "Admin"; option (http_method) = "post"; diff --git a/proto/service/structs.proto b/proto/service/structs.proto index e93e6691..5b25c699 100644 --- a/proto/service/structs.proto +++ b/proto/service/structs.proto @@ -867,9 +867,15 @@ message InvoiceSwapsList { repeated InvoiceSwapQuote quotes = 2; } +message RefundAdminInvoiceSwapRequest { + string swap_operation_id = 1; + int64 sat_per_v_byte = 2; +} + message PayAdminInvoiceSwapRequest { string swap_operation_id = 1; int64 sat_per_v_byte = 2; + optional bool no_claim = 3; } message AdminInvoiceSwapResponse { diff --git a/src/services/lnd/lnd.ts b/src/services/lnd/lnd.ts index daf7b411..e1f8ed1b 100644 --- a/src/services/lnd/lnd.ts +++ b/src/services/lnd/lnd.ts @@ -23,7 +23,7 @@ import { TxPointSettings } from '../storage/tlv/stateBundler.js'; import { WalletKitClient } from '../../../proto/lnd/walletkit.client.js'; import SettingsManager from '../main/settingsManager.js'; import { LndNodeSettings, LndSettings } from '../main/settings.js'; -import { ListAddressesResponse } from '../../../proto/lnd/walletkit.js'; +import { ListAddressesResponse, PublishResponse } from '../../../proto/lnd/walletkit.js'; const DeadLineMetadata = (deadline = 10 * 1000) => ({ deadline: Date.now() + deadline }) const deadLndRetrySeconds = 20 @@ -156,6 +156,13 @@ export default class { }) } + async PublishTransaction(txHex: string): Promise { + const res = await this.walletKit.publishTransaction({ + txHex: Buffer.from(txHex, 'hex'), label: "" + }, DeadLineMetadata()) + return res.response + } + async GetInfo(): Promise { if (this.liquidProvider.getSettings().useOnlyLiquidityProvider) { // Return dummy info when bypass is enabled diff --git a/src/services/lnd/swaps/reverseSwaps.ts b/src/services/lnd/swaps/reverseSwaps.ts index 4510389b..f0a5bc03 100644 --- a/src/services/lnd/swaps/reverseSwaps.ts +++ b/src/services/lnd/swaps/reverseSwaps.ts @@ -3,7 +3,7 @@ import { initEccLib, Transaction, address } from 'bitcoinjs-lib'; // import bolt11 from 'bolt11'; import { Musig, SwapTreeSerializer, TaprootUtils, detectSwap, - constructClaimTransaction, OutputType, + constructClaimTransaction, OutputType, constructRefundTransaction } from 'boltz-core'; import { randomBytes, createHash } from 'crypto'; import { ECPairFactory, ECPairInterface } from 'ecpair'; diff --git a/src/services/lnd/swaps/submarineSwaps.ts b/src/services/lnd/swaps/submarineSwaps.ts index ffbb8545..bf223b3e 100644 --- a/src/services/lnd/swaps/submarineSwaps.ts +++ b/src/services/lnd/swaps/submarineSwaps.ts @@ -1,14 +1,16 @@ import zkpInit from '@vulpemventures/secp256k1-zkp'; // import bolt11 from 'bolt11'; import { - Musig, SwapTreeSerializer, TaprootUtils + Musig, SwapTreeSerializer, TaprootUtils, constructRefundTransaction, + detectSwap, OutputType } from 'boltz-core'; import { randomBytes, createHash } from 'crypto'; import { ECPairFactory, ECPairInterface } from 'ecpair'; import * as ecc from 'tiny-secp256k1'; +import { Transaction, address } from 'bitcoinjs-lib'; import ws from 'ws'; import { getLogger, PubLogger, ERROR } from '../../helpers/logger.js'; -import { loggedGet, loggedPost } from './swapHelpers.js'; +import { loggedGet, loggedPost, getNetwork } from './swapHelpers.js'; import { BTCNetwork } from '../../main/settings.js'; /* type InvoiceSwapFees = { @@ -47,10 +49,12 @@ export type InvoiceSwapData = { createdResponse: InvoiceSwapResponse, info: Invo export class SubmarineSwaps { private httpUrl: string private wsUrl: string + private network: BTCNetwork log: PubLogger - constructor({ httpUrl, wsUrl }: { httpUrl: string, wsUrl: string, network: BTCNetwork }) { + constructor({ httpUrl, wsUrl, network }: { httpUrl: string, wsUrl: string, network: BTCNetwork }) { this.httpUrl = httpUrl this.wsUrl = wsUrl + this.network = network this.log = getLogger({ component: 'SubmarineSwaps' }) } @@ -97,6 +101,273 @@ export class SubmarineSwaps { } + /** + * Get the lockup transaction for a swap from Boltz + */ + private getLockupTransaction = async (swapId: string): Promise<{ ok: true, data: { hex: string } } | { ok: false, error: string }> => { + const url = `${this.httpUrl}/v2/swap/submarine/${swapId}/transaction` + return await loggedGet<{ hex: string }>(this.log, url) + } + + /** + * Get partial refund signature from Boltz for cooperative refund + */ + private getPartialRefundSignature = async ( + swapId: string, + pubNonce: Buffer, + transaction: Transaction, + index: number + ): Promise<{ ok: true, data: { pubNonce: string, partialSignature: string } } | { ok: false, error: string }> => { + const url = `${this.httpUrl}/v2/swap/submarine/${swapId}/refund` + const req = { + index, + pubNonce: pubNonce.toString('hex'), + transaction: transaction.toHex() + } + return await loggedPost<{ pubNonce: string, partialSignature: string }>(this.log, url, req) + } + + /** + * Constructs a Taproot refund transaction (cooperative or uncooperative) + */ + private constructTaprootRefund = async ( + swapId: string, + claimPublicKey: string, + swapTree: string, + timeoutBlockHeight: number, + lockupTx: Transaction, + privateKey: ECPairInterface, + refundAddress: string, + feePerVbyte: number, + cooperative: boolean = true + ): Promise<{ + ok: true, + transaction: Transaction, + cooperativeError?: string + } | { + ok: false, + error: string + }> => { + this.log(`Constructing ${cooperative ? 'cooperative' : 'uncooperative'} Taproot refund for swap ${swapId}`) + + const boltzPublicKey = Buffer.from(claimPublicKey, 'hex') + const swapTreeDeserialized = SwapTreeSerializer.deserializeSwapTree(swapTree) + + // Create musig and tweak it + let musig = new Musig(await zkpInit(), privateKey, randomBytes(32), [ + boltzPublicKey, + Buffer.from(privateKey.publicKey), + ]) + const tweakedKey = TaprootUtils.tweakMusig(musig, swapTreeDeserialized.tree) + + // Detect the swap output in the lockup transaction + const swapOutput = detectSwap(tweakedKey, lockupTx) + if (!swapOutput) { + return { ok: false, error: 'Could not detect swap output in lockup transaction' } + } + + const network = getNetwork(this.network) + // const decodedAddress = address.fromBech32(refundAddress) + + const details = [ + { + ...swapOutput, + keys: privateKey, + cooperative, + type: OutputType.Taproot, + txHash: lockupTx.getHash(), + swapTree: swapTreeDeserialized, + internalKey: musig.getAggregatedPublicKey(), + } + ] + const outputScript = address.toOutputScript(refundAddress, network) + // Construct the refund transaction + const refundTx = constructRefundTransaction( + details, + outputScript, + cooperative ? 0 : timeoutBlockHeight, + feePerVbyte, + true + ) + + if (!cooperative) { + return { ok: true, transaction: refundTx } + } + + // For cooperative refund, get Boltz's partial signature + try { + musig = new Musig(await zkpInit(), privateKey, randomBytes(32), [ + boltzPublicKey, + Buffer.from(privateKey.publicKey), + ]) + // Get the partial signature from Boltz + const boltzSigRes = await this.getPartialRefundSignature( + swapId, + Buffer.from(musig.getPublicNonce()), + refundTx, + 0 + ) + + if (!boltzSigRes.ok) { + this.log(ERROR, 'Failed to get Boltz partial signature, falling back to uncooperative refund') + // Fallback to uncooperative refund + return await this.constructTaprootRefund( + swapId, + claimPublicKey, + swapTree, + timeoutBlockHeight, + lockupTx, + privateKey, + refundAddress, + feePerVbyte, + false + ) + } + + const boltzSig = boltzSigRes.data + + // Aggregate nonces + musig.aggregateNonces([ + [boltzPublicKey, Musig.parsePubNonce(boltzSig.pubNonce)], + ]) + + // Tweak musig again after aggregating nonces + TaprootUtils.tweakMusig(musig, swapTreeDeserialized.tree) + + // Initialize session and sign + musig.initializeSession( + TaprootUtils.hashForWitnessV1( + details, + refundTx, + 0 + ) + ) + + musig.signPartial() + musig.addPartial(boltzPublicKey, Buffer.from(boltzSig.partialSignature, 'hex')) + + // Set the witness to the aggregated signature + refundTx.ins[0].witness = [musig.aggregatePartials()] + + return { ok: true, transaction: refundTx } + } catch (error: any) { + this.log(ERROR, 'Cooperative refund failed:', error.message) + // Fallback to uncooperative refund + return await this.constructTaprootRefund( + swapId, + claimPublicKey, + swapTree, + timeoutBlockHeight, + lockupTx, + privateKey, + refundAddress, + feePerVbyte, + false + ) + } + } + + /** + * Broadcasts a refund transaction + */ + private broadcastRefundTransaction = async (transaction: Transaction): Promise<{ ok: true, txId: string } | { ok: false, error: string }> => { + const url = `${this.httpUrl}/v2/chain/BTC/transaction` + const req = { hex: transaction.toHex() } + + const result = await loggedPost<{ id: string }>(this.log, url, req) + if (!result.ok) { + return result + } + + return { ok: true, txId: result.data.id } + } + + /** + * Refund a submarine swap + * @param swapId - The swap ID + * @param claimPublicKey - Boltz's claim public key + * @param swapTree - The swap tree + * @param timeoutBlockHeight - The timeout block height + * @param privateKey - The refund private key (hex string) + * @param refundAddress - The address to refund to + * @param currentHeight - The current block height + * @param lockupTxHex - The lockup transaction hex (optional, will fetch from Boltz if not provided) + * @param feePerVbyte - Fee rate in sat/vbyte (optional, will use default if not provided) + */ + RefundSwap = async (params: { + swapId: string, + claimPublicKey: string, + swapTree: string, + timeoutBlockHeight: number, + privateKeyHex: string, + refundAddress: string, + currentHeight: number, + lockupTxHex?: string, + feePerVbyte?: number + }): Promise<{ ok: true, publish: { done: false, txHex: string, txId: string } | { done: true, txId: string } } | { ok: false, error: string }> => { + const { swapId, claimPublicKey, swapTree, timeoutBlockHeight, privateKeyHex, refundAddress, currentHeight, lockupTxHex, feePerVbyte = 2 } = params + + this.log('Starting refund process for swap:', swapId) + + // Get the lockup transaction (from parameter or fetch from Boltz) + let lockupTx: Transaction + if (lockupTxHex) { + this.log('Using provided lockup transaction hex') + lockupTx = Transaction.fromHex(lockupTxHex) + } else { + this.log('Fetching lockup transaction from Boltz') + const lockupTxRes = await this.getLockupTransaction(swapId) + if (!lockupTxRes.ok) { + return { ok: false, error: `Failed to get lockup transaction: ${lockupTxRes.error}` } + } + lockupTx = Transaction.fromHex(lockupTxRes.data.hex) + } + this.log('Lockup transaction retrieved:', lockupTx.getId()) + + // Check if swap has timed out + if (currentHeight < timeoutBlockHeight) { + return { + ok: false, + error: `Swap has not timed out yet. Current height: ${currentHeight}, timeout: ${timeoutBlockHeight}` + } + } + this.log(`Swap has timed out. Current height: ${currentHeight}, timeout: ${timeoutBlockHeight}`) + + // Parse the private key + const privateKey = ECPairFactory(ecc).fromPrivateKey(Buffer.from(privateKeyHex, 'hex')) + + // Construct the refund transaction (tries cooperative first, then falls back to uncooperative) + const refundTxRes = await this.constructTaprootRefund( + swapId, + claimPublicKey, + swapTree, + timeoutBlockHeight, + lockupTx, + privateKey, + refundAddress, + feePerVbyte, + true // Try cooperative first + ) + + if (!refundTxRes.ok) { + return { ok: false, error: refundTxRes.error } + } + + const cooperative = !refundTxRes.cooperativeError + this.log(`Refund transaction constructed (${cooperative ? 'cooperative' : 'uncooperative'}):`, refundTxRes.transaction.getId()) + if (!cooperative) { + return { ok: true, publish: { done: false, txHex: refundTxRes.transaction.toHex(), txId: refundTxRes.transaction.getId() } } + } + // Broadcast the refund transaction + const broadcastRes = await this.broadcastRefundTransaction(refundTxRes.transaction) + if (!broadcastRes.ok) { + return { ok: false, error: `Failed to broadcast refund transaction: ${broadcastRes.error}` } + } + + this.log('Refund transaction broadcasted successfully:', broadcastRes.txId) + return { ok: true, publish: { done: true, txId: broadcastRes.txId } } + } + SubscribeToInvoiceSwap = (data: InvoiceSwapData, swapDone: (result: { ok: true } | { ok: false, error: string }) => void, waitingTx: () => void) => { const webSocket = new ws(`${this.wsUrl}/v2/ws`) const subReq = { op: 'subscribe', channel: 'swap.update', args: [data.createdResponse.id] } diff --git a/src/services/lnd/swaps/swaps.ts b/src/services/lnd/swaps/swaps.ts index 381e0690..79a3f408 100644 --- a/src/services/lnd/swaps/swaps.ts +++ b/src/services/lnd/swaps/swaps.ts @@ -100,6 +100,36 @@ export class Swaps { } } + RefundInvoiceSwap = async (swapOperationId: string, satPerVByte: number, refundAddress: string, currentHeight: number): Promise<{ published: false, txHex: string, txId: string } | { published: true, txId: string }> => { + const swap = await this.storage.paymentStorage.GetRefundableInvoiceSwap(swapOperationId) + if (!swap) { + throw new Error("Swap not found or already used") + } + const swapper = this.subSwappers[swap.service_url] + if (!swapper) { + throw new Error("swapper service not found") + } + const result = await swapper.RefundSwap({ + swapId: swap.swap_quote_id, + claimPublicKey: swap.claim_public_key, + currentHeight, + privateKeyHex: swap.ephemeral_private_key, + refundAddress, + swapTree: swap.swap_tree, + timeoutBlockHeight: swap.timeout_block_height, + feePerVbyte: satPerVByte, + lockupTxHex: swap.lockup_tx_hex, + }) + if (!result.ok) { + throw new Error(result.error) + } + if (result.publish.done) { + return { published: true, txId: result.publish.txId } + } + return { published: false, txHex: result.publish.txHex, txId: result.publish.txId } + + } + PayInvoiceSwap = async (appUserId: string, swapOpId: string, satPerVByte: number, payAddress: (address: string, amt: number) => Promise<{ txId: string }>): Promise => { if (!this.settings.getSettings().swapsSettings.enableSwaps) { throw new Error("Swaps are not enabled") diff --git a/src/services/main/adminManager.ts b/src/services/main/adminManager.ts index 8284b253..8fae2b5d 100644 --- a/src/services/main/adminManager.ts +++ b/src/services/main/adminManager.ts @@ -274,6 +274,18 @@ export class AdminManager { this.swaps.PayInvoiceSwap("admin", req.swap_operation_id, req.sat_per_v_byte, async (addr, amt) => { const tx = await this.lnd.PayAddress(addr, amt, req.sat_per_v_byte, "", { useProvider: false, from: 'system' }) this.log("paid admin invoice swap", { swapOpId: req.swap_operation_id, txId: tx.txid }) + await this.storage.metricsStorage.AddRootOperation("chain_payment", txId, amt) + + // Fetch the full transaction hex for potential refunds + let lockupTxHex: string | undefined + try { + const txDetails = await this.lnd.GetTx(tx.txid) + lockupTxHex = txDetails.rawTxHex + } catch (err: any) { + this.log("Warning: Could not fetch transaction hex for refund purposes:", err.message) + } + + await this.storage.paymentStorage.SetInvoiceSwapTxId(req.swap_operation_id, txId, lockupTxHex) res(tx.txid) return { txId: tx.txid } }) @@ -281,6 +293,18 @@ export class AdminManager { return { tx_id: txId } } + async RefundAdminInvoiceSwap(req: Types.RefundAdminInvoiceSwapRequest): Promise { + const info = await this.lnd.GetInfo() + const currentHeight = info.blockHeight + const address = await this.lnd.NewAddress(Types.AddressType.WITNESS_PUBKEY_HASH, { useProvider: false, from: 'system' }) + const result = await this.swaps.RefundInvoiceSwap(req.swap_operation_id, req.sat_per_v_byte, address.address, currentHeight) + if (result.published) { + return { tx_id: result.txId } + } + await this.lnd.PublishTransaction(result.txHex) + return { tx_id: result.txId } + } + async ListAdminTxSwaps(): Promise { return this.swaps.ListTxSwaps("admin", [], p => undefined, amt => 0) } diff --git a/src/services/storage/entity/InvoiceSwap.ts b/src/services/storage/entity/InvoiceSwap.ts index 2ab18347..f435edab 100644 --- a/src/services/storage/entity/InvoiceSwap.ts +++ b/src/services/storage/entity/InvoiceSwap.ts @@ -71,6 +71,9 @@ export class InvoiceSwap { @Column({ default: "" }) tx_id: string + @Column({ default: "", type: "text" }) + lockup_tx_hex: string + /* @Column({ default: "" }) address_paid: string */ diff --git a/src/services/storage/migrations/1769529793283-invoice_swaps.ts b/src/services/storage/migrations/1769529793283-invoice_swaps.ts index b32cc1de..f7b93755 100644 --- a/src/services/storage/migrations/1769529793283-invoice_swaps.ts +++ b/src/services/storage/migrations/1769529793283-invoice_swaps.ts @@ -5,25 +5,9 @@ export class InvoiceSwaps1769529793283 implements MigrationInterface { public async up(queryRunner: QueryRunner): Promise { await queryRunner.query(`CREATE TABLE "invoice_swap" ("swap_operation_id" varchar PRIMARY KEY NOT NULL, "app_user_id" varchar NOT NULL, "swap_quote_id" varchar NOT NULL, "swap_tree" varchar NOT NULL, "claim_public_key" varchar NOT NULL, "payment_hash" varchar NOT NULL, "timeout_block_height" integer NOT NULL, "invoice" varchar NOT NULL, "invoice_amount" integer NOT NULL, "transaction_amount" integer NOT NULL, "swap_fee_sats" integer NOT NULL, "chain_fee_sats" integer NOT NULL, "ephemeral_public_key" varchar NOT NULL, "address" varchar NOT NULL, "ephemeral_private_key" varchar NOT NULL, "used" boolean NOT NULL DEFAULT (0), "preimage" varchar NOT NULL DEFAULT (''), "failure_reason" varchar NOT NULL DEFAULT (''), "tx_id" varchar NOT NULL DEFAULT (''), "service_url" varchar NOT NULL DEFAULT (''), "created_at" datetime NOT NULL DEFAULT (datetime('now')), "updated_at" datetime NOT NULL DEFAULT (datetime('now')))`); - await queryRunner.query(`DROP INDEX "recv_invoice_paid_serial"`); - await queryRunner.query(`DROP INDEX "IDX_a131e6b58f084f1340538681b5"`); - await queryRunner.query(`CREATE TABLE "temporary_user_receiving_invoice" ("serial_id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "invoice" varchar NOT NULL, "expires_at_unix" integer NOT NULL, "paid_at_unix" integer NOT NULL DEFAULT (0), "internal" boolean NOT NULL DEFAULT (0), "paidByLnd" boolean NOT NULL DEFAULT (0), "callbackUrl" varchar NOT NULL DEFAULT (''), "paid_amount" integer NOT NULL DEFAULT (0), "service_fee" integer NOT NULL DEFAULT (0), "zap_info" text, "created_at" datetime NOT NULL DEFAULT (datetime('now')), "updated_at" datetime NOT NULL DEFAULT (datetime('now')), "userSerialId" integer, "productProductId" varchar, "payerSerialId" integer, "linkedApplicationSerialId" integer, "liquidityProvider" varchar, "payer_data" text, "offer_id" varchar NOT NULL DEFAULT (''), "rejectUnauthorized" boolean NOT NULL DEFAULT (1), "bearer_token" varchar NOT NULL DEFAULT (''), "clink_requester_pub" varchar, "clink_requester_event_id" varchar, CONSTRAINT "FK_2c0dfb3483f3e5e7e3cdd5dc71f" FOREIGN KEY ("userSerialId") REFERENCES "user" ("serial_id") ON DELETE NO ACTION ON UPDATE NO ACTION, CONSTRAINT "FK_5263bde2a519db9ea608b702ec8" FOREIGN KEY ("productProductId") REFERENCES "product" ("product_id") ON DELETE NO ACTION ON UPDATE NO ACTION, CONSTRAINT "FK_d4bb1e4c60e8a869f1f43ca2e31" FOREIGN KEY ("payerSerialId") REFERENCES "user" ("serial_id") ON DELETE NO ACTION ON UPDATE NO ACTION, CONSTRAINT "FK_714a8b7d4f89f8a802ca181b789" FOREIGN KEY ("linkedApplicationSerialId") REFERENCES "application" ("serial_id") ON DELETE NO ACTION ON UPDATE NO ACTION)`); - await queryRunner.query(`INSERT INTO "temporary_user_receiving_invoice"("serial_id", "invoice", "expires_at_unix", "paid_at_unix", "internal", "paidByLnd", "callbackUrl", "paid_amount", "service_fee", "zap_info", "created_at", "updated_at", "userSerialId", "productProductId", "payerSerialId", "linkedApplicationSerialId", "liquidityProvider", "payer_data", "offer_id", "rejectUnauthorized", "bearer_token", "clink_requester_pub", "clink_requester_event_id") SELECT "serial_id", "invoice", "expires_at_unix", "paid_at_unix", "internal", "paidByLnd", "callbackUrl", "paid_amount", "service_fee", "zap_info", "created_at", "updated_at", "userSerialId", "productProductId", "payerSerialId", "linkedApplicationSerialId", "liquidityProvider", "payer_data", "offer_id", "rejectUnauthorized", "bearer_token", "clink_requester_pub", "clink_requester_event_id" FROM "user_receiving_invoice"`); - await queryRunner.query(`DROP TABLE "user_receiving_invoice"`); - await queryRunner.query(`ALTER TABLE "temporary_user_receiving_invoice" RENAME TO "user_receiving_invoice"`); - await queryRunner.query(`CREATE INDEX "recv_invoice_paid_serial" ON "user_receiving_invoice" ("userSerialId", "paid_at_unix", "serial_id") WHERE paid_at_unix > 0`); - await queryRunner.query(`CREATE UNIQUE INDEX "IDX_a131e6b58f084f1340538681b5" ON "user_receiving_invoice" ("invoice") `); } public async down(queryRunner: QueryRunner): Promise { - await queryRunner.query(`DROP INDEX "IDX_a131e6b58f084f1340538681b5"`); - await queryRunner.query(`DROP INDEX "recv_invoice_paid_serial"`); - await queryRunner.query(`ALTER TABLE "user_receiving_invoice" RENAME TO "temporary_user_receiving_invoice"`); - await queryRunner.query(`CREATE TABLE "user_receiving_invoice" ("serial_id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "invoice" varchar NOT NULL, "expires_at_unix" integer NOT NULL, "paid_at_unix" integer NOT NULL DEFAULT (0), "internal" boolean NOT NULL DEFAULT (0), "paidByLnd" boolean NOT NULL DEFAULT (0), "callbackUrl" varchar NOT NULL DEFAULT (''), "paid_amount" integer NOT NULL DEFAULT (0), "service_fee" integer NOT NULL DEFAULT (0), "zap_info" text, "created_at" datetime NOT NULL DEFAULT (datetime('now')), "updated_at" datetime NOT NULL DEFAULT (datetime('now')), "userSerialId" integer, "productProductId" varchar, "payerSerialId" integer, "linkedApplicationSerialId" integer, "liquidityProvider" varchar, "payer_data" text, "offer_id" varchar NOT NULL DEFAULT (''), "rejectUnauthorized" boolean NOT NULL DEFAULT (1), "bearer_token" varchar NOT NULL DEFAULT (''), "clink_requester_pub" varchar(64), "clink_requester_event_id" varchar(64), CONSTRAINT "FK_2c0dfb3483f3e5e7e3cdd5dc71f" FOREIGN KEY ("userSerialId") REFERENCES "user" ("serial_id") ON DELETE NO ACTION ON UPDATE NO ACTION, CONSTRAINT "FK_5263bde2a519db9ea608b702ec8" FOREIGN KEY ("productProductId") REFERENCES "product" ("product_id") ON DELETE NO ACTION ON UPDATE NO ACTION, CONSTRAINT "FK_d4bb1e4c60e8a869f1f43ca2e31" FOREIGN KEY ("payerSerialId") REFERENCES "user" ("serial_id") ON DELETE NO ACTION ON UPDATE NO ACTION, CONSTRAINT "FK_714a8b7d4f89f8a802ca181b789" FOREIGN KEY ("linkedApplicationSerialId") REFERENCES "application" ("serial_id") ON DELETE NO ACTION ON UPDATE NO ACTION)`); - await queryRunner.query(`INSERT INTO "user_receiving_invoice"("serial_id", "invoice", "expires_at_unix", "paid_at_unix", "internal", "paidByLnd", "callbackUrl", "paid_amount", "service_fee", "zap_info", "created_at", "updated_at", "userSerialId", "productProductId", "payerSerialId", "linkedApplicationSerialId", "liquidityProvider", "payer_data", "offer_id", "rejectUnauthorized", "bearer_token", "clink_requester_pub", "clink_requester_event_id") SELECT "serial_id", "invoice", "expires_at_unix", "paid_at_unix", "internal", "paidByLnd", "callbackUrl", "paid_amount", "service_fee", "zap_info", "created_at", "updated_at", "userSerialId", "productProductId", "payerSerialId", "linkedApplicationSerialId", "liquidityProvider", "payer_data", "offer_id", "rejectUnauthorized", "bearer_token", "clink_requester_pub", "clink_requester_event_id" FROM "temporary_user_receiving_invoice"`); - await queryRunner.query(`DROP TABLE "temporary_user_receiving_invoice"`); - await queryRunner.query(`CREATE UNIQUE INDEX "IDX_a131e6b58f084f1340538681b5" ON "user_receiving_invoice" ("invoice") `); - await queryRunner.query(`CREATE INDEX "recv_invoice_paid_serial" ON "user_receiving_invoice" ("userSerialId", "paid_at_unix", "serial_id") WHERE paid_at_unix > 0`); await queryRunner.query(`DROP TABLE "invoice_swap"`); } diff --git a/src/services/storage/migrations/1769805357459-invoice_swaps_fixes.ts b/src/services/storage/migrations/1769805357459-invoice_swaps_fixes.ts new file mode 100644 index 00000000..3ba13031 --- /dev/null +++ b/src/services/storage/migrations/1769805357459-invoice_swaps_fixes.ts @@ -0,0 +1,21 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class InvoiceSwapsFixes1769805357459 implements MigrationInterface { + name = 'InvoiceSwapsFixes1769805357459' + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(`CREATE TABLE "temporary_invoice_swap" ("swap_operation_id" varchar PRIMARY KEY NOT NULL, "app_user_id" varchar NOT NULL, "swap_quote_id" varchar NOT NULL, "swap_tree" varchar NOT NULL, "claim_public_key" varchar NOT NULL, "payment_hash" varchar NOT NULL, "timeout_block_height" integer NOT NULL, "invoice" varchar NOT NULL, "invoice_amount" integer NOT NULL, "transaction_amount" integer NOT NULL, "swap_fee_sats" integer NOT NULL, "chain_fee_sats" integer NOT NULL, "ephemeral_public_key" varchar NOT NULL, "address" varchar NOT NULL, "ephemeral_private_key" varchar NOT NULL, "used" boolean NOT NULL DEFAULT (0), "preimage" varchar NOT NULL DEFAULT (''), "failure_reason" varchar NOT NULL DEFAULT (''), "tx_id" varchar NOT NULL DEFAULT (''), "service_url" varchar NOT NULL DEFAULT (''), "created_at" datetime NOT NULL DEFAULT (datetime('now')), "updated_at" datetime NOT NULL DEFAULT (datetime('now')), "lockup_tx_hex" text NOT NULL DEFAULT (''))`); + await queryRunner.query(`INSERT INTO "temporary_invoice_swap"("swap_operation_id", "app_user_id", "swap_quote_id", "swap_tree", "claim_public_key", "payment_hash", "timeout_block_height", "invoice", "invoice_amount", "transaction_amount", "swap_fee_sats", "chain_fee_sats", "ephemeral_public_key", "address", "ephemeral_private_key", "used", "preimage", "failure_reason", "tx_id", "service_url", "created_at", "updated_at") SELECT "swap_operation_id", "app_user_id", "swap_quote_id", "swap_tree", "claim_public_key", "payment_hash", "timeout_block_height", "invoice", "invoice_amount", "transaction_amount", "swap_fee_sats", "chain_fee_sats", "ephemeral_public_key", "address", "ephemeral_private_key", "used", "preimage", "failure_reason", "tx_id", "service_url", "created_at", "updated_at" FROM "invoice_swap"`); + await queryRunner.query(`DROP TABLE "invoice_swap"`); + await queryRunner.query(`ALTER TABLE "temporary_invoice_swap" RENAME TO "invoice_swap"`); + + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE "invoice_swap" RENAME TO "temporary_invoice_swap"`); + await queryRunner.query(`CREATE TABLE "invoice_swap" ("swap_operation_id" varchar PRIMARY KEY NOT NULL, "app_user_id" varchar NOT NULL, "swap_quote_id" varchar NOT NULL, "swap_tree" varchar NOT NULL, "claim_public_key" varchar NOT NULL, "payment_hash" varchar NOT NULL, "timeout_block_height" integer NOT NULL, "invoice" varchar NOT NULL, "invoice_amount" integer NOT NULL, "transaction_amount" integer NOT NULL, "swap_fee_sats" integer NOT NULL, "chain_fee_sats" integer NOT NULL, "ephemeral_public_key" varchar NOT NULL, "address" varchar NOT NULL, "ephemeral_private_key" varchar NOT NULL, "used" boolean NOT NULL DEFAULT (0), "preimage" varchar NOT NULL DEFAULT (''), "failure_reason" varchar NOT NULL DEFAULT (''), "tx_id" varchar NOT NULL DEFAULT (''), "service_url" varchar NOT NULL DEFAULT (''), "created_at" datetime NOT NULL DEFAULT (datetime('now')), "updated_at" datetime NOT NULL DEFAULT (datetime('now')))`); + await queryRunner.query(`INSERT INTO "invoice_swap"("swap_operation_id", "app_user_id", "swap_quote_id", "swap_tree", "claim_public_key", "payment_hash", "timeout_block_height", "invoice", "invoice_amount", "transaction_amount", "swap_fee_sats", "chain_fee_sats", "ephemeral_public_key", "address", "ephemeral_private_key", "used", "preimage", "failure_reason", "tx_id", "service_url", "created_at", "updated_at") SELECT "swap_operation_id", "app_user_id", "swap_quote_id", "swap_tree", "claim_public_key", "payment_hash", "timeout_block_height", "invoice", "invoice_amount", "transaction_amount", "swap_fee_sats", "chain_fee_sats", "ephemeral_public_key", "address", "ephemeral_private_key", "used", "preimage", "failure_reason", "tx_id", "service_url", "created_at", "updated_at" FROM "temporary_invoice_swap"`); + await queryRunner.query(`DROP TABLE "temporary_invoice_swap"`); + } + +} diff --git a/src/services/storage/migrations/runner.ts b/src/services/storage/migrations/runner.ts index ce3f7e8d..0b08799a 100644 --- a/src/services/storage/migrations/runner.ts +++ b/src/services/storage/migrations/runner.ts @@ -33,14 +33,14 @@ import { ClinkRequester1765497600000 } from './1765497600000-clink_requester.js' import { TrackedProviderHeight1766504040000 } from './1766504040000-tracked_provider_height.js' import { SwapsServiceUrl1768413055036 } from './1768413055036-swaps_service_url.js' import { InvoiceSwaps1769529793283 } from './1769529793283-invoice_swaps.js' - +import { InvoiceSwapsFixes1769805357459 } from './1769805357459-invoice_swaps_fixes.js' export const allMigrations = [Initial1703170309875, LspOrder1718387847693, LiquidityProvider1719335699480, LndNodeInfo1720187506189, TrackedProvider1720814323679, CreateInviteTokenTable1721751414878, PaymentIndex1721760297610, DebitAccess1726496225078, DebitAccessFixes1726685229264, DebitToPub1727105758354, UserCbUrl1727112281043, UserOffer1733502626042, ManagementGrant1751307732346, ManagementGrantBanned1751989251513, InvoiceCallbackUrls1752425992291, OldSomethingLeftover1753106599604, UserReceivingInvoiceIdx1753109184611, AppUserDevice1753285173175, UserAccess1759426050669, AddBlindToUserOffer1760000000000, ApplicationAvatarUrl1761000001000, AdminSettings1761683639419, TxSwap1762890527098, - TxSwapAddress1764779178945, ClinkRequester1765497600000, TrackedProviderHeight1766504040000, SwapsServiceUrl1768413055036, InvoiceSwaps1769529793283] + TxSwapAddress1764779178945, ClinkRequester1765497600000, TrackedProviderHeight1766504040000, SwapsServiceUrl1768413055036, InvoiceSwaps1769529793283, InvoiceSwapsFixes1769805357459] export const allMetricsMigrations = [LndMetrics1703170330183, ChannelRouting1709316653538, HtlcCount1724266887195, BalanceEvents1724860966825, RootOps1732566440447, RootOpsTime1745428134124, ChannelEvents1750777346411] /* export const TypeOrmMigrationRunner = async (log: PubLogger, storageManager: Storage, settings: DbSettings, arg: string | undefined): Promise => { diff --git a/src/services/storage/paymentStorage.ts b/src/services/storage/paymentStorage.ts index a1ffa3d1..34c6d3bf 100644 --- a/src/services/storage/paymentStorage.ts +++ b/src/services/storage/paymentStorage.ts @@ -535,10 +535,14 @@ export default class { }, txId) } - async SetInvoiceSwapTxId(swapOperationId: string, chainTxId: string, txId?: string) { - return this.dbs.Update('InvoiceSwap', { swap_operation_id: swapOperationId }, { + async SetInvoiceSwapTxId(swapOperationId: string, chainTxId: string, lockupTxHex?: string, txId?: string) { + const update: Partial = { tx_id: chainTxId, - }, txId) + } + if (lockupTxHex) { + update.lockup_tx_hex = lockupTxHex + } + return this.dbs.Update('InvoiceSwap', { swap_operation_id: swapOperationId }, update, txId) } async FailInvoiceSwap(swapOperationId: string, failureReason: string, txId?: string) { @@ -566,7 +570,18 @@ export default class { async ListUnfinishedInvoiceSwaps(txId?: string) { const swaps = await this.dbs.Find('InvoiceSwap', { where: { used: false } }, txId) - return swaps.filter(s => !s.tx_id) + return swaps.filter(s => !!s.tx_id) + } + + async GetRefundableInvoiceSwap(swapOperationId: string, txId?: string) { + const swap = await this.dbs.FindOne('InvoiceSwap', { where: { swap_operation_id: swapOperationId } }, txId) + if (!swap || !swap.tx_id) { + return null + } + if (swap.used && !swap.failure_reason) { + return null + } + return swap } } From f5eb1f3253e5a8e716c7304ae42de372dff31ceb Mon Sep 17 00:00:00 2001 From: boufni95 Date: Mon, 2 Feb 2026 21:15:42 +0000 Subject: [PATCH 06/66] amount input --- proto/autogenerated/client.md | 2 +- proto/autogenerated/go/types.go | 2 +- proto/autogenerated/ts/types.ts | 8 ++++---- proto/service/structs.proto | 2 +- src/services/main/adminManager.ts | 4 +++- 5 files changed, 10 insertions(+), 8 deletions(-) diff --git a/proto/autogenerated/client.md b/proto/autogenerated/client.md index 60dd284e..75b44d4e 100644 --- a/proto/autogenerated/client.md +++ b/proto/autogenerated/client.md @@ -1405,7 +1405,7 @@ The nostr server will send back a message response, and inside the body there wi - __quotes__: ARRAY of: _[InvoiceSwapQuote](#InvoiceSwapQuote)_ ### InvoiceSwapRequest - - __invoice__: _string_ + - __amount_sats__: _number_ ### InvoiceSwapsList - __quotes__: ARRAY of: _[InvoiceSwapQuote](#InvoiceSwapQuote)_ diff --git a/proto/autogenerated/go/types.go b/proto/autogenerated/go/types.go index d5b21b2f..2c79cb0a 100644 --- a/proto/autogenerated/go/types.go +++ b/proto/autogenerated/go/types.go @@ -382,7 +382,7 @@ type InvoiceSwapQuoteList struct { Quotes []InvoiceSwapQuote `json:"quotes"` } type InvoiceSwapRequest struct { - Invoice string `json:"invoice"` + Amount_sats int64 `json:"amount_sats"` } type InvoiceSwapsList struct { Quotes []InvoiceSwapQuote `json:"quotes"` diff --git a/proto/autogenerated/ts/types.ts b/proto/autogenerated/ts/types.ts index a738a06c..17fec2b1 100644 --- a/proto/autogenerated/ts/types.ts +++ b/proto/autogenerated/ts/types.ts @@ -2251,19 +2251,19 @@ export const InvoiceSwapQuoteListValidate = (o?: InvoiceSwapQuoteList, opts: Inv } export type InvoiceSwapRequest = { - invoice: string + amount_sats: number } export const InvoiceSwapRequestOptionalFields: [] = [] export type InvoiceSwapRequestOptions = OptionsBaseMessage & { checkOptionalsAreSet?: [] - invoice_CustomCheck?: (v: string) => boolean + amount_sats_CustomCheck?: (v: number) => boolean } export const InvoiceSwapRequestValidate = (o?: InvoiceSwapRequest, opts: InvoiceSwapRequestOptions = {}, path: string = 'InvoiceSwapRequest::root.'): Error | null => { if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message') if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null') - if (typeof o.invoice !== 'string') return new Error(`${path}.invoice: is not a string`) - if (opts.invoice_CustomCheck && !opts.invoice_CustomCheck(o.invoice)) return new Error(`${path}.invoice: custom check failed`) + if (typeof o.amount_sats !== 'number') return new Error(`${path}.amount_sats: is not a number`) + if (opts.amount_sats_CustomCheck && !opts.amount_sats_CustomCheck(o.amount_sats)) return new Error(`${path}.amount_sats: custom check failed`) return null } diff --git a/proto/service/structs.proto b/proto/service/structs.proto index 5b25c699..2ce6adc3 100644 --- a/proto/service/structs.proto +++ b/proto/service/structs.proto @@ -834,7 +834,7 @@ message MessagingToken { } message InvoiceSwapRequest { - string invoice = 1; + int64 amount_sats = 1; } message InvoiceSwapQuote { diff --git a/src/services/main/adminManager.ts b/src/services/main/adminManager.ts index 8fae2b5d..1c54d12f 100644 --- a/src/services/main/adminManager.ts +++ b/src/services/main/adminManager.ts @@ -6,6 +6,7 @@ import * as Types from '../../../proto/autogenerated/ts/types.js' import LND from "../lnd/lnd.js"; import SettingsManager from "./settingsManager.js"; import { Swaps } from "../lnd/swaps/swaps.js"; +import { defaultInvoiceExpiry } from "../storage/paymentStorage.js"; export class AdminManager { settings: SettingsManager storage: Storage @@ -265,7 +266,8 @@ export class AdminManager { } async GetAdminInvoiceSwapQuotes(req: Types.InvoiceSwapRequest): Promise { - const quotes = await this.swaps.GetInvoiceSwapQuotes("admin", req.invoice) + const invoice = await this.lnd.NewInvoice(req.amount_sats, "Admin Swap", defaultInvoiceExpiry, { useProvider: false, from: 'system' }) + const quotes = await this.swaps.GetInvoiceSwapQuotes("admin", invoice.payRequest) return { quotes } } From ae4a5cb5d042af6273df3c82b9dffa4f26a736bb Mon Sep 17 00:00:00 2001 From: boufni95 Date: Wed, 4 Feb 2026 16:53:59 +0000 Subject: [PATCH 07/66] lnd logs --- src/services/lnd/lnd.ts | 62 +++++++++++++++++++++++--------------- src/services/main/index.ts | 1 + 2 files changed, 38 insertions(+), 25 deletions(-) diff --git a/src/services/lnd/lnd.ts b/src/services/lnd/lnd.ts index daf7b411..27e9f8a4 100644 --- a/src/services/lnd/lnd.ts +++ b/src/services/lnd/lnd.ts @@ -126,6 +126,7 @@ export default class { } async Warmup() { + this.log("Warming up LND") // Skip LND warmup if using only liquidity provider if (this.liquidProvider.getSettings().useOnlyLiquidityProvider) { this.log("USE_ONLY_LIQUIDITY_PROVIDER enabled, skipping LND warmup") @@ -174,6 +175,7 @@ export default class { return res.response } async ListPendingChannels(): Promise { + this.log("Listing pending channels") if (this.liquidProvider.getSettings().useOnlyLiquidityProvider) { return { pendingOpenChannels: [], pendingClosingChannels: [], pendingForceClosingChannels: [], waitingCloseChannels: [], totalLimboBalance: 0n } } @@ -182,14 +184,14 @@ export default class { return res.response } async ListChannels(peerLookup = false): Promise { - // console.log("Listing channels") + this.log("Listing channels") const res = await this.lightning.listChannels({ activeOnly: false, inactiveOnly: false, privateOnly: false, publicOnly: false, peer: Buffer.alloc(0), peerAliasLookup: peerLookup }, DeadLineMetadata()) return res.response } async ListClosedChannels(): Promise { - // console.log("Listing closed channels") + this.log("Listing closed channels") const res = await this.lightning.closedChannels({ abandoned: true, breach: true, @@ -217,7 +219,7 @@ export default class { } RestartStreams() { - // console.log("Restarting streams") + this.log("Restarting streams") if (!this.ready || this.abortController.signal.aborted) { return } @@ -235,7 +237,7 @@ export default class { } async SubscribeChannelEvents() { - // console.log("Subscribing to channel events") + this.log("Subscribing to channel events") const stream = this.lightning.subscribeChannelEvents({}, { abort: this.abortController.signal }) stream.responses.onMessage(async channel => { const channels = await this.ListChannels() @@ -250,7 +252,7 @@ export default class { } async SubscribeHtlcEvents() { - // console.log("Subscribing to htlc events") + this.log("Subscribing to htlc events") const stream = this.router.subscribeHtlcEvents({}, { abort: this.abortController.signal }) stream.responses.onMessage(htlc => { this.htlcCb(htlc) @@ -264,7 +266,7 @@ export default class { } async SubscribeNewBlock() { - // console.log("Subscribing to new block") + this.log("Subscribing to new block") const { blockHeight } = await this.GetInfo() const stream = this.chainNotifier.registerBlockEpochNtfn({ height: blockHeight, hash: Buffer.alloc(0) }, { abort: this.abortController.signal }) stream.responses.onMessage(block => { @@ -279,7 +281,7 @@ export default class { } SubscribeAddressPaid(): void { - // console.log("Subscribing to address paid") + this.log("Subscribing to address paid") const stream = this.lightning.subscribeTransactions({ account: "", endHeight: 0, @@ -306,7 +308,7 @@ export default class { } SubscribeInvoicePaid(): void { - // console.log("Subscribing to invoice paid") + this.log("Subscribing to invoice paid") const stream = this.lightning.subscribeInvoices({ settleIndex: BigInt(this.latestKnownSettleIndex), addIndex: 0n, @@ -348,6 +350,7 @@ export default class { } async ListAddresses(): Promise { + this.log("Listing addresses") const res = await this.walletKit.listAddresses({ accountName: "", showCustomAccounts: false }, DeadLineMetadata()) const addresses = res.response.accountWithAddresses.map(a => a.addresses.map(a => ({ address: a.address, change: a.isInternal }))).flat() addresses.forEach(a => this.addressesCache[a.address] = { isChange: a.change }) @@ -355,6 +358,7 @@ export default class { } async NewAddress(addressType: Types.AddressType, { useProvider, from }: TxActionOptions): Promise { + this.log("Creating new address") // 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") @@ -389,7 +393,7 @@ export default class { } async NewInvoice(value: number, memo: string, expiry: number, { useProvider, from }: TxActionOptions, blind = false): Promise { - // console.log("Creating new invoice") + this.log("Creating new invoice") // Force use of provider when bypass is enabled const mustUseProvider = this.liquidProvider.getSettings().useOnlyLiquidityProvider || useProvider if (mustUseProvider) { @@ -409,6 +413,7 @@ export default class { } async DecodeInvoice(paymentRequest: string): Promise { + this.log("Decoding invoice") if (this.liquidProvider.getSettings().useOnlyLiquidityProvider) { // Use light-bolt11-decoder when LND is bypassed try { @@ -440,6 +445,7 @@ export default class { } async ChannelBalance(): Promise<{ local: number, remote: number }> { + this.log("Getting channel balance") if (this.liquidProvider.getSettings().useOnlyLiquidityProvider) { return { local: 0, remote: 0 } } @@ -449,7 +455,7 @@ export default class { return { local: r.localBalance ? Number(r.localBalance.sat) : 0, remote: r.remoteBalance ? Number(r.remoteBalance.sat) : 0 } } async PayInvoice(invoice: string, amount: number, { routingFeeLimit, serviceFee }: { routingFeeLimit: number, serviceFee: number }, decodedAmount: number, { useProvider, from }: TxActionOptions, paymentIndexCb?: (index: number) => void): Promise { - // console.log("Paying invoice") + this.log("Paying invoice") if (this.outgoingOpsLocked) { this.log("outgoing ops locked, rejecting payment request") throw new Error("lnd node is currently out of sync") @@ -498,7 +504,7 @@ export default class { } async EstimateChainFees(address: string, amount: number, targetConf: number): Promise { - // console.log("Estimating chain fees") + this.log("Estimating chain fees") await this.Health() const res = await this.lightning.estimateFee({ addrToAmount: { [address]: BigInt(amount) }, @@ -511,6 +517,7 @@ export default class { } async PayAddress(address: string, amount: number, satPerVByte: number, label = "", { useProvider, from }: TxActionOptions): Promise { + this.log("Paying address") // 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") @@ -535,19 +542,19 @@ export default class { } async GetTransactions(startHeight: number): Promise { - // console.log("Getting transactions") + this.log("Getting transactions") const res = await this.lightning.getTransactions({ startHeight, endHeight: 0, account: "" }, DeadLineMetadata()) return res.response } async GetChannelInfo(chanId: string) { - // console.log("Getting channel info") + this.log("Getting channel info") const res = await this.lightning.getChanInfo({ chanId, chanPoint: "" }, DeadLineMetadata()) return res.response } async UpdateChannelPolicy(chanPoint: string, policy: Types.ChannelPolicy) { - // console.log("Updating channel policy") + this.log("Updating channel policy") const split = chanPoint.split(':') const res = await this.lightning.updateChannelPolicy({ @@ -565,19 +572,19 @@ export default class { } async GetChannelBalance() { - // console.log("Getting channel balance") + this.log("Getting channel balance") const res = await this.lightning.channelBalance({}, DeadLineMetadata()) return res.response } async GetWalletBalance() { - // console.log("Getting wallet balance") + this.log("Getting wallet balance") const res = await this.lightning.walletBalance({ account: "", minConfs: 1 }, DeadLineMetadata()) return res.response } async GetTotalBalace() { - // console.log("Getting total balance") + this.log("Getting total balance") const walletBalance = await this.GetWalletBalance() const confirmedWalletBalance = Number(walletBalance.confirmedBalance) this.utils.stateBundler.AddBalancePoint('walletBalance', confirmedWalletBalance) @@ -592,6 +599,7 @@ export default class { } async GetBalance(): Promise { // TODO: remove this + this.log("Getting balance") if (this.liquidProvider.getSettings().useOnlyLiquidityProvider) { return { confirmedBalance: 0, unconfirmedBalance: 0, totalBalance: 0, channelsBalance: [] } } @@ -611,6 +619,7 @@ export default class { } async GetForwardingHistory(indexOffset: number, startTime = 0, endTime = 0): Promise { + this.log("Getting forwarding history") if (this.liquidProvider.getSettings().useOnlyLiquidityProvider) { return { forwardingEvents: [], lastOffsetIndex: indexOffset } } @@ -620,6 +629,7 @@ export default class { } async GetAllPaidInvoices(max: number) { + this.log("Getting all paid invoices") if (this.liquidProvider.getSettings().useOnlyLiquidityProvider) { return { invoices: [] } } @@ -628,6 +638,7 @@ export default class { return res.response } async GetAllPayments(max: number) { + this.log("Getting all payments") if (this.liquidProvider.getSettings().useOnlyLiquidityProvider) { return { payments: [] } } @@ -637,7 +648,7 @@ export default class { } async GetPayment(paymentIndex: number) { - // console.log("Getting payment") + this.log("Getting payment") if (paymentIndex === 0) { throw new Error("payment index starts from 1") } @@ -649,6 +660,7 @@ export default class { } async GetLatestPaymentIndex(from = 0) { + this.log("Getting latest payment index") if (this.liquidProvider.getSettings().useOnlyLiquidityProvider) { return from } @@ -664,7 +676,7 @@ export default class { } async ConnectPeer(addr: { pubkey: string, host: string }) { - // console.log("Connecting to peer") + this.log("Connecting to peer") const res = await this.lightning.connectPeer({ addr, perm: true, @@ -674,7 +686,7 @@ export default class { } async GetPaymentFromHash(paymentHash: string): Promise { - // console.log("Getting payment from hash") + this.log("Getting payment from hash") const abortController = new AbortController() const stream = this.router.trackPaymentV2({ paymentHash: Buffer.from(paymentHash, 'hex'), @@ -696,13 +708,13 @@ export default class { } async GetTx(txid: string) { - // console.log("Getting transaction") + this.log("Getting transaction") const res = await this.walletKit.getTransaction({ txid }, DeadLineMetadata()) return res.response } async AddPeer(pub: string, host: string, port: number) { - // console.log("Adding peer") + this.log("Adding peer") const res = await this.lightning.connectPeer({ addr: { pubkey: pub, @@ -715,13 +727,13 @@ export default class { } async ListPeers() { - // console.log("Listing peers") + this.log("Listing peers") const res = await this.lightning.listPeers({ latestError: true }, DeadLineMetadata()) return res.response } async OpenChannel(destination: string, closeAddress: string, fundingAmount: number, pushSats: number, satsPerVByte: number): Promise { - // console.log("Opening channel") + this.log("Opening channel") const abortController = new AbortController() const req = OpenChannelReq(destination, closeAddress, fundingAmount, pushSats, satsPerVByte) const stream = this.lightning.openChannel(req, { abort: abortController.signal }) @@ -742,7 +754,7 @@ export default class { } async CloseChannel(fundingTx: string, outputIndex: number, force: boolean, satPerVByte: number): Promise { - // console.log("Closing channel") + this.log("Closing channel") const stream = this.lightning.closeChannel({ deliveryAddress: "", force: force, diff --git a/src/services/main/index.ts b/src/services/main/index.ts index 3d885681..b79f74f6 100644 --- a/src/services/main/index.ts +++ b/src/services/main/index.ts @@ -208,6 +208,7 @@ export default class { addressPaidCb: AddressPaidCb = (txOutput, address, amount, used, broadcastHeight) => { return this.storage.StartTransaction(async tx => { + getLogger({})("addressPaidCb called", JSON.stringify({ txOutput, address, amount, used, broadcastHeight })) // 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") From f262d46d1f7508f1e5900e14d53165c35dd401e3 Mon Sep 17 00:00:00 2001 From: boufni95 Date: Wed, 4 Feb 2026 17:58:29 +0000 Subject: [PATCH 08/66] fixes --- src/services/lnd/swaps/swaps.ts | 6 +++++- src/services/main/index.ts | 2 ++ src/services/serverMethods/index.ts | 9 ++++++++- 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/services/lnd/swaps/swaps.ts b/src/services/lnd/swaps/swaps.ts index 79a3f408..ba9b7f5b 100644 --- a/src/services/lnd/swaps/swaps.ts +++ b/src/services/lnd/swaps/swaps.ts @@ -170,7 +170,11 @@ export class Swaps { const swaps = await this.storage.paymentStorage.ListUnfinishedInvoiceSwaps() this.log("resuming", swaps.length, "invoice swaps") for (const swap of swaps) { - this.resumeInvoiceSwap(swap) + try { + this.resumeInvoiceSwap(swap) + } catch (err: any) { + this.log("error resuming invoice swap", err.message || err) + } } } diff --git a/src/services/main/index.ts b/src/services/main/index.ts index 3d885681..6f136e09 100644 --- a/src/services/main/index.ts +++ b/src/services/main/index.ts @@ -163,6 +163,8 @@ export default class { let log = getLogger({}) this.storage.paymentStorage.DeleteExpiredTransactionSwaps(height) .catch(err => log(ERROR, "failed to delete expired transaction swaps", err.message || err)) + this.storage.paymentStorage.DeleteExpiredInvoiceSwaps(height) + .catch(err => log(ERROR, "failed to delete expired invoice swaps", err.message || err)) try { const balanceEvents = await this.paymentManager.GetLndBalance() if (!skipMetrics) { diff --git a/src/services/serverMethods/index.ts b/src/services/serverMethods/index.ts index 47624db7..21668449 100644 --- a/src/services/serverMethods/index.ts +++ b/src/services/serverMethods/index.ts @@ -111,11 +111,18 @@ export default (mainHandler: Main): Types.ServerMethods => { }, GetAdminInvoiceSwapQuotes: async ({ ctx, req }) => { const err = Types.InvoiceSwapRequestValidate(req, { - invoice_CustomCheck: invoice => invoice !== '' + amount_sats_CustomCheck: amt => amt > 0 }) if (err != null) throw new Error(err.message) return mainHandler.adminManager.GetAdminInvoiceSwapQuotes(req) }, + RefundAdminInvoiceSwap: async ({ ctx, req }) => { + const err = Types.RefundAdminInvoiceSwapRequestValidate(req, { + swap_operation_id_CustomCheck: id => id !== '', + }) + if (err != null) throw new Error(err.message) + return mainHandler.adminManager.RefundAdminInvoiceSwap(req) + }, ListAdminInvoiceSwaps: async ({ ctx }) => { return mainHandler.adminManager.ListAdminInvoiceSwaps() }, From 23156986b1e8e62793838fa80cb1aa37ccc67f49 Mon Sep 17 00:00:00 2001 From: boufni95 Date: Wed, 4 Feb 2026 18:31:37 +0000 Subject: [PATCH 09/66] handle failure cases --- src/services/lnd/swaps/reverseSwaps.ts | 21 +++++++++++++++++---- src/services/lnd/swaps/submarineSwaps.ts | 20 ++++++++++++++++---- 2 files changed, 33 insertions(+), 8 deletions(-) diff --git a/src/services/lnd/swaps/reverseSwaps.ts b/src/services/lnd/swaps/reverseSwaps.ts index f0a5bc03..1486464a 100644 --- a/src/services/lnd/swaps/reverseSwaps.ts +++ b/src/services/lnd/swaps/reverseSwaps.ts @@ -121,10 +121,14 @@ export class ReverseSwaps { webSocket.send(JSON.stringify(subReq)) }) let txId = "", isDone = false - const done = () => { + const done = (failureReason?: string) => { isDone = true webSocket.close() - swapDone({ ok: true, txId }) + if (failureReason) { + swapDone({ ok: false, error: failureReason }) + } else { + swapDone({ ok: true, txId }) + } } webSocket.on('error', (err) => { this.log(ERROR, 'Error in WebSocket', err.message) @@ -132,7 +136,7 @@ export class ReverseSwaps { webSocket.on('close', () => { if (!isDone) { this.log(ERROR, 'WebSocket closed before swap was done'); - swapDone({ ok: false, error: 'WebSocket closed before swap was done' }) + done('WebSocket closed before swap was done') } }) webSocket.on('message', async (rawMsg) => { @@ -151,7 +155,7 @@ export class ReverseSwaps { }) } - handleSwapTransactionMessage = async (rawMsg: ws.RawData, data: TransactionSwapData, done: () => void) => { + handleSwapTransactionMessage = async (rawMsg: ws.RawData, data: TransactionSwapData, done: (failureReason?: string) => void) => { const msg = JSON.parse(rawMsg.toString('utf-8')); if (msg.event !== 'update') { return; @@ -176,6 +180,15 @@ export class ReverseSwaps { this.log('Transaction swap successful'); done() return; + case 'invoice.expired': + case 'swap.expired': + case 'transaction.failed': + done(`swap ${data.createdResponse.id} failed with status ${msg.args[0].status}`) + return; + default: + this.log('Unknown swap transaction WebSocket message', msg) + return; + } } diff --git a/src/services/lnd/swaps/submarineSwaps.ts b/src/services/lnd/swaps/submarineSwaps.ts index bf223b3e..760ca57e 100644 --- a/src/services/lnd/swaps/submarineSwaps.ts +++ b/src/services/lnd/swaps/submarineSwaps.ts @@ -375,10 +375,14 @@ export class SubmarineSwaps { webSocket.send(JSON.stringify(subReq)) }) let isDone = false - const done = () => { + const done = (failureReason?: string) => { isDone = true webSocket.close() - swapDone({ ok: true }) + if (failureReason) { + swapDone({ ok: false, error: failureReason }) + } else { + swapDone({ ok: true }) + } } webSocket.on('error', (err) => { this.log(ERROR, 'Error in WebSocket', err.message) @@ -386,7 +390,7 @@ export class SubmarineSwaps { webSocket.on('close', () => { if (!isDone) { this.log(ERROR, 'WebSocket closed before swap was done'); - swapDone({ ok: false, error: 'WebSocket closed before swap was done' }) + done('WebSocket closed before swap was done') } }) webSocket.on('message', async (rawMsg) => { @@ -403,7 +407,7 @@ export class SubmarineSwaps { } } - handleSwapInvoiceMessage = async (rawMsg: ws.RawData, data: InvoiceSwapData, closeWebSocket: () => void, waitingTx: () => void) => { + handleSwapInvoiceMessage = async (rawMsg: ws.RawData, data: InvoiceSwapData, closeWebSocket: (failureReason?: string) => void, waitingTx: () => void) => { const msg = JSON.parse(rawMsg.toString('utf-8')); if (msg.event !== 'update') { return; @@ -426,6 +430,14 @@ export class SubmarineSwaps { this.log('Invoice swap successful'); closeWebSocket() return; + case 'swap.expired': + case 'transaction.lockupFailed': + case 'invoice.failedToPay': + closeWebSocket(`swap ${data.createdResponse.id} failed with status ${msg.args[0].status}`) + return; + default: + this.log('Unknown swap invoice WebSocket message', msg) + return; } } From 070aa758d899437bab008632039e77c3c095781a Mon Sep 17 00:00:00 2001 From: boufni95 Date: Wed, 4 Feb 2026 19:42:53 +0000 Subject: [PATCH 10/66] swap logs --- src/services/lnd/swaps/submarineSwaps.ts | 1 + src/services/lnd/swaps/swaps.ts | 2 ++ 2 files changed, 3 insertions(+) diff --git a/src/services/lnd/swaps/submarineSwaps.ts b/src/services/lnd/swaps/submarineSwaps.ts index 760ca57e..788e3ce9 100644 --- a/src/services/lnd/swaps/submarineSwaps.ts +++ b/src/services/lnd/swaps/submarineSwaps.ts @@ -369,6 +369,7 @@ export class SubmarineSwaps { } SubscribeToInvoiceSwap = (data: InvoiceSwapData, swapDone: (result: { ok: true } | { ok: false, error: string }) => void, waitingTx: () => void) => { + this.log("subscribing to invoice swap", { id: data.createdResponse.id }) const webSocket = new ws(`${this.wsUrl}/v2/ws`) const subReq = { op: 'subscribe', channel: 'swap.update', args: [data.createdResponse.id] } webSocket.on('open', () => { diff --git a/src/services/lnd/swaps/swaps.ts b/src/services/lnd/swaps/swaps.ts index ba9b7f5b..fbb1613a 100644 --- a/src/services/lnd/swaps/swaps.ts +++ b/src/services/lnd/swaps/swaps.ts @@ -101,6 +101,7 @@ export class Swaps { } RefundInvoiceSwap = async (swapOperationId: string, satPerVByte: number, refundAddress: string, currentHeight: number): Promise<{ published: false, txHex: string, txId: string } | { published: true, txId: string }> => { + this.log("refunding invoice swap", { swapOperationId, satPerVByte, refundAddress, currentHeight }) const swap = await this.storage.paymentStorage.GetRefundableInvoiceSwap(swapOperationId) if (!swap) { throw new Error("Swap not found or already used") @@ -131,6 +132,7 @@ export class Swaps { } PayInvoiceSwap = async (appUserId: string, swapOpId: string, satPerVByte: number, payAddress: (address: string, amt: number) => Promise<{ txId: string }>): Promise => { + this.log("paying invoice swap", { appUserId, swapOpId, satPerVByte }) if (!this.settings.getSettings().swapsSettings.enableSwaps) { throw new Error("Swaps are not enabled") } From 1f09bcc679c103ede4985604dc1aa2e1fdf101a6 Mon Sep 17 00:00:00 2001 From: boufni95 Date: Wed, 4 Feb 2026 19:59:22 +0000 Subject: [PATCH 11/66] tmp fix --- src/services/lnd/swaps/swaps.ts | 4 +++- src/services/main/adminManager.ts | 5 +++++ src/services/main/init.ts | 1 + 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/services/lnd/swaps/swaps.ts b/src/services/lnd/swaps/swaps.ts index fbb1613a..dc57309a 100644 --- a/src/services/lnd/swaps/swaps.ts +++ b/src/services/lnd/swaps/swaps.ts @@ -164,7 +164,9 @@ export class Swaps { await this.storage.paymentStorage.FailInvoiceSwap(swapOpId, result.error, txId) this.log("invoice swap failed", { swapOpId, error: result.error }) } - }, () => payAddress(swap.address, swap.transaction_amount).then(res => { txId = res.txId }).catch(err => { close(); this.log("error paying address", err) })) + }, () => payAddress(swap.address, swap.transaction_amount) + .then(res => { txId = res.txId }) + .catch(err => { close(); this.log("error paying address", err.message || err) })) } ResumeInvoiceSwaps = async () => { diff --git a/src/services/main/adminManager.ts b/src/services/main/adminManager.ts index 1c54d12f..3585248e 100644 --- a/src/services/main/adminManager.ts +++ b/src/services/main/adminManager.ts @@ -271,6 +271,10 @@ export class AdminManager { return { quotes } } + TMP_FIX_ADMIN_TX_ID = async () => { + await this.storage.paymentStorage.SetInvoiceSwapTxId("6089e1e5-2178-418e-ae19-d32ac5eb1a84", "f997b521ce1374a85e40a0fee5ad40692338b0f5965002b9f07d141cdbe03036") + } + async PayAdminInvoiceSwap(req: Types.PayAdminInvoiceSwapRequest): Promise { const txId = await new Promise(res => { this.swaps.PayInvoiceSwap("admin", req.swap_operation_id, req.sat_per_v_byte, async (addr, amt) => { @@ -288,6 +292,7 @@ export class AdminManager { } await this.storage.paymentStorage.SetInvoiceSwapTxId(req.swap_operation_id, txId, lockupTxHex) + this.log("saved admin swap txid", { swapOpId: req.swap_operation_id, txId }) res(tx.txid) return { txId: tx.txid } }) diff --git a/src/services/main/init.ts b/src/services/main/init.ts index 946061fb..5d48ea6b 100644 --- a/src/services/main/init.ts +++ b/src/services/main/init.ts @@ -80,6 +80,7 @@ export const initMainHandler = async (log: PubLogger, settingsManager: SettingsM await mainHandler.appUserManager.CleanupInactiveUsers() await mainHandler.appUserManager.CleanupNeverActiveUsers() await swaps.ResumeInvoiceSwaps() + await adminManager.TMP_FIX_ADMIN_TX_ID() await mainHandler.paymentManager.watchDog.Start() return { mainHandler, apps, localProviderClient, wizard, adminManager } } From 7b81a90c1aef42e3cbfe1a36ed2159441d136bdb Mon Sep 17 00:00:00 2001 From: boufni95 Date: Wed, 4 Feb 2026 20:00:01 +0000 Subject: [PATCH 12/66] fix --- src/services/main/init.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/services/main/init.ts b/src/services/main/init.ts index 5d48ea6b..acfe44f9 100644 --- a/src/services/main/init.ts +++ b/src/services/main/init.ts @@ -79,8 +79,8 @@ export const initMainHandler = async (log: PubLogger, settingsManager: SettingsM await mainHandler.paymentManager.CleanupOldUnpaidInvoices() await mainHandler.appUserManager.CleanupInactiveUsers() await mainHandler.appUserManager.CleanupNeverActiveUsers() - await swaps.ResumeInvoiceSwaps() await adminManager.TMP_FIX_ADMIN_TX_ID() + await swaps.ResumeInvoiceSwaps() await mainHandler.paymentManager.watchDog.Start() return { mainHandler, apps, localProviderClient, wizard, adminManager } } From d9ec58165fbf29508a5c4bad799cfb55099c5866 Mon Sep 17 00:00:00 2001 From: boufni95 Date: Wed, 4 Feb 2026 20:03:46 +0000 Subject: [PATCH 13/66] log --- src/services/main/adminManager.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/services/main/adminManager.ts b/src/services/main/adminManager.ts index 3585248e..e01346ab 100644 --- a/src/services/main/adminManager.ts +++ b/src/services/main/adminManager.ts @@ -272,6 +272,7 @@ export class AdminManager { } TMP_FIX_ADMIN_TX_ID = async () => { + this.log("fixing tmp admin tx") await this.storage.paymentStorage.SetInvoiceSwapTxId("6089e1e5-2178-418e-ae19-d32ac5eb1a84", "f997b521ce1374a85e40a0fee5ad40692338b0f5965002b9f07d141cdbe03036") } From e24fa4f055e7edab7cac5a8534e0badc38fa9de7 Mon Sep 17 00:00:00 2001 From: boufni95 Date: Wed, 4 Feb 2026 20:09:15 +0000 Subject: [PATCH 14/66] better fix --- src/services/main/adminManager.ts | 4 +++- src/services/storage/paymentStorage.ts | 4 ++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/services/main/adminManager.ts b/src/services/main/adminManager.ts index e01346ab..e9695dc2 100644 --- a/src/services/main/adminManager.ts +++ b/src/services/main/adminManager.ts @@ -273,7 +273,9 @@ export class AdminManager { TMP_FIX_ADMIN_TX_ID = async () => { this.log("fixing tmp admin tx") - await this.storage.paymentStorage.SetInvoiceSwapTxId("6089e1e5-2178-418e-ae19-d32ac5eb1a84", "f997b521ce1374a85e40a0fee5ad40692338b0f5965002b9f07d141cdbe03036") + await this.storage.paymentStorage.UpdateInvoiceSwap("6089e1e5-2178-418e-ae19-d32ac5eb1a84", { + used: false, failure_reason: "", tx_id: "f997b521ce1374a85e40a0fee5ad40692338b0f5965002b9f07d141cdbe03036" + }) } async PayAdminInvoiceSwap(req: Types.PayAdminInvoiceSwapRequest): Promise { diff --git a/src/services/storage/paymentStorage.ts b/src/services/storage/paymentStorage.ts index 34c6d3bf..d14138bd 100644 --- a/src/services/storage/paymentStorage.ts +++ b/src/services/storage/paymentStorage.ts @@ -535,6 +535,10 @@ export default class { }, txId) } + async UpdateInvoiceSwap(swapOperationId: string, update: Partial, txId?: string) { + return this.dbs.Update('InvoiceSwap', { swap_operation_id: swapOperationId }, update, txId) + } + async SetInvoiceSwapTxId(swapOperationId: string, chainTxId: string, lockupTxHex?: string, txId?: string) { const update: Partial = { tx_id: chainTxId, From 3046e734645a3489412a2212d875ef1f9880151b Mon Sep 17 00:00:00 2001 From: shocknet-justin Date: Wed, 4 Feb 2026 15:27:52 -0500 Subject: [PATCH 15/66] zkpinit workaround --- src/services/lnd/swaps/reverseSwaps.ts | 3 ++- src/services/lnd/swaps/submarineSwaps.ts | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/services/lnd/swaps/reverseSwaps.ts b/src/services/lnd/swaps/reverseSwaps.ts index 1486464a..a8bd6ade 100644 --- a/src/services/lnd/swaps/reverseSwaps.ts +++ b/src/services/lnd/swaps/reverseSwaps.ts @@ -1,4 +1,5 @@ -import zkpInit from '@vulpemventures/secp256k1-zkp'; +import secp256k1ZkpModule from '@vulpemventures/secp256k1-zkp'; +const zkpInit = (secp256k1ZkpModule as any).default || secp256k1ZkpModule; import { initEccLib, Transaction, address } from 'bitcoinjs-lib'; // import bolt11 from 'bolt11'; import { diff --git a/src/services/lnd/swaps/submarineSwaps.ts b/src/services/lnd/swaps/submarineSwaps.ts index 788e3ce9..56ce40e3 100644 --- a/src/services/lnd/swaps/submarineSwaps.ts +++ b/src/services/lnd/swaps/submarineSwaps.ts @@ -1,4 +1,5 @@ -import zkpInit from '@vulpemventures/secp256k1-zkp'; +import secp256k1ZkpModule from '@vulpemventures/secp256k1-zkp'; +const zkpInit = (secp256k1ZkpModule as any).default || secp256k1ZkpModule; // import bolt11 from 'bolt11'; import { Musig, SwapTreeSerializer, TaprootUtils, constructRefundTransaction, From 0a2556d0d46abb288e89c3e32b36047f8b11fb49 Mon Sep 17 00:00:00 2001 From: boufni95 Date: Wed, 4 Feb 2026 20:30:52 +0000 Subject: [PATCH 16/66] cleanup tmp fix --- src/services/main/adminManager.ts | 7 ------- src/services/main/init.ts | 1 - 2 files changed, 8 deletions(-) diff --git a/src/services/main/adminManager.ts b/src/services/main/adminManager.ts index e9695dc2..84ff5537 100644 --- a/src/services/main/adminManager.ts +++ b/src/services/main/adminManager.ts @@ -271,13 +271,6 @@ export class AdminManager { return { quotes } } - TMP_FIX_ADMIN_TX_ID = async () => { - this.log("fixing tmp admin tx") - await this.storage.paymentStorage.UpdateInvoiceSwap("6089e1e5-2178-418e-ae19-d32ac5eb1a84", { - used: false, failure_reason: "", tx_id: "f997b521ce1374a85e40a0fee5ad40692338b0f5965002b9f07d141cdbe03036" - }) - } - async PayAdminInvoiceSwap(req: Types.PayAdminInvoiceSwapRequest): Promise { const txId = await new Promise(res => { this.swaps.PayInvoiceSwap("admin", req.swap_operation_id, req.sat_per_v_byte, async (addr, amt) => { diff --git a/src/services/main/init.ts b/src/services/main/init.ts index acfe44f9..946061fb 100644 --- a/src/services/main/init.ts +++ b/src/services/main/init.ts @@ -79,7 +79,6 @@ export const initMainHandler = async (log: PubLogger, settingsManager: SettingsM await mainHandler.paymentManager.CleanupOldUnpaidInvoices() await mainHandler.appUserManager.CleanupInactiveUsers() await mainHandler.appUserManager.CleanupNeverActiveUsers() - await adminManager.TMP_FIX_ADMIN_TX_ID() await swaps.ResumeInvoiceSwaps() await mainHandler.paymentManager.watchDog.Start() return { mainHandler, apps, localProviderClient, wizard, adminManager } From 3a6b22cff8fb699afa54091a611e7197e907a94a Mon Sep 17 00:00:00 2001 From: boufni95 Date: Thu, 5 Feb 2026 19:00:00 +0000 Subject: [PATCH 17/66] swap fixes --- src/services/main/adminManager.ts | 10 +++++----- src/services/storage/paymentStorage.ts | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/services/main/adminManager.ts b/src/services/main/adminManager.ts index 84ff5537..1581c245 100644 --- a/src/services/main/adminManager.ts +++ b/src/services/main/adminManager.ts @@ -272,11 +272,11 @@ export class AdminManager { } async PayAdminInvoiceSwap(req: Types.PayAdminInvoiceSwapRequest): Promise { - const txId = await new Promise(res => { + const resolvedTxId = await new Promise(res => { this.swaps.PayInvoiceSwap("admin", req.swap_operation_id, req.sat_per_v_byte, async (addr, amt) => { const tx = await this.lnd.PayAddress(addr, amt, req.sat_per_v_byte, "", { useProvider: false, from: 'system' }) this.log("paid admin invoice swap", { swapOpId: req.swap_operation_id, txId: tx.txid }) - await this.storage.metricsStorage.AddRootOperation("chain_payment", txId, amt) + await this.storage.metricsStorage.AddRootOperation("chain_payment", tx.txid, amt) // Fetch the full transaction hex for potential refunds let lockupTxHex: string | undefined @@ -287,13 +287,13 @@ export class AdminManager { this.log("Warning: Could not fetch transaction hex for refund purposes:", err.message) } - await this.storage.paymentStorage.SetInvoiceSwapTxId(req.swap_operation_id, txId, lockupTxHex) - this.log("saved admin swap txid", { swapOpId: req.swap_operation_id, txId }) + await this.storage.paymentStorage.SetInvoiceSwapTxId(req.swap_operation_id, tx.txid, lockupTxHex) + this.log("saved admin swap txid", { swapOpId: req.swap_operation_id, txId: tx.txid }) res(tx.txid) return { txId: tx.txid } }) }) - return { tx_id: txId } + return { tx_id: resolvedTxId } } async RefundAdminInvoiceSwap(req: Types.RefundAdminInvoiceSwapRequest): Promise { diff --git a/src/services/storage/paymentStorage.ts b/src/services/storage/paymentStorage.ts index d14138bd..5726c5cf 100644 --- a/src/services/storage/paymentStorage.ts +++ b/src/services/storage/paymentStorage.ts @@ -494,7 +494,7 @@ export default class { } async DeleteExpiredTransactionSwaps(currentHeight: number, txId?: string) { - return this.dbs.Delete('TransactionSwap', { timeout_block_height: LessThan(currentHeight) }, txId) + return this.dbs.Delete('TransactionSwap', { timeout_block_height: LessThan(currentHeight), used: false }, txId) } async ListPendingTransactionSwaps(appUserId: string, txId?: string) { @@ -561,7 +561,7 @@ export default class { } async DeleteExpiredInvoiceSwaps(currentHeight: number, txId?: string) { - return this.dbs.Delete('InvoiceSwap', { timeout_block_height: LessThan(currentHeight) }, txId) + return this.dbs.Delete('InvoiceSwap', { timeout_block_height: LessThan(currentHeight), used: false, tx_id: "" }, txId) } async ListCompletedInvoiceSwaps(appUserId: string, txId?: string) { From 81f7400748d601963883094c2ef1de2d5727d5e0 Mon Sep 17 00:00:00 2001 From: boufni95 Date: Thu, 5 Feb 2026 20:07:57 +0000 Subject: [PATCH 18/66] socket ping pong --- src/services/lnd/swaps/reverseSwaps.ts | 7 +++++++ src/services/lnd/swaps/submarineSwaps.ts | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/src/services/lnd/swaps/reverseSwaps.ts b/src/services/lnd/swaps/reverseSwaps.ts index a8bd6ade..14dc4d44 100644 --- a/src/services/lnd/swaps/reverseSwaps.ts +++ b/src/services/lnd/swaps/reverseSwaps.ts @@ -121,9 +121,13 @@ export class ReverseSwaps { webSocket.on('open', () => { webSocket.send(JSON.stringify(subReq)) }) + const interval = setInterval(() => { + webSocket.ping() + }, 30 * 1000) let txId = "", isDone = false const done = (failureReason?: string) => { isDone = true + clearInterval(interval) webSocket.close() if (failureReason) { swapDone({ ok: false, error: failureReason }) @@ -131,6 +135,9 @@ export class ReverseSwaps { swapDone({ ok: true, txId }) } } + webSocket.on('pong', () => { + this.log('WebSocket transaction swap pong received') + }) webSocket.on('error', (err) => { this.log(ERROR, 'Error in WebSocket', err.message) }) diff --git a/src/services/lnd/swaps/submarineSwaps.ts b/src/services/lnd/swaps/submarineSwaps.ts index 56ce40e3..32ed1fac 100644 --- a/src/services/lnd/swaps/submarineSwaps.ts +++ b/src/services/lnd/swaps/submarineSwaps.ts @@ -376,9 +376,13 @@ export class SubmarineSwaps { webSocket.on('open', () => { webSocket.send(JSON.stringify(subReq)) }) + const interval = setInterval(() => { + webSocket.ping() + }, 30 * 1000) let isDone = false const done = (failureReason?: string) => { isDone = true + clearInterval(interval) webSocket.close() if (failureReason) { swapDone({ ok: false, error: failureReason }) @@ -386,6 +390,9 @@ export class SubmarineSwaps { swapDone({ ok: true }) } } + webSocket.on('pong', () => { + this.log('WebSocket invoice swap pong received') + }) webSocket.on('error', (err) => { this.log(ERROR, 'Error in WebSocket', err.message) }) From 9fe681d73bc0c106984b691a07d62836f0a922ee Mon Sep 17 00:00:00 2001 From: shocknet-justin Date: Thu, 5 Feb 2026 15:46:39 -0500 Subject: [PATCH 19/66] swap clear interval --- src/services/lnd/swaps/reverseSwaps.ts | 4 +--- src/services/lnd/swaps/submarineSwaps.ts | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/services/lnd/swaps/reverseSwaps.ts b/src/services/lnd/swaps/reverseSwaps.ts index 14dc4d44..83dddc37 100644 --- a/src/services/lnd/swaps/reverseSwaps.ts +++ b/src/services/lnd/swaps/reverseSwaps.ts @@ -155,9 +155,7 @@ export class ReverseSwaps { } } catch (err: any) { this.log(ERROR, 'Error handling transaction WebSocket message', err.message) - isDone = true - webSocket.close() - swapDone({ ok: false, error: err.message }) + done(err.message) return } }) diff --git a/src/services/lnd/swaps/submarineSwaps.ts b/src/services/lnd/swaps/submarineSwaps.ts index 32ed1fac..462f4751 100644 --- a/src/services/lnd/swaps/submarineSwaps.ts +++ b/src/services/lnd/swaps/submarineSwaps.ts @@ -407,7 +407,7 @@ export class SubmarineSwaps { await this.handleSwapInvoiceMessage(rawMsg, data, done, waitingTx) } catch (err: any) { this.log(ERROR, 'Error handling invoice WebSocket message', err.message) - webSocket.close() + done(err.message) return } }); From 3389045de708adfa4db70aab822b662679e552d2 Mon Sep 17 00:00:00 2001 From: boufni95 Date: Fri, 6 Feb 2026 20:23:09 +0000 Subject: [PATCH 20/66] missing ops --- src/services/lnd/lnd.ts | 1 - src/services/metrics/index.ts | 9 +++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/services/lnd/lnd.ts b/src/services/lnd/lnd.ts index f4548aef..3d66b268 100644 --- a/src/services/lnd/lnd.ts +++ b/src/services/lnd/lnd.ts @@ -715,7 +715,6 @@ export default class { } async GetTx(txid: string) { - this.log("Getting transaction") const res = await this.walletKit.getTransaction({ txid }, DeadLineMetadata()) return res.response } diff --git a/src/services/metrics/index.ts b/src/services/metrics/index.ts index 3dbafedb..20c92a95 100644 --- a/src/services/metrics/index.ts +++ b/src/services/metrics/index.ts @@ -425,8 +425,13 @@ export default class Handler { const mapRootOpType = (opType: string): Types.OperationType => { switch (opType) { - case "chain": return Types.OperationType.CHAIN_OP - case "invoice": return Types.OperationType.INVOICE_OP + case "chain_payment": + case "chain": + return Types.OperationType.CHAIN_OP + case "invoice_payment": + case "invoice": + return Types.OperationType.INVOICE_OP + default: throw new Error("Unknown operation type") } } \ No newline at end of file From e271d35c2d748913135841f07ac0730419aa9a13 Mon Sep 17 00:00:00 2001 From: boufni95 Date: Tue, 10 Feb 2026 17:04:49 +0000 Subject: [PATCH 21/66] restart sub p --- src/services/nostr/index.ts | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/services/nostr/index.ts b/src/services/nostr/index.ts index 3cd90e88..d544a286 100644 --- a/src/services/nostr/index.ts +++ b/src/services/nostr/index.ts @@ -11,19 +11,31 @@ export default class NostrSubprocess { utils: Utils awaitingPongs: (() => void)[] = [] log = getLogger({}) + latestRestart = 0 constructor(settings: NostrSettings, utils: Utils, eventCallback: EventCallback, beaconCallback: BeaconCallback) { this.utils = utils + this.startSubProcess(settings, eventCallback, beaconCallback) + } + + startSubProcess(settings: NostrSettings, eventCallback: EventCallback, beaconCallback: BeaconCallback) { this.childProcess = fork("./build/src/services/nostr/handler") this.childProcess.on("error", (error) => { this.log(ERROR, "nostr subprocess error", error) }) this.childProcess.on("exit", (code, signal) => { - this.log(ERROR, `nostr subprocess exited with code ${code} and signal ${signal}`) if (code === 0) { + this.log("nostr subprocess exited") return } - throw new Error(`nostr subprocess exited with code ${code} and signal ${signal}`) + this.log(ERROR, `nostr subprocess exited with code ${code} and signal ${signal}`) + const now = Date.now() + if (now - this.latestRestart < 1000 * 5) { + this.log(ERROR, "nostr subprocess exited too quickly") + throw new Error("nostr subprocess exited too quickly") + } + this.latestRestart = now + this.startSubProcess(settings, eventCallback, beaconCallback) }) this.childProcess.on("message", (message: ChildProcessResponse) => { @@ -50,6 +62,8 @@ export default class NostrSubprocess { } }) } + + sendToChildProcess(message: ChildProcessRequest) { this.childProcess.send(message) } From c3e3f99c7d4942a7dc81dd9760fc1822ff1a73d2 Mon Sep 17 00:00:00 2001 From: shocknet-justin Date: Tue, 10 Feb 2026 17:36:37 -0500 Subject: [PATCH 22/66] fix subprocess restart issues - Fix event listener memory leak by removing all listeners before restart - Properly cleanup old process with SIGTERM before forking new one - Fix Stop() to actually kill process (was using kill(0) which only checks existence) - Store callbacks in instance to avoid re-attaching listeners on restart - Add isShuttingDown flag to prevent restart when stopping intentionally - Add 100ms delay before restart to ensure clean process termination - Check if process is killed before sending messages - Update Reset() to store new settings for future restarts Co-authored-by: Cursor --- src/services/nostr/index.ts | 65 ++++++++++++++++++++++++++++--------- 1 file changed, 49 insertions(+), 16 deletions(-) diff --git a/src/services/nostr/index.ts b/src/services/nostr/index.ts index d544a286..5b2f0ddc 100644 --- a/src/services/nostr/index.ts +++ b/src/services/nostr/index.ts @@ -12,39 +12,68 @@ export default class NostrSubprocess { awaitingPongs: (() => void)[] = [] log = getLogger({}) latestRestart = 0 + private settings: NostrSettings + private eventCallback: EventCallback + private beaconCallback: BeaconCallback + private isShuttingDown = false + constructor(settings: NostrSettings, utils: Utils, eventCallback: EventCallback, beaconCallback: BeaconCallback) { this.utils = utils - this.startSubProcess(settings, eventCallback, beaconCallback) + this.settings = settings + this.eventCallback = eventCallback + this.beaconCallback = beaconCallback + this.startSubProcess() } - startSubProcess(settings: NostrSettings, eventCallback: EventCallback, beaconCallback: BeaconCallback) { + private cleanupProcess() { + if (this.childProcess) { + this.childProcess.removeAllListeners() + if (!this.childProcess.killed) { + this.childProcess.kill('SIGTERM') + } + } + } + + private startSubProcess() { + this.cleanupProcess() + this.childProcess = fork("./build/src/services/nostr/handler") + this.childProcess.on("error", (error) => { this.log(ERROR, "nostr subprocess error", error) }) this.childProcess.on("exit", (code, signal) => { - if (code === 0) { - this.log("nostr subprocess exited") + if (this.isShuttingDown) { + this.log("nostr subprocess stopped") return } - this.log(ERROR, `nostr subprocess exited with code ${code} and signal ${signal}`) - const now = Date.now() - if (now - this.latestRestart < 1000 * 5) { - this.log(ERROR, "nostr subprocess exited too quickly") - throw new Error("nostr subprocess exited too quickly") + + if (code === 0) { + this.log("nostr subprocess exited cleanly") + return } + + this.log(ERROR, `nostr subprocess exited with code ${code} and signal ${signal}`) + + const now = Date.now() + if (now - this.latestRestart < 5000) { + this.log(ERROR, "nostr subprocess exited too quickly, not restarting") + throw new Error("nostr subprocess crashed repeatedly") + } + + this.log("restarting nostr subprocess...") this.latestRestart = now - this.startSubProcess(settings, eventCallback, beaconCallback) + setTimeout(() => this.startSubProcess(), 100) }) this.childProcess.on("message", (message: ChildProcessResponse) => { switch (message.type) { case 'ready': - this.sendToChildProcess({ type: 'settings', settings: settings }) + this.sendToChildProcess({ type: 'settings', settings: this.settings }) break; case 'event': - eventCallback(message.event) + this.eventCallback(message.event) break case 'processMetrics': this.utils.tlvStorageFactory.ProcessMetrics(message.metrics, 'nostr') @@ -54,7 +83,7 @@ export default class NostrSubprocess { this.awaitingPongs = [] break case 'beacon': - beaconCallback({ content: message.content, pub: message.pub }) + this.beaconCallback({ content: message.content, pub: message.pub }) break default: console.error("unknown nostr event response", message) @@ -63,12 +92,14 @@ export default class NostrSubprocess { }) } - sendToChildProcess(message: ChildProcessRequest) { - this.childProcess.send(message) + if (this.childProcess && !this.childProcess.killed) { + this.childProcess.send(message) + } } Reset(settings: NostrSettings) { + this.settings = settings this.sendToChildProcess({ type: 'settings', settings }) } @@ -82,7 +113,9 @@ export default class NostrSubprocess { Send(initiator: SendInitiator, data: SendData, relays?: string[]) { this.sendToChildProcess({ type: 'send', data, initiator, relays }) } + Stop() { - this.childProcess.kill(0) + this.isShuttingDown = true + this.cleanupProcess() } } From edbbbd4aecb150078939cbc23eed6d693e853d79 Mon Sep 17 00:00:00 2001 From: boufni95 Date: Tue, 17 Feb 2026 18:12:33 +0000 Subject: [PATCH 23/66] add time info to swaps --- datasource.js | 5 +- proto/autogenerated/client.md | 9 ++-- proto/autogenerated/go/types.go | 15 +++--- proto/autogenerated/ts/types.ts | 51 ++++++++++--------- proto/service/structs.proto | 9 ++-- src/services/lnd/swaps/swaps.ts | 51 +++++++++++-------- src/services/main/adminManager.ts | 4 +- src/services/nostr/index.ts | 16 +++--- src/services/storage/entity/InvoiceSwap.ts | 6 +++ .../1771347307798-swap_timestamps.ts | 20 ++++++++ src/services/storage/migrations/runner.ts | 4 +- src/services/storage/paymentStorage.ts | 9 +++- 12 files changed, 124 insertions(+), 75 deletions(-) create mode 100644 src/services/storage/migrations/1771347307798-swap_timestamps.ts diff --git a/datasource.js b/datasource.js index 081634d8..9c291b25 100644 --- a/datasource.js +++ b/datasource.js @@ -50,6 +50,7 @@ import { ClinkRequester1765497600000 } from './build/src/services/storage/migrat import { TrackedProviderHeight1766504040000 } from './build/src/services/storage/migrations/1766504040000-tracked_provider_height.js' import { SwapsServiceUrl1768413055036 } from './build/src/services/storage/migrations/1768413055036-swaps_service_url.js' import { InvoiceSwaps1769529793283 } from './build/src/services/storage/migrations/1769529793283-invoice_swaps.js' +import { InvoiceSwapsFixes1769805357459 } from './build/src/services/storage/migrations/1769805357459-invoice_swaps_fixes.js' export default new DataSource({ type: "better-sqlite3", @@ -59,11 +60,11 @@ export default new DataSource({ PaymentIndex1721760297610, DebitAccess1726496225078, DebitAccessFixes1726685229264, DebitToPub1727105758354, UserCbUrl1727112281043, UserOffer1733502626042, ManagementGrant1751307732346, InvoiceCallbackUrls1752425992291, OldSomethingLeftover1753106599604, UserReceivingInvoiceIdx1753109184611, AppUserDevice1753285173175, UserAccess1759426050669, AddBlindToUserOffer1760000000000, ApplicationAvatarUrl1761000001000, AdminSettings1761683639419, TxSwap1762890527098, - TxSwapAddress1764779178945, ClinkRequester1765497600000, TrackedProviderHeight1766504040000, SwapsServiceUrl1768413055036, InvoiceSwaps1769529793283], + TxSwapAddress1764779178945, ClinkRequester1765497600000, TrackedProviderHeight1766504040000, SwapsServiceUrl1768413055036, InvoiceSwaps1769529793283, InvoiceSwapsFixes1769805357459], entities: [User, UserReceivingInvoice, UserReceivingAddress, AddressReceivingTransaction, UserInvoicePayment, UserTransactionPayment, UserBasicAuth, UserEphemeralKey, Product, UserToUserPayment, Application, ApplicationUser, UserToUserPayment, LspOrder, LndNodeInfo, TrackedProvider, InviteToken, DebitAccess, UserOffer, ManagementGrant, AppUserDevice, UserAccess, AdminSettings, TransactionSwap, InvoiceSwap], // synchronize: true, }) -//npx typeorm migration:generate ./src/services/storage/migrations/invoice_swaps_fixes -d ./datasource.js \ No newline at end of file +//npx typeorm migration:generate ./src/services/storage/migrations/swap_timestamps -d ./datasource.js \ No newline at end of file diff --git a/proto/autogenerated/client.md b/proto/autogenerated/client.md index 75b44d4e..679e0d30 100644 --- a/proto/autogenerated/client.md +++ b/proto/autogenerated/client.md @@ -1383,17 +1383,18 @@ The nostr server will send back a message response, and inside the body there wi - __url__: _string_ ### InvoiceSwapOperation + - __completed_at_unix__: _number_ *this field is optional - __failure_reason__: _string_ *this field is optional - - __invoice_paid__: _string_ - __operation_payment__: _[UserOperation](#UserOperation)_ *this field is optional - - __swap_operation_id__: _string_ - - __tx_id__: _string_ + - __quote__: _[InvoiceSwapQuote](#InvoiceSwapQuote)_ ### InvoiceSwapQuote - __address__: _string_ - __chain_fee_sats__: _number_ + - __expires_at_block_height__: _number_ - __invoice__: _string_ - __invoice_amount_sats__: _number_ + - __paid_at_unix__: _number_ - __service_fee_sats__: _number_ - __service_url__: _string_ - __swap_fee_sats__: _number_ @@ -1408,7 +1409,7 @@ The nostr server will send back a message response, and inside the body there wi - __amount_sats__: _number_ ### InvoiceSwapsList - - __quotes__: ARRAY of: _[InvoiceSwapQuote](#InvoiceSwapQuote)_ + - __current_block_height__: _number_ - __swaps__: ARRAY of: _[InvoiceSwapOperation](#InvoiceSwapOperation)_ ### LatestBundleMetricReq diff --git a/proto/autogenerated/go/types.go b/proto/autogenerated/go/types.go index 2c79cb0a..a59adaaf 100644 --- a/proto/autogenerated/go/types.go +++ b/proto/autogenerated/go/types.go @@ -360,17 +360,18 @@ type HttpCreds struct { Url string `json:"url"` } type InvoiceSwapOperation struct { - Failure_reason string `json:"failure_reason"` - Invoice_paid string `json:"invoice_paid"` - Operation_payment *UserOperation `json:"operation_payment"` - Swap_operation_id string `json:"swap_operation_id"` - Tx_id string `json:"tx_id"` + Completed_at_unix int64 `json:"completed_at_unix"` + Failure_reason string `json:"failure_reason"` + Operation_payment *UserOperation `json:"operation_payment"` + Quote *InvoiceSwapQuote `json:"quote"` } type InvoiceSwapQuote struct { Address string `json:"address"` Chain_fee_sats int64 `json:"chain_fee_sats"` + Expires_at_block_height int64 `json:"expires_at_block_height"` Invoice string `json:"invoice"` Invoice_amount_sats int64 `json:"invoice_amount_sats"` + Paid_at_unix int64 `json:"paid_at_unix"` Service_fee_sats int64 `json:"service_fee_sats"` Service_url string `json:"service_url"` Swap_fee_sats int64 `json:"swap_fee_sats"` @@ -385,8 +386,8 @@ type InvoiceSwapRequest struct { Amount_sats int64 `json:"amount_sats"` } type InvoiceSwapsList struct { - Quotes []InvoiceSwapQuote `json:"quotes"` - Swaps []InvoiceSwapOperation `json:"swaps"` + Current_block_height int64 `json:"current_block_height"` + Swaps []InvoiceSwapOperation `json:"swaps"` } type LatestBundleMetricReq struct { Limit int64 `json:"limit"` diff --git a/proto/autogenerated/ts/types.ts b/proto/autogenerated/ts/types.ts index 17fec2b1..82f2c1fe 100644 --- a/proto/autogenerated/ts/types.ts +++ b/proto/autogenerated/ts/types.ts @@ -2123,43 +2123,39 @@ export const HttpCredsValidate = (o?: HttpCreds, opts: HttpCredsOptions = {}, pa } export type InvoiceSwapOperation = { + completed_at_unix?: number failure_reason?: string - invoice_paid: string operation_payment?: UserOperation - swap_operation_id: string - tx_id: string + quote: InvoiceSwapQuote } -export type InvoiceSwapOperationOptionalField = 'failure_reason' | 'operation_payment' -export const InvoiceSwapOperationOptionalFields: InvoiceSwapOperationOptionalField[] = ['failure_reason', 'operation_payment'] +export type InvoiceSwapOperationOptionalField = 'completed_at_unix' | 'failure_reason' | 'operation_payment' +export const InvoiceSwapOperationOptionalFields: InvoiceSwapOperationOptionalField[] = ['completed_at_unix', 'failure_reason', 'operation_payment'] export type InvoiceSwapOperationOptions = OptionsBaseMessage & { checkOptionalsAreSet?: InvoiceSwapOperationOptionalField[] + completed_at_unix_CustomCheck?: (v?: number) => boolean failure_reason_CustomCheck?: (v?: string) => boolean - invoice_paid_CustomCheck?: (v: string) => boolean operation_payment_Options?: UserOperationOptions - swap_operation_id_CustomCheck?: (v: string) => boolean - tx_id_CustomCheck?: (v: string) => boolean + quote_Options?: InvoiceSwapQuoteOptions } export const InvoiceSwapOperationValidate = (o?: InvoiceSwapOperation, opts: InvoiceSwapOperationOptions = {}, path: string = 'InvoiceSwapOperation::root.'): Error | null => { if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message') if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null') + if ((o.completed_at_unix || opts.allOptionalsAreSet || opts.checkOptionalsAreSet?.includes('completed_at_unix')) && typeof o.completed_at_unix !== 'number') return new Error(`${path}.completed_at_unix: is not a number`) + if (opts.completed_at_unix_CustomCheck && !opts.completed_at_unix_CustomCheck(o.completed_at_unix)) return new Error(`${path}.completed_at_unix: custom check failed`) + if ((o.failure_reason || opts.allOptionalsAreSet || opts.checkOptionalsAreSet?.includes('failure_reason')) && typeof o.failure_reason !== 'string') return new Error(`${path}.failure_reason: is not a string`) if (opts.failure_reason_CustomCheck && !opts.failure_reason_CustomCheck(o.failure_reason)) return new Error(`${path}.failure_reason: custom check failed`) - if (typeof o.invoice_paid !== 'string') return new Error(`${path}.invoice_paid: is not a string`) - if (opts.invoice_paid_CustomCheck && !opts.invoice_paid_CustomCheck(o.invoice_paid)) return new Error(`${path}.invoice_paid: custom check failed`) - if (typeof o.operation_payment === 'object' || opts.allOptionalsAreSet || opts.checkOptionalsAreSet?.includes('operation_payment')) { const operation_paymentErr = UserOperationValidate(o.operation_payment, opts.operation_payment_Options, `${path}.operation_payment`) if (operation_paymentErr !== null) return operation_paymentErr } - if (typeof o.swap_operation_id !== 'string') return new Error(`${path}.swap_operation_id: is not a string`) - if (opts.swap_operation_id_CustomCheck && !opts.swap_operation_id_CustomCheck(o.swap_operation_id)) return new Error(`${path}.swap_operation_id: custom check failed`) - - if (typeof o.tx_id !== 'string') return new Error(`${path}.tx_id: is not a string`) - if (opts.tx_id_CustomCheck && !opts.tx_id_CustomCheck(o.tx_id)) return new Error(`${path}.tx_id: custom check failed`) + const quoteErr = InvoiceSwapQuoteValidate(o.quote, opts.quote_Options, `${path}.quote`) + if (quoteErr !== null) return quoteErr + return null } @@ -2167,8 +2163,10 @@ export const InvoiceSwapOperationValidate = (o?: InvoiceSwapOperation, opts: Inv export type InvoiceSwapQuote = { address: string chain_fee_sats: number + expires_at_block_height: number invoice: string invoice_amount_sats: number + paid_at_unix: number service_fee_sats: number service_url: string swap_fee_sats: number @@ -2181,8 +2179,10 @@ export type InvoiceSwapQuoteOptions = OptionsBaseMessage & { checkOptionalsAreSet?: [] address_CustomCheck?: (v: string) => boolean chain_fee_sats_CustomCheck?: (v: number) => boolean + expires_at_block_height_CustomCheck?: (v: number) => boolean invoice_CustomCheck?: (v: string) => boolean invoice_amount_sats_CustomCheck?: (v: number) => boolean + paid_at_unix_CustomCheck?: (v: number) => boolean service_fee_sats_CustomCheck?: (v: number) => boolean service_url_CustomCheck?: (v: string) => boolean swap_fee_sats_CustomCheck?: (v: number) => boolean @@ -2200,12 +2200,18 @@ export const InvoiceSwapQuoteValidate = (o?: InvoiceSwapQuote, opts: InvoiceSwap if (typeof o.chain_fee_sats !== 'number') return new Error(`${path}.chain_fee_sats: is not a number`) if (opts.chain_fee_sats_CustomCheck && !opts.chain_fee_sats_CustomCheck(o.chain_fee_sats)) return new Error(`${path}.chain_fee_sats: custom check failed`) + if (typeof o.expires_at_block_height !== 'number') return new Error(`${path}.expires_at_block_height: is not a number`) + if (opts.expires_at_block_height_CustomCheck && !opts.expires_at_block_height_CustomCheck(o.expires_at_block_height)) return new Error(`${path}.expires_at_block_height: custom check failed`) + if (typeof o.invoice !== 'string') return new Error(`${path}.invoice: is not a string`) if (opts.invoice_CustomCheck && !opts.invoice_CustomCheck(o.invoice)) return new Error(`${path}.invoice: custom check failed`) if (typeof o.invoice_amount_sats !== 'number') return new Error(`${path}.invoice_amount_sats: is not a number`) if (opts.invoice_amount_sats_CustomCheck && !opts.invoice_amount_sats_CustomCheck(o.invoice_amount_sats)) return new Error(`${path}.invoice_amount_sats: custom check failed`) + if (typeof o.paid_at_unix !== 'number') return new Error(`${path}.paid_at_unix: is not a number`) + if (opts.paid_at_unix_CustomCheck && !opts.paid_at_unix_CustomCheck(o.paid_at_unix)) return new Error(`${path}.paid_at_unix: custom check failed`) + if (typeof o.service_fee_sats !== 'number') return new Error(`${path}.service_fee_sats: is not a number`) if (opts.service_fee_sats_CustomCheck && !opts.service_fee_sats_CustomCheck(o.service_fee_sats)) return new Error(`${path}.service_fee_sats: custom check failed`) @@ -2269,14 +2275,13 @@ export const InvoiceSwapRequestValidate = (o?: InvoiceSwapRequest, opts: Invoice } export type InvoiceSwapsList = { - quotes: InvoiceSwapQuote[] + current_block_height: number swaps: InvoiceSwapOperation[] } export const InvoiceSwapsListOptionalFields: [] = [] export type InvoiceSwapsListOptions = OptionsBaseMessage & { checkOptionalsAreSet?: [] - quotes_ItemOptions?: InvoiceSwapQuoteOptions - quotes_CustomCheck?: (v: InvoiceSwapQuote[]) => boolean + current_block_height_CustomCheck?: (v: number) => boolean swaps_ItemOptions?: InvoiceSwapOperationOptions swaps_CustomCheck?: (v: InvoiceSwapOperation[]) => boolean } @@ -2284,12 +2289,8 @@ export const InvoiceSwapsListValidate = (o?: InvoiceSwapsList, opts: InvoiceSwap if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message') if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null') - if (!Array.isArray(o.quotes)) return new Error(`${path}.quotes: is not an array`) - for (let index = 0; index < o.quotes.length; index++) { - const quotesErr = InvoiceSwapQuoteValidate(o.quotes[index], opts.quotes_ItemOptions, `${path}.quotes[${index}]`) - if (quotesErr !== null) return quotesErr - } - if (opts.quotes_CustomCheck && !opts.quotes_CustomCheck(o.quotes)) return new Error(`${path}.quotes: custom check failed`) + if (typeof o.current_block_height !== 'number') return new Error(`${path}.current_block_height: is not a number`) + if (opts.current_block_height_CustomCheck && !opts.current_block_height_CustomCheck(o.current_block_height)) return new Error(`${path}.current_block_height: custom check failed`) if (!Array.isArray(o.swaps)) return new Error(`${path}.swaps: is not an array`) for (let index = 0; index < o.swaps.length; index++) { diff --git a/proto/service/structs.proto b/proto/service/structs.proto index 2ce6adc3..07b930da 100644 --- a/proto/service/structs.proto +++ b/proto/service/structs.proto @@ -848,6 +848,8 @@ message InvoiceSwapQuote { string service_url = 8; int64 swap_fee_sats = 9; string tx_id = 10; + int64 paid_at_unix = 11; + int64 expires_at_block_height = 12; } message InvoiceSwapQuoteList { @@ -855,16 +857,15 @@ message InvoiceSwapQuoteList { } message InvoiceSwapOperation { - string swap_operation_id = 1; + InvoiceSwapQuote quote = 1; optional UserOperation operation_payment = 2; optional string failure_reason = 3; - string invoice_paid = 4; - string tx_id = 5; + optional int64 completed_at_unix = 6; } message InvoiceSwapsList { repeated InvoiceSwapOperation swaps = 1; - repeated InvoiceSwapQuote quotes = 2; + int64 current_block_height = 3; } message RefundAdminInvoiceSwapRequest { diff --git a/src/services/lnd/swaps/swaps.ts b/src/services/lnd/swaps/swaps.ts index dc57309a..3a21d2f8 100644 --- a/src/services/lnd/swaps/swaps.ts +++ b/src/services/lnd/swaps/swaps.ts @@ -71,32 +71,37 @@ export class Swaps { return success } + private mapInvoiceSwapQuote = (s: InvoiceSwap): Types.InvoiceSwapQuote => { + return { + swap_operation_id: s.swap_operation_id, + invoice: s.invoice, + invoice_amount_sats: s.invoice_amount, + address: s.address, + transaction_amount_sats: s.transaction_amount, + chain_fee_sats: s.chain_fee_sats, + service_fee_sats: 0, + service_url: s.service_url, + swap_fee_sats: s.swap_fee_sats, + tx_id: s.tx_id, + paid_at_unix: s.paid_at_unix, + expires_at_block_height: s.timeout_block_height, + } + } + ListInvoiceSwaps = async (appUserId: string): Promise => { + const info = await this.lnd.GetInfo() + const currentBlockHeight = info.blockHeight const completedSwaps = await this.storage.paymentStorage.ListCompletedInvoiceSwaps(appUserId) const pendingSwaps = await this.storage.paymentStorage.ListPendingInvoiceSwaps(appUserId) + const quotes: Types.InvoiceSwapOperation[] = pendingSwaps.map(s => ({ quote: this.mapInvoiceSwapQuote(s) })) + const operations: Types.InvoiceSwapOperation[] = completedSwaps.map(s => ({ + quote: this.mapInvoiceSwapQuote(s), + failure_reason: s.failure_reason, + completed_at_unix: s.completed_at_unix || 1, + })) return { - swaps: completedSwaps.map(s => { - return { - invoice_paid: s.invoice, - swap_operation_id: s.swap_operation_id, - failure_reason: s.failure_reason, - tx_id: s.tx_id, - } - }), - quotes: pendingSwaps.map(s => { - return { - swap_operation_id: s.swap_operation_id, - invoice: s.invoice, - invoice_amount_sats: s.invoice_amount, - address: s.address, - transaction_amount_sats: s.transaction_amount, - chain_fee_sats: s.chain_fee_sats, - service_fee_sats: 0, - service_url: s.service_url, - swap_fee_sats: s.swap_fee_sats, - tx_id: s.tx_id, - } - }) + current_block_height: currentBlockHeight, + swaps: operations.concat(quotes), } } @@ -261,6 +266,8 @@ export class Swaps { service_url: swapper.getHttpUrl(), swap_fee_sats: fee, tx_id: newSwap.tx_id, + paid_at_unix: newSwap.paid_at_unix, + expires_at_block_height: newSwap.timeout_block_height, } } diff --git a/src/services/main/adminManager.ts b/src/services/main/adminManager.ts index 1581c245..4449e9ca 100644 --- a/src/services/main/adminManager.ts +++ b/src/services/main/adminManager.ts @@ -280,14 +280,16 @@ export class AdminManager { // Fetch the full transaction hex for potential refunds let lockupTxHex: string | undefined + let chainFeeSats = 0 try { const txDetails = await this.lnd.GetTx(tx.txid) + chainFeeSats = Number(txDetails.totalFees) lockupTxHex = txDetails.rawTxHex } catch (err: any) { this.log("Warning: Could not fetch transaction hex for refund purposes:", err.message) } - await this.storage.paymentStorage.SetInvoiceSwapTxId(req.swap_operation_id, tx.txid, lockupTxHex) + await this.storage.paymentStorage.SetInvoiceSwapTxId(req.swap_operation_id, tx.txid, chainFeeSats, lockupTxHex) this.log("saved admin swap txid", { swapOpId: req.swap_operation_id, txId: tx.txid }) res(tx.txid) return { txId: tx.txid } diff --git a/src/services/nostr/index.ts b/src/services/nostr/index.ts index 5b2f0ddc..ffa636b6 100644 --- a/src/services/nostr/index.ts +++ b/src/services/nostr/index.ts @@ -16,7 +16,7 @@ export default class NostrSubprocess { private eventCallback: EventCallback private beaconCallback: BeaconCallback private isShuttingDown = false - + constructor(settings: NostrSettings, utils: Utils, eventCallback: EventCallback, beaconCallback: BeaconCallback) { this.utils = utils this.settings = settings @@ -36,9 +36,9 @@ export default class NostrSubprocess { private startSubProcess() { this.cleanupProcess() - + this.childProcess = fork("./build/src/services/nostr/handler") - + this.childProcess.on("error", (error) => { this.log(ERROR, "nostr subprocess error", error) }) @@ -48,20 +48,20 @@ export default class NostrSubprocess { this.log("nostr subprocess stopped") return } - + if (code === 0) { this.log("nostr subprocess exited cleanly") return } - + this.log(ERROR, `nostr subprocess exited with code ${code} and signal ${signal}`) - + const now = Date.now() if (now - this.latestRestart < 5000) { this.log(ERROR, "nostr subprocess exited too quickly, not restarting") throw new Error("nostr subprocess crashed repeatedly") } - + this.log("restarting nostr subprocess...") this.latestRestart = now setTimeout(() => this.startSubProcess(), 100) @@ -113,7 +113,7 @@ export default class NostrSubprocess { Send(initiator: SendInitiator, data: SendData, relays?: string[]) { this.sendToChildProcess({ type: 'send', data, initiator, relays }) } - + Stop() { this.isShuttingDown = true this.cleanupProcess() diff --git a/src/services/storage/entity/InvoiceSwap.ts b/src/services/storage/entity/InvoiceSwap.ts index f435edab..746756b8 100644 --- a/src/services/storage/entity/InvoiceSwap.ts +++ b/src/services/storage/entity/InvoiceSwap.ts @@ -62,6 +62,12 @@ export class InvoiceSwap { @Column({ default: false }) used: boolean + @Column({ default: 0 }) + completed_at_unix: number + + @Column({ default: 0 }) + paid_at_unix: number + @Column({ default: "" }) preimage: string diff --git a/src/services/storage/migrations/1771347307798-swap_timestamps.ts b/src/services/storage/migrations/1771347307798-swap_timestamps.ts new file mode 100644 index 00000000..ce5c0b39 --- /dev/null +++ b/src/services/storage/migrations/1771347307798-swap_timestamps.ts @@ -0,0 +1,20 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class SwapTimestamps1771347307798 implements MigrationInterface { + name = 'SwapTimestamps1771347307798' + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(`CREATE TABLE "temporary_invoice_swap" ("swap_operation_id" varchar PRIMARY KEY NOT NULL, "app_user_id" varchar NOT NULL, "swap_quote_id" varchar NOT NULL, "swap_tree" varchar NOT NULL, "claim_public_key" varchar NOT NULL, "payment_hash" varchar NOT NULL, "timeout_block_height" integer NOT NULL, "invoice" varchar NOT NULL, "invoice_amount" integer NOT NULL, "transaction_amount" integer NOT NULL, "swap_fee_sats" integer NOT NULL, "chain_fee_sats" integer NOT NULL, "ephemeral_public_key" varchar NOT NULL, "address" varchar NOT NULL, "ephemeral_private_key" varchar NOT NULL, "used" boolean NOT NULL DEFAULT (0), "preimage" varchar NOT NULL DEFAULT (''), "failure_reason" varchar NOT NULL DEFAULT (''), "tx_id" varchar NOT NULL DEFAULT (''), "service_url" varchar NOT NULL DEFAULT (''), "created_at" datetime NOT NULL DEFAULT (datetime('now')), "updated_at" datetime NOT NULL DEFAULT (datetime('now')), "lockup_tx_hex" text NOT NULL DEFAULT (''), "completed_at_unix" integer NOT NULL DEFAULT (0), "paid_at_unix" integer NOT NULL DEFAULT (0))`); + await queryRunner.query(`INSERT INTO "temporary_invoice_swap"("swap_operation_id", "app_user_id", "swap_quote_id", "swap_tree", "claim_public_key", "payment_hash", "timeout_block_height", "invoice", "invoice_amount", "transaction_amount", "swap_fee_sats", "chain_fee_sats", "ephemeral_public_key", "address", "ephemeral_private_key", "used", "preimage", "failure_reason", "tx_id", "service_url", "created_at", "updated_at", "lockup_tx_hex") SELECT "swap_operation_id", "app_user_id", "swap_quote_id", "swap_tree", "claim_public_key", "payment_hash", "timeout_block_height", "invoice", "invoice_amount", "transaction_amount", "swap_fee_sats", "chain_fee_sats", "ephemeral_public_key", "address", "ephemeral_private_key", "used", "preimage", "failure_reason", "tx_id", "service_url", "created_at", "updated_at", "lockup_tx_hex" FROM "invoice_swap"`); + await queryRunner.query(`DROP TABLE "invoice_swap"`); + await queryRunner.query(`ALTER TABLE "temporary_invoice_swap" RENAME TO "invoice_swap"`); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE "invoice_swap" RENAME TO "temporary_invoice_swap"`); + await queryRunner.query(`CREATE TABLE "invoice_swap" ("swap_operation_id" varchar PRIMARY KEY NOT NULL, "app_user_id" varchar NOT NULL, "swap_quote_id" varchar NOT NULL, "swap_tree" varchar NOT NULL, "claim_public_key" varchar NOT NULL, "payment_hash" varchar NOT NULL, "timeout_block_height" integer NOT NULL, "invoice" varchar NOT NULL, "invoice_amount" integer NOT NULL, "transaction_amount" integer NOT NULL, "swap_fee_sats" integer NOT NULL, "chain_fee_sats" integer NOT NULL, "ephemeral_public_key" varchar NOT NULL, "address" varchar NOT NULL, "ephemeral_private_key" varchar NOT NULL, "used" boolean NOT NULL DEFAULT (0), "preimage" varchar NOT NULL DEFAULT (''), "failure_reason" varchar NOT NULL DEFAULT (''), "tx_id" varchar NOT NULL DEFAULT (''), "service_url" varchar NOT NULL DEFAULT (''), "created_at" datetime NOT NULL DEFAULT (datetime('now')), "updated_at" datetime NOT NULL DEFAULT (datetime('now')), "lockup_tx_hex" text NOT NULL DEFAULT (''))`); + await queryRunner.query(`INSERT INTO "invoice_swap"("swap_operation_id", "app_user_id", "swap_quote_id", "swap_tree", "claim_public_key", "payment_hash", "timeout_block_height", "invoice", "invoice_amount", "transaction_amount", "swap_fee_sats", "chain_fee_sats", "ephemeral_public_key", "address", "ephemeral_private_key", "used", "preimage", "failure_reason", "tx_id", "service_url", "created_at", "updated_at", "lockup_tx_hex") SELECT "swap_operation_id", "app_user_id", "swap_quote_id", "swap_tree", "claim_public_key", "payment_hash", "timeout_block_height", "invoice", "invoice_amount", "transaction_amount", "swap_fee_sats", "chain_fee_sats", "ephemeral_public_key", "address", "ephemeral_private_key", "used", "preimage", "failure_reason", "tx_id", "service_url", "created_at", "updated_at", "lockup_tx_hex" FROM "temporary_invoice_swap"`); + await queryRunner.query(`DROP TABLE "temporary_invoice_swap"`); + } + +} diff --git a/src/services/storage/migrations/runner.ts b/src/services/storage/migrations/runner.ts index 0b08799a..eb5d7c19 100644 --- a/src/services/storage/migrations/runner.ts +++ b/src/services/storage/migrations/runner.ts @@ -34,13 +34,15 @@ import { TrackedProviderHeight1766504040000 } from './1766504040000-tracked_prov import { SwapsServiceUrl1768413055036 } from './1768413055036-swaps_service_url.js' import { InvoiceSwaps1769529793283 } from './1769529793283-invoice_swaps.js' import { InvoiceSwapsFixes1769805357459 } from './1769805357459-invoice_swaps_fixes.js' +import { SwapTimestamps1771347307798 } from './1771347307798-swap_timestamps.js' export const allMigrations = [Initial1703170309875, LspOrder1718387847693, LiquidityProvider1719335699480, LndNodeInfo1720187506189, TrackedProvider1720814323679, CreateInviteTokenTable1721751414878, PaymentIndex1721760297610, DebitAccess1726496225078, DebitAccessFixes1726685229264, DebitToPub1727105758354, UserCbUrl1727112281043, UserOffer1733502626042, ManagementGrant1751307732346, ManagementGrantBanned1751989251513, InvoiceCallbackUrls1752425992291, OldSomethingLeftover1753106599604, UserReceivingInvoiceIdx1753109184611, AppUserDevice1753285173175, UserAccess1759426050669, AddBlindToUserOffer1760000000000, ApplicationAvatarUrl1761000001000, AdminSettings1761683639419, TxSwap1762890527098, - TxSwapAddress1764779178945, ClinkRequester1765497600000, TrackedProviderHeight1766504040000, SwapsServiceUrl1768413055036, InvoiceSwaps1769529793283, InvoiceSwapsFixes1769805357459] + TxSwapAddress1764779178945, ClinkRequester1765497600000, TrackedProviderHeight1766504040000, SwapsServiceUrl1768413055036, + InvoiceSwaps1769529793283, InvoiceSwapsFixes1769805357459, SwapTimestamps1771347307798] export const allMetricsMigrations = [LndMetrics1703170330183, ChannelRouting1709316653538, HtlcCount1724266887195, BalanceEvents1724860966825, RootOps1732566440447, RootOpsTime1745428134124, ChannelEvents1750777346411] /* export const TypeOrmMigrationRunner = async (log: PubLogger, storageManager: Storage, settings: DbSettings, arg: string | undefined): Promise => { diff --git a/src/services/storage/paymentStorage.ts b/src/services/storage/paymentStorage.ts index 5726c5cf..785f9909 100644 --- a/src/services/storage/paymentStorage.ts +++ b/src/services/storage/paymentStorage.ts @@ -530,8 +530,10 @@ export default class { } async FinalizeInvoiceSwap(swapOperationId: string, txId?: string) { + const now = Math.floor(Date.now() / 1000) return this.dbs.Update('InvoiceSwap', { swap_operation_id: swapOperationId }, { used: true, + completed_at_unix: now, }, txId) } @@ -539,9 +541,12 @@ export default class { return this.dbs.Update('InvoiceSwap', { swap_operation_id: swapOperationId }, update, txId) } - async SetInvoiceSwapTxId(swapOperationId: string, chainTxId: string, lockupTxHex?: string, txId?: string) { + async SetInvoiceSwapTxId(swapOperationId: string, chainTxId: string, chainFeeSats: number, lockupTxHex?: string, txId?: string) { + const now = Math.floor(Date.now() / 1000) const update: Partial = { tx_id: chainTxId, + paid_at_unix: now, + chain_fee_sats: chainFeeSats, } if (lockupTxHex) { update.lockup_tx_hex = lockupTxHex @@ -550,9 +555,11 @@ export default class { } async FailInvoiceSwap(swapOperationId: string, failureReason: string, txId?: string) { + const now = Math.floor(Date.now() / 1000) return this.dbs.Update('InvoiceSwap', { swap_operation_id: swapOperationId }, { used: true, failure_reason: failureReason, + completed_at_unix: now, }, txId) } From a10cf126b36ce88a8499cc55396d96697724e96e Mon Sep 17 00:00:00 2001 From: shocknet-justin Date: Tue, 17 Feb 2026 13:53:02 -0500 Subject: [PATCH 24/66] comment --- datasource.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/datasource.js b/datasource.js index 9c291b25..7126f7de 100644 --- a/datasource.js +++ b/datasource.js @@ -1,3 +1,14 @@ +/** + * TypeORM DataSource used only by the TypeORM CLI (e.g. migration:generate). + * + * Migrations at runtime are run from src/services/storage/migrations/runner.ts (allMigrations), + * not from this file. The app never uses this DataSource to run migrations. + * + * Workflow: update the migrations array in this file *before* running + * migration:generate, so TypeORM knows the current schema (entities + existing migrations). + * We do not update this file immediately after adding a new migration; update it when you + * are about to generate the next migration. + */ import { DataSource } from "typeorm" import { User } from "./build/src/services/storage/entity/User.js" import { UserReceivingInvoice } from "./build/src/services/storage/entity/UserReceivingInvoice.js" From e32dff939ee58c796a332dfbccd14fdb77e4ed63 Mon Sep 17 00:00:00 2001 From: boufni95 Date: Tue, 17 Feb 2026 21:29:34 +0000 Subject: [PATCH 25/66] paid at unix default --- src/services/lnd/swaps/swaps.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/services/lnd/swaps/swaps.ts b/src/services/lnd/swaps/swaps.ts index 3a21d2f8..c5abad05 100644 --- a/src/services/lnd/swaps/swaps.ts +++ b/src/services/lnd/swaps/swaps.ts @@ -83,7 +83,7 @@ export class Swaps { service_url: s.service_url, swap_fee_sats: s.swap_fee_sats, tx_id: s.tx_id, - paid_at_unix: s.paid_at_unix, + paid_at_unix: s.paid_at_unix || (s.tx_id ? 1 : 0), expires_at_block_height: s.timeout_block_height, } } From 6da84340731755ca93495378877ec7b43595c72e Mon Sep 17 00:00:00 2001 From: boufni95 Date: Thu, 19 Feb 2026 18:11:41 +0000 Subject: [PATCH 26/66] account for root ops and change --- metricsDatasource.js | 8 ++- src/services/main/adminManager.ts | 2 +- src/services/main/watchdog.ts | 51 ++++++++++++++++--- src/services/storage/entity/RootOperation.ts | 3 ++ src/services/storage/metricsStorage.ts | 18 +++++-- .../1771524665409-root_op_pending.ts | 20 ++++++++ src/services/storage/migrations/runner.ts | 5 +- 7 files changed, 91 insertions(+), 16 deletions(-) create mode 100644 src/services/storage/migrations/1771524665409-root_op_pending.ts diff --git a/metricsDatasource.js b/metricsDatasource.js index 226b9dac..c1c3f493 100644 --- a/metricsDatasource.js +++ b/metricsDatasource.js @@ -8,12 +8,16 @@ import { LndMetrics1703170330183 } from './build/src/services/storage/migrations import { ChannelRouting1709316653538 } from './build/src/services/storage/migrations/1709316653538-channel_routing.js' import { HtlcCount1724266887195 } from './build/src/services/storage/migrations/1724266887195-htlc_count.js' import { BalanceEvents1724860966825 } from './build/src/services/storage/migrations/1724860966825-balance_events.js' +import { RootOps1732566440447 } from './build/src/services/storage/migrations/1732566440447-root_ops.js' +import { RootOpsTime1745428134124 } from './build/src/services/storage/migrations/1745428134124-root_ops_time.js' +import { ChannelEvents1750777346411 } from './build/src/services/storage/migrations/1750777346411-channel_events.js' export default new DataSource({ type: "better-sqlite3", database: "metrics.sqlite", entities: [BalanceEvent, ChannelBalanceEvent, ChannelRouting, RootOperation, ChannelEvent], - migrations: [LndMetrics1703170330183, ChannelRouting1709316653538, HtlcCount1724266887195, BalanceEvents1724860966825] + migrations: [LndMetrics1703170330183, ChannelRouting1709316653538, HtlcCount1724266887195, BalanceEvents1724860966825, + RootOps1732566440447, RootOpsTime1745428134124, ChannelEvents1750777346411] }); -//npx typeorm migration:generate ./src/services/storage/migrations/channel_events -d ./metricsDatasource.js \ No newline at end of file +//npx typeorm migration:generate ./src/services/storage/migrations/root_op_pending -d ./metricsDatasource.js \ No newline at end of file diff --git a/src/services/main/adminManager.ts b/src/services/main/adminManager.ts index 4449e9ca..e8147aa6 100644 --- a/src/services/main/adminManager.ts +++ b/src/services/main/adminManager.ts @@ -276,7 +276,7 @@ export class AdminManager { this.swaps.PayInvoiceSwap("admin", req.swap_operation_id, req.sat_per_v_byte, async (addr, amt) => { const tx = await this.lnd.PayAddress(addr, amt, req.sat_per_v_byte, "", { useProvider: false, from: 'system' }) this.log("paid admin invoice swap", { swapOpId: req.swap_operation_id, txId: tx.txid }) - await this.storage.metricsStorage.AddRootOperation("chain_payment", tx.txid, amt) + await this.storage.metricsStorage.AddRootOperation("chain_payment", tx.txid, amt, true) // Fetch the full transaction hex for potential refunds let lockupTxHex: string | undefined diff --git a/src/services/main/watchdog.ts b/src/services/main/watchdog.ts index 778e09ce..b02b9678 100644 --- a/src/services/main/watchdog.ts +++ b/src/services/main/watchdog.ts @@ -29,6 +29,7 @@ export class Watchdog { ready = false interval: NodeJS.Timer; lndPubKey: string; + lastHandlerRootOpsAtUnix = 0 constructor(settings: SettingsManager, liquidityManager: LiquidityManager, lnd: LND, storage: Storage, utils: Utils, rugPullTracker: RugPullTracker) { this.lnd = lnd; this.settings = settings; @@ -67,7 +68,7 @@ export class Watchdog { await this.getTracker() const totalUsersBalance = await this.storage.paymentStorage.GetTotalUsersBalance() this.utils.stateBundler.AddBalancePoint('usersBalance', totalUsersBalance) - const { totalExternal, otherExternal } = await this.getAggregatedExternalBalance() + const { totalExternal } = await this.getAggregatedExternalBalance() this.initialLndBalance = totalExternal this.initialUsersBalance = totalUsersBalance const fwEvents = await this.lnd.GetForwardingHistory(0, this.startedAtUnix) @@ -76,8 +77,6 @@ export class Watchdog { const paymentFound = await this.storage.paymentStorage.GetMaxPaymentIndex() const knownMaxIndex = paymentFound.length > 0 ? Math.max(paymentFound[0].paymentIndex, 0) : 0 this.latestPaymentIndexOffset = await this.lnd.GetLatestPaymentIndex(knownMaxIndex) - const other = { ilnd: this.initialLndBalance, hf: this.accumulatedHtlcFees, iu: this.initialUsersBalance, tu: totalUsersBalance, oext: otherExternal } - //getLogger({ component: 'watchdog_debug2' })(JSON.stringify({ deltaLnd: 0, deltaUsers: 0, totalExternal, latestIndex: this.latestPaymentIndexOffset, other })) this.interval = setInterval(() => { if (this.latestCheckStart + (1000 * 58) < Date.now()) { this.PaymentRequested() @@ -93,7 +92,44 @@ export class Watchdog { fwEvents.forwardingEvents.forEach((event) => { this.accumulatedHtlcFees += Number(event.fee) }) + } + handleRootOperations = async () => { + let pendingChange = 0 + const pendingChainPayments = await this.storage.metricsStorage.GetPendingChainPayments() + for (const payment of pendingChainPayments) { + const tx = await this.lnd.GetTx(payment.operation_identifier) + if (tx.numConfirmations > 0) { + await this.storage.metricsStorage.SetRootOpConfirmed(payment.serial_id) + continue + } + tx.outputDetails.forEach(o => pendingChange += o.isOurAddress ? Number(o.amount) : 0) + } + let newReceived = 0 + let newSpent = 0 + if (this.lastHandlerRootOpsAtUnix === 0) { + this.lastHandlerRootOpsAtUnix = Math.floor(Date.now() / 1000) + return { newReceived, newSpent, pendingChange } + } + + const newOps = await this.storage.metricsStorage.GetRootOperations({ from: this.lastHandlerRootOpsAtUnix }) + newOps.forEach(o => { + switch (o.operation_type) { + case 'chain_payment': + newSpent += Number(o.operation_amount) + break + case 'invoice_payment': + newSpent += Number(o.operation_amount) + break + case 'chain': + newReceived += Number(o.operation_amount) + break + case 'invoice': + newReceived += Number(o.operation_amount) + break + } + }) + return { newReceived, newSpent, pendingChange } } getAggregatedExternalBalance = async () => { @@ -101,8 +137,9 @@ export class Watchdog { const feesPaidForLiquidity = this.liquidityManager.GetPaidFees() const pb = await this.rugPullTracker.CheckProviderBalance() const providerBalance = pb.prevBalance || pb.balance - const otherExternal = { pb: providerBalance, f: feesPaidForLiquidity, lnd: totalLndBalance, olnd: othersFromLnd } - return { totalExternal: totalLndBalance + providerBalance + feesPaidForLiquidity, otherExternal } + const { newReceived, newSpent, pendingChange } = await this.handleRootOperations() + const opsTotal = newReceived + pendingChange - newSpent + return { totalExternal: totalLndBalance + providerBalance + feesPaidForLiquidity + opsTotal } } checkBalanceUpdate = async (deltaLnd: number, deltaUsers: number) => { @@ -187,7 +224,7 @@ export class Watchdog { } const totalUsersBalance = await this.storage.paymentStorage.GetTotalUsersBalance() this.utils.stateBundler.AddBalancePoint('usersBalance', totalUsersBalance) - const { totalExternal, otherExternal } = await this.getAggregatedExternalBalance() + const { totalExternal } = await this.getAggregatedExternalBalance() this.utils.stateBundler.AddBalancePoint('accumulatedHtlcFees', this.accumulatedHtlcFees) const deltaLnd = totalExternal - (this.initialLndBalance + this.accumulatedHtlcFees) const deltaUsers = totalUsersBalance - this.initialUsersBalance @@ -196,8 +233,6 @@ export class Watchdog { const knownMaxIndex = Math.max(maxFromDb, this.latestPaymentIndexOffset) const newLatest = await this.lnd.GetLatestPaymentIndex(knownMaxIndex) const historyMismatch = newLatest > knownMaxIndex - const other = { ilnd: this.initialLndBalance, hf: this.accumulatedHtlcFees, iu: this.initialUsersBalance, tu: totalUsersBalance, km: knownMaxIndex, nl: newLatest, oext: otherExternal } - //getLogger({ component: 'watchdog_debug2' })(JSON.stringify({ deltaLnd, deltaUsers, totalExternal, other })) const deny = await this.checkBalanceUpdate(deltaLnd, deltaUsers) if (historyMismatch) { getLogger({ component: 'bark' })("History mismatch detected in absolute update, locking outgoing operations") diff --git a/src/services/storage/entity/RootOperation.ts b/src/services/storage/entity/RootOperation.ts index 3a2bd1f9..ec4914bc 100644 --- a/src/services/storage/entity/RootOperation.ts +++ b/src/services/storage/entity/RootOperation.ts @@ -17,6 +17,9 @@ export class RootOperation { @Column({ default: 0 }) at_unix: number + @Column({ default: false }) + pending: boolean + @CreateDateColumn() created_at: Date diff --git a/src/services/storage/metricsStorage.ts b/src/services/storage/metricsStorage.ts index 44da304c..b388a587 100644 --- a/src/services/storage/metricsStorage.ts +++ b/src/services/storage/metricsStorage.ts @@ -10,6 +10,7 @@ import { StorageInterface } from "./db/storageInterface.js"; import { Utils } from "../helpers/utilsWrapper.js"; import { Channel, ChannelEventUpdate } from "../../../proto/lnd/lightning.js"; import { ChannelEvent } from "./entity/ChannelEvent.js"; +export type RootOperationType = 'chain' | 'invoice' | 'chain_payment' | 'invoice_payment' export default class { //DB: DataSource | EntityManager settings: StorageSettings @@ -145,14 +146,25 @@ export default class { } } - async AddRootOperation(opType: string, id: string, amount: number, txId?: string) { - return this.dbs.CreateAndSave('RootOperation', { operation_type: opType, operation_amount: amount, operation_identifier: id, at_unix: Math.floor(Date.now() / 1000) }, txId) + async AddRootOperation(opType: RootOperationType, id: string, amount: number, pending = false, dbTxId?: string) { + return this.dbs.CreateAndSave('RootOperation', { + operation_type: opType, operation_amount: amount, + operation_identifier: id, at_unix: Math.floor(Date.now() / 1000), pending + }, dbTxId) } - async GetRootOperation(opType: string, id: string, txId?: string) { + async GetRootOperation(opType: RootOperationType, id: string, txId?: string) { return this.dbs.FindOne('RootOperation', { where: { operation_type: opType, operation_identifier: id } }, txId) } + async GetPendingChainPayments() { + return this.dbs.Find('RootOperation', { where: { operation_type: 'chain_payment', pending: true } }) + } + + async SetRootOpConfirmed(serialId: number) { + return this.dbs.Update('RootOperation', serialId, { pending: false }) + } + async GetRootOperations({ from, to }: { from?: number, to?: number }, txId?: string) { const q = getTimeQuery({ from, to }) return this.dbs.Find('RootOperation', q, txId) diff --git a/src/services/storage/migrations/1771524665409-root_op_pending.ts b/src/services/storage/migrations/1771524665409-root_op_pending.ts new file mode 100644 index 00000000..e65461f3 --- /dev/null +++ b/src/services/storage/migrations/1771524665409-root_op_pending.ts @@ -0,0 +1,20 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class RootOpPending1771524665409 implements MigrationInterface { + name = 'RootOpPending1771524665409' + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(`CREATE TABLE "temporary_root_operation" ("serial_id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "operation_type" varchar NOT NULL, "operation_amount" integer NOT NULL, "operation_identifier" varchar NOT NULL, "created_at" datetime NOT NULL DEFAULT (datetime('now')), "updated_at" datetime NOT NULL DEFAULT (datetime('now')), "at_unix" integer NOT NULL DEFAULT (0), "pending" boolean NOT NULL DEFAULT (0))`); + await queryRunner.query(`INSERT INTO "temporary_root_operation"("serial_id", "operation_type", "operation_amount", "operation_identifier", "created_at", "updated_at", "at_unix") SELECT "serial_id", "operation_type", "operation_amount", "operation_identifier", "created_at", "updated_at", "at_unix" FROM "root_operation"`); + await queryRunner.query(`DROP TABLE "root_operation"`); + await queryRunner.query(`ALTER TABLE "temporary_root_operation" RENAME TO "root_operation"`); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE "root_operation" RENAME TO "temporary_root_operation"`); + await queryRunner.query(`CREATE TABLE "root_operation" ("serial_id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "operation_type" varchar NOT NULL, "operation_amount" integer NOT NULL, "operation_identifier" varchar NOT NULL, "created_at" datetime NOT NULL DEFAULT (datetime('now')), "updated_at" datetime NOT NULL DEFAULT (datetime('now')), "at_unix" integer NOT NULL DEFAULT (0))`); + await queryRunner.query(`INSERT INTO "root_operation"("serial_id", "operation_type", "operation_amount", "operation_identifier", "created_at", "updated_at", "at_unix") SELECT "serial_id", "operation_type", "operation_amount", "operation_identifier", "created_at", "updated_at", "at_unix" FROM "temporary_root_operation"`); + await queryRunner.query(`DROP TABLE "temporary_root_operation"`); + } + +} diff --git a/src/services/storage/migrations/runner.ts b/src/services/storage/migrations/runner.ts index eb5d7c19..d68e3698 100644 --- a/src/services/storage/migrations/runner.ts +++ b/src/services/storage/migrations/runner.ts @@ -35,7 +35,7 @@ import { SwapsServiceUrl1768413055036 } from './1768413055036-swaps_service_url. import { InvoiceSwaps1769529793283 } from './1769529793283-invoice_swaps.js' import { InvoiceSwapsFixes1769805357459 } from './1769805357459-invoice_swaps_fixes.js' import { SwapTimestamps1771347307798 } from './1771347307798-swap_timestamps.js' - +import { RootOpPending1771524665409 } from './1771524665409-root_op_pending.js' export const allMigrations = [Initial1703170309875, LspOrder1718387847693, LiquidityProvider1719335699480, LndNodeInfo1720187506189, TrackedProvider1720814323679, CreateInviteTokenTable1721751414878, PaymentIndex1721760297610, DebitAccess1726496225078, DebitAccessFixes1726685229264, DebitToPub1727105758354, UserCbUrl1727112281043, UserOffer1733502626042, ManagementGrant1751307732346, ManagementGrantBanned1751989251513, @@ -44,7 +44,8 @@ export const allMigrations = [Initial1703170309875, LspOrder1718387847693, Liqui TxSwapAddress1764779178945, ClinkRequester1765497600000, TrackedProviderHeight1766504040000, SwapsServiceUrl1768413055036, InvoiceSwaps1769529793283, InvoiceSwapsFixes1769805357459, SwapTimestamps1771347307798] -export const allMetricsMigrations = [LndMetrics1703170330183, ChannelRouting1709316653538, HtlcCount1724266887195, BalanceEvents1724860966825, RootOps1732566440447, RootOpsTime1745428134124, ChannelEvents1750777346411] +export const allMetricsMigrations = [LndMetrics1703170330183, ChannelRouting1709316653538, HtlcCount1724266887195, BalanceEvents1724860966825, + RootOps1732566440447, RootOpsTime1745428134124, ChannelEvents1750777346411, RootOpPending1771524665409] /* export const TypeOrmMigrationRunner = async (log: PubLogger, storageManager: Storage, settings: DbSettings, arg: string | undefined): Promise => { await connectAndMigrate(log, storageManager, allMigrations, allMetricsMigrations) return false From 305b268d73e58b22c8097f0f47c50656c3ee3f02 Mon Sep 17 00:00:00 2001 From: boufni95 Date: Thu, 19 Feb 2026 18:53:24 +0000 Subject: [PATCH 27/66] fixes --- metricsDatasource.js | 15 +++++++++++++-- src/services/main/watchdog.ts | 15 ++++++++++----- 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/metricsDatasource.js b/metricsDatasource.js index c1c3f493..aaf5ddbc 100644 --- a/metricsDatasource.js +++ b/metricsDatasource.js @@ -1,3 +1,14 @@ +/** + * TypeORM DataSource used only by the TypeORM CLI (e.g. migration:generate). + * + * Migrations at runtime are run from src/services/storage/migrations/runner.ts (allMigrations), + * not from this file. The app never uses this DataSource to run migrations. + * + * Workflow: update the migrations array in this file *before* running + * migration:generate, so TypeORM knows the current schema (entities + existing migrations). + * We do not update this file immediately after adding a new migration; update it when you + * are about to generate the next migration. + */ import { DataSource } from "typeorm" import { BalanceEvent } from "./build/src/services/storage/entity/BalanceEvent.js" import { ChannelBalanceEvent } from "./build/src/services/storage/entity/ChannelsBalanceEvent.js" @@ -11,13 +22,13 @@ import { BalanceEvents1724860966825 } from './build/src/services/storage/migrati import { RootOps1732566440447 } from './build/src/services/storage/migrations/1732566440447-root_ops.js' import { RootOpsTime1745428134124 } from './build/src/services/storage/migrations/1745428134124-root_ops_time.js' import { ChannelEvents1750777346411 } from './build/src/services/storage/migrations/1750777346411-channel_events.js' - +import { RootOpPending1771524665409 } from './build/src/services/storage/migrations/1771524665409-root_op_pending.js' export default new DataSource({ type: "better-sqlite3", database: "metrics.sqlite", entities: [BalanceEvent, ChannelBalanceEvent, ChannelRouting, RootOperation, ChannelEvent], migrations: [LndMetrics1703170330183, ChannelRouting1709316653538, HtlcCount1724266887195, BalanceEvents1724860966825, - RootOps1732566440447, RootOpsTime1745428134124, ChannelEvents1750777346411] + RootOps1732566440447, RootOpsTime1745428134124, ChannelEvents1750777346411, RootOpPending1771524665409] }); //npx typeorm migration:generate ./src/services/storage/migrations/root_op_pending -d ./metricsDatasource.js \ No newline at end of file diff --git a/src/services/main/watchdog.ts b/src/services/main/watchdog.ts index b02b9678..d9d585ba 100644 --- a/src/services/main/watchdog.ts +++ b/src/services/main/watchdog.ts @@ -98,12 +98,17 @@ export class Watchdog { let pendingChange = 0 const pendingChainPayments = await this.storage.metricsStorage.GetPendingChainPayments() for (const payment of pendingChainPayments) { - const tx = await this.lnd.GetTx(payment.operation_identifier) - if (tx.numConfirmations > 0) { - await this.storage.metricsStorage.SetRootOpConfirmed(payment.serial_id) - continue + try { + const tx = await this.lnd.GetTx(payment.operation_identifier) + if (tx.numConfirmations > 0) { + await this.storage.metricsStorage.SetRootOpConfirmed(payment.serial_id) + continue + } + tx.outputDetails.forEach(o => pendingChange += o.isOurAddress ? Number(o.amount) : 0) + } catch (err: any) { + this.log("Error getting tx for root operation", err.message || err) } - tx.outputDetails.forEach(o => pendingChange += o.isOurAddress ? Number(o.amount) : 0) + } let newReceived = 0 let newSpent = 0 From 875d1274de057c6f91420941ea9e16196ea4058a Mon Sep 17 00:00:00 2001 From: boufni95 Date: Thu, 19 Feb 2026 21:24:24 +0000 Subject: [PATCH 28/66] await tx added to db --- src/services/main/paymentManager.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/services/main/paymentManager.ts b/src/services/main/paymentManager.ts index ec351091..cb9b31cf 100644 --- a/src/services/main/paymentManager.ts +++ b/src/services/main/paymentManager.ts @@ -302,8 +302,11 @@ export default class { const amount = Number(output.amount) const outputIndex = Number(output.outputIndex) log(`processing missed chain tx: address=${output.address}, txHash=${tx.txHash}, amount=${amount}, outputIndex=${outputIndex}`) - this.addressPaidCb({ hash: tx.txHash, index: outputIndex }, output.address, amount, 'lnd', startHeight) - .catch(err => log(ERROR, "failed to process user address output:", err.message || err)) + try { + await this.addressPaidCb({ hash: tx.txHash, index: outputIndex }, output.address, amount, 'lnd', startHeight) + } catch (err: any) { + log(ERROR, "failed to process user address output:", err.message || err) + } return true } From 8ada2ac1654829f3ae91d104e5ddaaace26c9b05 Mon Sep 17 00:00:00 2001 From: boufni95 Date: Thu, 19 Feb 2026 21:45:31 +0000 Subject: [PATCH 29/66] new block handler logs --- src/services/main/index.ts | 2 ++ src/services/main/paymentManager.ts | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/services/main/index.ts b/src/services/main/index.ts index 965c2eba..9e90d2c2 100644 --- a/src/services/main/index.ts +++ b/src/services/main/index.ts @@ -161,6 +161,7 @@ export default class { NewBlockHandler = async (height: number, skipMetrics?: boolean) => { let confirmed: (PendingTx & { confs: number; })[] let log = getLogger({}) + log("NewBlockHandler called", JSON.stringify({ height, skipMetrics })) this.storage.paymentStorage.DeleteExpiredTransactionSwaps(height) .catch(err => log(ERROR, "failed to delete expired transaction swaps", err.message || err)) this.storage.paymentStorage.DeleteExpiredInvoiceSwaps(height) @@ -176,6 +177,7 @@ export default class { log(ERROR, "failed to check transactions after new block", err.message || err) return } + log("NewBlockHandler new confirmed transactions", confirmed.length) await Promise.all(confirmed.map(async c => { if (c.type === 'outgoing') { await this.storage.paymentStorage.UpdateUserTransactionPayment(c.tx.serial_id, { confs: c.confs }) diff --git a/src/services/main/paymentManager.ts b/src/services/main/paymentManager.ts index cb9b31cf..63999116 100644 --- a/src/services/main/paymentManager.ts +++ b/src/services/main/paymentManager.ts @@ -980,7 +980,8 @@ export default class { const pending = await this.storage.paymentStorage.GetPendingTransactions() let lowestHeight = height const map: Record = {} - + let log = getLogger({}) + log("CheckNewlyConfirmedTxs ", pending.incoming.length, "incoming", pending.outgoing.length, "outgoing") const checkTx = (t: PendingTx) => { if (t.tx.broadcast_height < lowestHeight) { lowestHeight = t.tx.broadcast_height } map[t.tx.tx_hash] = t From c146d46c59c08d7b4a182ac5b6a86573959934f3 Mon Sep 17 00:00:00 2001 From: Mothana Date: Wed, 4 Feb 2026 22:30:24 +0400 Subject: [PATCH 30/66] notification types and topic id --- datasource.js | 8 +- proto/autogenerated/client.md | 9 ++ proto/autogenerated/go/types.go | 21 +++++ proto/autogenerated/ts/types.ts | 89 +++++++++++++++++++ proto/service/structs.proto | 16 ++++ src/services/main/appUserManager.ts | 3 +- src/services/main/applicationManager.ts | 6 +- src/services/main/index.ts | 29 +++++- src/services/storage/applicationStorage.ts | 3 +- .../storage/entity/ApplicationUser.ts | 3 + ...1770038768784-application_user_topic_id.ts | 24 +++++ src/services/storage/migrations/runner.ts | 9 +- 12 files changed, 211 insertions(+), 9 deletions(-) create mode 100644 src/services/storage/migrations/1770038768784-application_user_topic_id.ts diff --git a/datasource.js b/datasource.js index 7126f7de..0ad041a1 100644 --- a/datasource.js +++ b/datasource.js @@ -62,6 +62,10 @@ import { TrackedProviderHeight1766504040000 } from './build/src/services/storage import { SwapsServiceUrl1768413055036 } from './build/src/services/storage/migrations/1768413055036-swaps_service_url.js' import { InvoiceSwaps1769529793283 } from './build/src/services/storage/migrations/1769529793283-invoice_swaps.js' import { InvoiceSwapsFixes1769805357459 } from './build/src/services/storage/migrations/1769805357459-invoice_swaps_fixes.js' +import { ApplicationUserTopicId1770038768784 } from './build/src/services/storage/migrations/1770038768784-application_user_topic_id.js' +import { SwapTimestamps1771347307798 } from './build/src/services/storage/migrations/1771347307798-swap_timestamps.js' + + export default new DataSource({ type: "better-sqlite3", @@ -71,7 +75,9 @@ export default new DataSource({ PaymentIndex1721760297610, DebitAccess1726496225078, DebitAccessFixes1726685229264, DebitToPub1727105758354, UserCbUrl1727112281043, UserOffer1733502626042, ManagementGrant1751307732346, InvoiceCallbackUrls1752425992291, OldSomethingLeftover1753106599604, UserReceivingInvoiceIdx1753109184611, AppUserDevice1753285173175, UserAccess1759426050669, AddBlindToUserOffer1760000000000, ApplicationAvatarUrl1761000001000, AdminSettings1761683639419, TxSwap1762890527098, - TxSwapAddress1764779178945, ClinkRequester1765497600000, TrackedProviderHeight1766504040000, SwapsServiceUrl1768413055036, InvoiceSwaps1769529793283, InvoiceSwapsFixes1769805357459], + TxSwapAddress1764779178945, ClinkRequester1765497600000, TrackedProviderHeight1766504040000, SwapsServiceUrl1768413055036, InvoiceSwaps1769529793283, InvoiceSwapsFixes1769805357459, + ApplicationUserTopicId1770038768784, SwapTimestamps1771347307798], + entities: [User, UserReceivingInvoice, UserReceivingAddress, AddressReceivingTransaction, UserInvoicePayment, UserTransactionPayment, UserBasicAuth, UserEphemeralKey, Product, UserToUserPayment, Application, ApplicationUser, UserToUserPayment, LspOrder, LndNodeInfo, diff --git a/proto/autogenerated/client.md b/proto/autogenerated/client.md index 679e0d30..d5b9baab 100644 --- a/proto/autogenerated/client.md +++ b/proto/autogenerated/client.md @@ -1670,6 +1670,14 @@ The nostr server will send back a message response, and inside the body there wi ### ProvidersDisruption - __disruptions__: ARRAY of: _[ProviderDisruption](#ProviderDisruption)_ +### PushNotificationEnvelope + - __app_npub_hex__: _string_ + - __encrypted_payload__: _string_ + - __topic_id__: _string_ + +### PushNotificationPayload + - __data__: _[PushNotificationPayload_data](#PushNotificationPayload_data)_ + ### RefundAdminInvoiceSwapRequest - __sat_per_v_byte__: _number_ - __swap_operation_id__: _string_ @@ -1797,6 +1805,7 @@ The nostr server will send back a message response, and inside the body there wi - __nmanage__: _string_ - __noffer__: _string_ - __service_fee_bps__: _number_ + - __topic_id__: _string_ - __userId__: _string_ - __user_identifier__: _string_ diff --git a/proto/autogenerated/go/types.go b/proto/autogenerated/go/types.go index a59adaaf..d0efb918 100644 --- a/proto/autogenerated/go/types.go +++ b/proto/autogenerated/go/types.go @@ -647,6 +647,14 @@ type ProviderDisruption struct { type ProvidersDisruption struct { Disruptions []ProviderDisruption `json:"disruptions"` } +type PushNotificationEnvelope struct { + App_npub_hex string `json:"app_npub_hex"` + Encrypted_payload string `json:"encrypted_payload"` + Topic_id string `json:"topic_id"` +} +type PushNotificationPayload struct { + Data *PushNotificationPayload_data `json:"data"` +} type RefundAdminInvoiceSwapRequest struct { Sat_per_v_byte int64 `json:"sat_per_v_byte"` Swap_operation_id string `json:"swap_operation_id"` @@ -774,6 +782,7 @@ type UserInfo struct { Nmanage string `json:"nmanage"` Noffer string `json:"noffer"` Service_fee_bps int64 `json:"service_fee_bps"` + Topic_id string `json:"topic_id"` Userid string `json:"userId"` User_identifier string `json:"user_identifier"` } @@ -872,6 +881,18 @@ type NPubLinking_state struct { Linking_token *string `json:"linking_token"` Unlinked *Empty `json:"unlinked"` } +type PushNotificationPayload_data_type string + +const ( + RECEIVED_OPERATION PushNotificationPayload_data_type = "received_operation" + SENT_OPERATION PushNotificationPayload_data_type = "sent_operation" +) + +type PushNotificationPayload_data struct { + Type PushNotificationPayload_data_type `json:"type"` + Received_operation *UserOperation `json:"received_operation"` + Sent_operation *UserOperation `json:"sent_operation"` +} type UpdateChannelPolicyRequest_update_type string const ( diff --git a/proto/autogenerated/ts/types.ts b/proto/autogenerated/ts/types.ts index 82f2c1fe..f62fea43 100644 --- a/proto/autogenerated/ts/types.ts +++ b/proto/autogenerated/ts/types.ts @@ -3843,6 +3843,53 @@ export const ProvidersDisruptionValidate = (o?: ProvidersDisruption, opts: Provi return null } +export type PushNotificationEnvelope = { + app_npub_hex: string + encrypted_payload: string + topic_id: string +} +export const PushNotificationEnvelopeOptionalFields: [] = [] +export type PushNotificationEnvelopeOptions = OptionsBaseMessage & { + checkOptionalsAreSet?: [] + app_npub_hex_CustomCheck?: (v: string) => boolean + encrypted_payload_CustomCheck?: (v: string) => boolean + topic_id_CustomCheck?: (v: string) => boolean +} +export const PushNotificationEnvelopeValidate = (o?: PushNotificationEnvelope, opts: PushNotificationEnvelopeOptions = {}, path: string = 'PushNotificationEnvelope::root.'): Error | null => { + if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message') + if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null') + + if (typeof o.app_npub_hex !== 'string') return new Error(`${path}.app_npub_hex: is not a string`) + if (opts.app_npub_hex_CustomCheck && !opts.app_npub_hex_CustomCheck(o.app_npub_hex)) return new Error(`${path}.app_npub_hex: custom check failed`) + + if (typeof o.encrypted_payload !== 'string') return new Error(`${path}.encrypted_payload: is not a string`) + if (opts.encrypted_payload_CustomCheck && !opts.encrypted_payload_CustomCheck(o.encrypted_payload)) return new Error(`${path}.encrypted_payload: custom check failed`) + + if (typeof o.topic_id !== 'string') return new Error(`${path}.topic_id: is not a string`) + if (opts.topic_id_CustomCheck && !opts.topic_id_CustomCheck(o.topic_id)) return new Error(`${path}.topic_id: custom check failed`) + + return null +} + +export type PushNotificationPayload = { + data: PushNotificationPayload_data +} +export const PushNotificationPayloadOptionalFields: [] = [] +export type PushNotificationPayloadOptions = OptionsBaseMessage & { + checkOptionalsAreSet?: [] + data_Options?: PushNotificationPayload_dataOptions +} +export const PushNotificationPayloadValidate = (o?: PushNotificationPayload, opts: PushNotificationPayloadOptions = {}, path: string = 'PushNotificationPayload::root.'): Error | null => { + if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message') + if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null') + + const dataErr = PushNotificationPayload_dataValidate(o.data, opts.data_Options, `${path}.data`) + if (dataErr !== null) return dataErr + + + return null +} + export type RefundAdminInvoiceSwapRequest = { sat_per_v_byte: number swap_operation_id: string @@ -4539,6 +4586,7 @@ export type UserInfo = { nmanage: string noffer: string service_fee_bps: number + topic_id: string userId: string user_identifier: string } @@ -4555,6 +4603,7 @@ export type UserInfoOptions = OptionsBaseMessage & { nmanage_CustomCheck?: (v: string) => boolean noffer_CustomCheck?: (v: string) => boolean service_fee_bps_CustomCheck?: (v: number) => boolean + topic_id_CustomCheck?: (v: string) => boolean userId_CustomCheck?: (v: string) => boolean user_identifier_CustomCheck?: (v: string) => boolean } @@ -4592,6 +4641,9 @@ export const UserInfoValidate = (o?: UserInfo, opts: UserInfoOptions = {}, path: if (typeof o.service_fee_bps !== 'number') return new Error(`${path}.service_fee_bps: is not a number`) if (opts.service_fee_bps_CustomCheck && !opts.service_fee_bps_CustomCheck(o.service_fee_bps)) return new Error(`${path}.service_fee_bps: custom check failed`) + if (typeof o.topic_id !== 'string') return new Error(`${path}.topic_id: is not a string`) + if (opts.topic_id_CustomCheck && !opts.topic_id_CustomCheck(o.topic_id)) return new Error(`${path}.topic_id: custom check failed`) + if (typeof o.userId !== 'string') return new Error(`${path}.userId: is not a string`) if (opts.userId_CustomCheck && !opts.userId_CustomCheck(o.userId)) return new Error(`${path}.userId: custom check failed`) @@ -5009,6 +5061,43 @@ export const NPubLinking_stateValidate = (o?: NPubLinking_state, opts:NPubLinkin if (unlinkedErr !== null) return unlinkedErr + break + default: + return new Error(path + ': unknown type '+ stringType) + } + return null +} +export enum PushNotificationPayload_data_type { + RECEIVED_OPERATION = 'received_operation', + SENT_OPERATION = 'sent_operation', +} +export const enumCheckPushNotificationPayload_data_type = (e?: PushNotificationPayload_data_type): boolean => { + for (const v in PushNotificationPayload_data_type) if (e === v) return true + return false +} +export type PushNotificationPayload_data = + {type:PushNotificationPayload_data_type.RECEIVED_OPERATION, received_operation:UserOperation}| + {type:PushNotificationPayload_data_type.SENT_OPERATION, sent_operation:UserOperation} + +export type PushNotificationPayload_dataOptions = { + received_operation_Options?: UserOperationOptions + sent_operation_Options?: UserOperationOptions +} +export const PushNotificationPayload_dataValidate = (o?: PushNotificationPayload_data, opts:PushNotificationPayload_dataOptions = {}, path: string = 'PushNotificationPayload_data::root.'): Error | null => { + if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null') + const stringType: string = o.type + switch (o.type) { + case PushNotificationPayload_data_type.RECEIVED_OPERATION: + const received_operationErr = UserOperationValidate(o.received_operation, opts.received_operation_Options, `${path}.received_operation`) + if (received_operationErr !== null) return received_operationErr + + + break + case PushNotificationPayload_data_type.SENT_OPERATION: + const sent_operationErr = UserOperationValidate(o.sent_operation, opts.sent_operation_Options, `${path}.sent_operation`) + if (sent_operationErr !== null) return sent_operationErr + + break default: return new Error(path + ': unknown type '+ stringType) diff --git a/proto/service/structs.proto b/proto/service/structs.proto index 07b930da..fb1f0867 100644 --- a/proto/service/structs.proto +++ b/proto/service/structs.proto @@ -541,6 +541,7 @@ message UserInfo{ string callback_url = 10; string bridge_url = 11; string nmanage = 12; + string topic_id = 13; } @@ -935,4 +936,19 @@ message BeaconData { optional string avatarUrl = 3; optional string nextRelay = 4; optional CumulativeFees fees = 5; +} + + +message PushNotificationEnvelope { + string topic_id = 1; + string app_npub_hex = 2; + string encrypted_payload = 3; // encrypted PushNotificationPayload +} + + +message PushNotificationPayload { + oneof data { + UserOperation received_operation = 1; + UserOperation sent_operation = 2; + } } \ No newline at end of file diff --git a/src/services/main/appUserManager.ts b/src/services/main/appUserManager.ts index 168258f1..e1db3637 100644 --- a/src/services/main/appUserManager.ts +++ b/src/services/main/appUserManager.ts @@ -82,7 +82,8 @@ export default class { ndebit: ndebitEncode({ pubkey: app.nostr_public_key!, pointer: appUser.identifier, relay: nostrSettings.relays[0] }), nmanage: nmanageEncode({ pubkey: app.nostr_public_key!, pointer: appUser.identifier, relay: nostrSettings.relays[0] }), callback_url: appUser.callback_url, - bridge_url: this.settings.getSettings().serviceSettings.bridgeUrl + bridge_url: this.settings.getSettings().serviceSettings.bridgeUrl, + topic_id: appUser.topic_id } } diff --git a/src/services/main/applicationManager.ts b/src/services/main/applicationManager.ts index aaafd8a7..ecfc7b85 100644 --- a/src/services/main/applicationManager.ts +++ b/src/services/main/applicationManager.ts @@ -169,7 +169,8 @@ export default class { ndebit: ndebitEncode({ pubkey: app.nostr_public_key!, pointer: u.identifier, relay: nostrSettings.relays[0] }), nmanage: nmanageEncode({ pubkey: app.nostr_public_key!, pointer: u.identifier, relay: nostrSettings.relays[0] }), callback_url: u.callback_url, - bridge_url: this.settings.getSettings().serviceSettings.bridgeUrl + bridge_url: this.settings.getSettings().serviceSettings.bridgeUrl, + topic_id: u.topic_id }, max_withdrawable: max @@ -227,7 +228,8 @@ export default class { ndebit: ndebitEncode({ pubkey: app.nostr_public_key!, pointer: user.identifier, relay: nostrSettings.relays[0] }), nmanage: nmanageEncode({ pubkey: app.nostr_public_key!, pointer: user.identifier, relay: nostrSettings.relays[0] }), callback_url: user.callback_url, - bridge_url: this.settings.getSettings().serviceSettings.bridgeUrl + bridge_url: this.settings.getSettings().serviceSettings.bridgeUrl, + topic_id: user.topic_id }, } } diff --git a/src/services/main/index.ts b/src/services/main/index.ts index 9e90d2c2..6a931cc6 100644 --- a/src/services/main/index.ts +++ b/src/services/main/index.ts @@ -424,13 +424,36 @@ export default class { if (devices.length === 0 || !app.nostr_public_key || !app.nostr_private_key || !appUser.nostr_public_key) { return } + const tokens = devices.map(d => d.firebase_messaging_token) const ck = nip44.getConversationKey(Buffer.from(app.nostr_private_key, 'hex'), appUser.nostr_public_key) - const j = JSON.stringify(op) + + let payloadToEncrypt: Types.PushNotificationPayload; + if (op.inbound) { + payloadToEncrypt = { + data: { + type: Types.PushNotificationPayload_data_type.RECEIVED_OPERATION, + received_operation: op + } + } + } else { + payloadToEncrypt = { + data: { + type: Types.PushNotificationPayload_data_type.SENT_OPERATION, + sent_operation: op + } + } + } + const j = JSON.stringify(payloadToEncrypt) const encrypted = nip44.encrypt(j, ck) - const encryptedData: { encrypted: string, app_npub_hex: string } = { encrypted, app_npub_hex: app.nostr_public_key } + + const envelope: Types.PushNotificationEnvelope = { + topic_id: appUser.topic_id, + app_npub_hex: app.nostr_public_key, + encrypted_payload: encrypted + } const notification: ShockPushNotification = { - message: JSON.stringify(encryptedData), + message: JSON.stringify(envelope), body, title } diff --git a/src/services/storage/applicationStorage.ts b/src/services/storage/applicationStorage.ts index 21f6f9c9..08aad37a 100644 --- a/src/services/storage/applicationStorage.ts +++ b/src/services/storage/applicationStorage.ts @@ -72,7 +72,8 @@ export default class { user: user, application, identifier: userIdentifier, - nostr_public_key: nostrPub + nostr_public_key: nostrPub, + topic_id: crypto.randomBytes(32).toString('hex') }, txId) }) } diff --git a/src/services/storage/entity/ApplicationUser.ts b/src/services/storage/entity/ApplicationUser.ts index 2284b9bd..c4717721 100644 --- a/src/services/storage/entity/ApplicationUser.ts +++ b/src/services/storage/entity/ApplicationUser.ts @@ -26,6 +26,9 @@ export class ApplicationUser { @Column({ default: "" }) callback_url: string + @Column({ unique: true }) + topic_id: string; + @CreateDateColumn() created_at: Date diff --git a/src/services/storage/migrations/1770038768784-application_user_topic_id.ts b/src/services/storage/migrations/1770038768784-application_user_topic_id.ts new file mode 100644 index 00000000..b520cbe9 --- /dev/null +++ b/src/services/storage/migrations/1770038768784-application_user_topic_id.ts @@ -0,0 +1,24 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class ApplicationUserTopicId1770038768784 implements MigrationInterface { + name = 'ApplicationUserTopicId1770038768784' + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(`DROP INDEX "IDX_0a0dbb25a73306b037dec82251"`); + await queryRunner.query(`CREATE TABLE "temporary_application_user" ("serial_id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "identifier" varchar NOT NULL, "nostr_public_key" varchar, "created_at" datetime NOT NULL DEFAULT (datetime('now')), "updated_at" datetime NOT NULL DEFAULT (datetime('now')), "userSerialId" integer, "applicationSerialId" integer, "callback_url" varchar NOT NULL DEFAULT (''), "topic_id" varchar NOT NULL, CONSTRAINT "UQ_3175dc397c8285d1e532554dea5" UNIQUE ("nostr_public_key"), CONSTRAINT "REL_0796a381bcc624f52e9a155712" UNIQUE ("userSerialId"), CONSTRAINT "UQ_bd1a42f39fd7b4218bed5cc63d9" UNIQUE ("topic_id"), CONSTRAINT "FK_0796a381bcc624f52e9a155712b" FOREIGN KEY ("userSerialId") REFERENCES "user" ("serial_id") ON DELETE NO ACTION ON UPDATE NO ACTION, CONSTRAINT "FK_1b3bdb6f660cd99533a1e673ef1" FOREIGN KEY ("applicationSerialId") REFERENCES "application" ("serial_id") ON DELETE NO ACTION ON UPDATE NO ACTION)`); + await queryRunner.query(`INSERT INTO "temporary_application_user"("serial_id", "identifier", "nostr_public_key", "created_at", "updated_at", "userSerialId", "applicationSerialId", "callback_url", "topic_id") SELECT "serial_id", "identifier", "nostr_public_key", "created_at", "updated_at", "userSerialId", "applicationSerialId", "callback_url", lower(hex(randomblob(32))) FROM "application_user"`); + await queryRunner.query(`DROP TABLE "application_user"`); + await queryRunner.query(`ALTER TABLE "temporary_application_user" RENAME TO "application_user"`); + await queryRunner.query(`CREATE UNIQUE INDEX "IDX_0a0dbb25a73306b037dec82251" ON "application_user" ("identifier") `); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`DROP INDEX "IDX_0a0dbb25a73306b037dec82251"`); + await queryRunner.query(`ALTER TABLE "application_user" RENAME TO "temporary_application_user"`); + await queryRunner.query(`CREATE TABLE "application_user" ("serial_id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "identifier" varchar NOT NULL, "nostr_public_key" varchar, "created_at" datetime NOT NULL DEFAULT (datetime('now')), "updated_at" datetime NOT NULL DEFAULT (datetime('now')), "userSerialId" integer, "applicationSerialId" integer, "callback_url" varchar NOT NULL DEFAULT (''), CONSTRAINT "UQ_3175dc397c8285d1e532554dea5" UNIQUE ("nostr_public_key"), CONSTRAINT "REL_0796a381bcc624f52e9a155712" UNIQUE ("userSerialId"), CONSTRAINT "FK_0796a381bcc624f52e9a155712b" FOREIGN KEY ("userSerialId") REFERENCES "user" ("serial_id") ON DELETE NO ACTION ON UPDATE NO ACTION, CONSTRAINT "FK_1b3bdb6f660cd99533a1e673ef1" FOREIGN KEY ("applicationSerialId") REFERENCES "application" ("serial_id") ON DELETE NO ACTION ON UPDATE NO ACTION)`); + await queryRunner.query(`INSERT INTO "application_user"("serial_id", "identifier", "nostr_public_key", "created_at", "updated_at", "userSerialId", "applicationSerialId", "callback_url") SELECT "serial_id", "identifier", "nostr_public_key", "created_at", "updated_at", "userSerialId", "applicationSerialId", "callback_url" FROM "temporary_application_user"`); + await queryRunner.query(`DROP TABLE "temporary_application_user"`); + await queryRunner.query(`CREATE UNIQUE INDEX "IDX_0a0dbb25a73306b037dec82251" ON "application_user" ("identifier") `); + } + +} diff --git a/src/services/storage/migrations/runner.ts b/src/services/storage/migrations/runner.ts index d68e3698..1b5537d6 100644 --- a/src/services/storage/migrations/runner.ts +++ b/src/services/storage/migrations/runner.ts @@ -32,17 +32,24 @@ import { TxSwapAddress1764779178945 } from './1764779178945-tx_swap_address.js' import { ClinkRequester1765497600000 } from './1765497600000-clink_requester.js' import { TrackedProviderHeight1766504040000 } from './1766504040000-tracked_provider_height.js' import { SwapsServiceUrl1768413055036 } from './1768413055036-swaps_service_url.js' + import { InvoiceSwaps1769529793283 } from './1769529793283-invoice_swaps.js' import { InvoiceSwapsFixes1769805357459 } from './1769805357459-invoice_swaps_fixes.js' +import { ApplicationUserTopicId1770038768784 } from './1770038768784-application_user_topic_id.js' import { SwapTimestamps1771347307798 } from './1771347307798-swap_timestamps.js' import { RootOpPending1771524665409 } from './1771524665409-root_op_pending.js' + + + + export const allMigrations = [Initial1703170309875, LspOrder1718387847693, LiquidityProvider1719335699480, LndNodeInfo1720187506189, TrackedProvider1720814323679, CreateInviteTokenTable1721751414878, PaymentIndex1721760297610, DebitAccess1726496225078, DebitAccessFixes1726685229264, DebitToPub1727105758354, UserCbUrl1727112281043, UserOffer1733502626042, ManagementGrant1751307732346, ManagementGrantBanned1751989251513, InvoiceCallbackUrls1752425992291, OldSomethingLeftover1753106599604, UserReceivingInvoiceIdx1753109184611, AppUserDevice1753285173175, UserAccess1759426050669, AddBlindToUserOffer1760000000000, ApplicationAvatarUrl1761000001000, AdminSettings1761683639419, TxSwap1762890527098, TxSwapAddress1764779178945, ClinkRequester1765497600000, TrackedProviderHeight1766504040000, SwapsServiceUrl1768413055036, - InvoiceSwaps1769529793283, InvoiceSwapsFixes1769805357459, SwapTimestamps1771347307798] + InvoiceSwaps1769529793283, InvoiceSwapsFixes1769805357459, ApplicationUserTopicId1770038768784, SwapTimestamps1771347307798] + export const allMetricsMigrations = [LndMetrics1703170330183, ChannelRouting1709316653538, HtlcCount1724266887195, BalanceEvents1724860966825, RootOps1732566440447, RootOpsTime1745428134124, ChannelEvents1750777346411, RootOpPending1771524665409] From c83028c41923f182b9f47b943690e3fce83bb40b Mon Sep 17 00:00:00 2001 From: boufni95 Date: Fri, 20 Feb 2026 18:40:40 +0000 Subject: [PATCH 31/66] fetch each pending tx to validate --- src/services/main/index.ts | 2 +- src/services/main/paymentManager.ts | 61 +++++++++++++---------------- 2 files changed, 29 insertions(+), 34 deletions(-) diff --git a/src/services/main/index.ts b/src/services/main/index.ts index 9e90d2c2..8d831e91 100644 --- a/src/services/main/index.ts +++ b/src/services/main/index.ts @@ -171,7 +171,7 @@ export default class { if (!skipMetrics) { await this.metricsManager.NewBlockCb(height, balanceEvents) } - confirmed = await this.paymentManager.CheckNewlyConfirmedTxs(height) + confirmed = await this.paymentManager.CheckNewlyConfirmedTxs() await this.liquidityManager.onNewBlock() } catch (err: any) { log(ERROR, "failed to check transactions after new block", err.message || err) diff --git a/src/services/main/paymentManager.ts b/src/services/main/paymentManager.ts index 63999116..38c7658b 100644 --- a/src/services/main/paymentManager.ts +++ b/src/services/main/paymentManager.ts @@ -201,24 +201,11 @@ export default class { } else { log("no missed chain transactions found") } - await this.reprocessStuckPendingTx(log, currentHeight) } catch (err: any) { log(ERROR, "failed to check for missed chain transactions:", err.message || err) } } - reprocessStuckPendingTx = async (log: PubLogger, currentHeight: number) => { - const { incoming } = await this.storage.paymentStorage.GetPendingTransactions() - const found = incoming.find(t => t.broadcast_height < currentHeight - 100) - if (found) { - log("found a possibly stuck pending transaction, reprocessing with full transaction history") - // There is a pending transaction more than 100 blocks old, this is likely a transaction - // that has a broadcast height higher than it actually is, so its not getting picked up when being processed - // by calling new block cb with height of 1, we make sure that even if the transaction has a newer height, it will still be processed - await this.newBlockCb(1, true) - } - } - private async getLatestTransactions(log: PubLogger): Promise<{ txs: Transaction[], currentHeight: number, lndPubkey: string, startHeight: number }> { const lndInfo = await this.lnd.GetInfo() const lndPubkey = lndInfo.identityPubkey @@ -273,7 +260,7 @@ export default class { private async processRootAddressOutput(output: OutputDetail, tx: Transaction, addresses: LndAddress[], log: PubLogger): Promise { const addr = addresses.find(a => a.address === output.address) if (!addr) { - throw new Error(`address ${output.address} not found in list of addresses`) + throw new Error(`root address ${output.address} not found in list of addresses`) } if (addr.change) { log(`ignoring change address ${output.address}`) @@ -976,30 +963,38 @@ export default class { return { amount: payment.paid_amount, fees: payment.service_fees } } - async CheckNewlyConfirmedTxs(height: number) { + private async getTxConfs(txHash: string): Promise { + try { + const info = await this.lnd.GetTx(txHash) + const { numConfirmations: confs, amount: amt } = info + if (confs > 2 || (amt <= confInTwo && confs > 1) || (amt <= confInOne && confs > 0)) { + return confs + } + } catch (err: any) { + getLogger({})("failed to get tx info", err.message || err) + } + return 0 + } + + async CheckNewlyConfirmedTxs() { const pending = await this.storage.paymentStorage.GetPendingTransactions() - let lowestHeight = height - const map: Record = {} let log = getLogger({}) log("CheckNewlyConfirmedTxs ", pending.incoming.length, "incoming", pending.outgoing.length, "outgoing") - const checkTx = (t: PendingTx) => { - if (t.tx.broadcast_height < lowestHeight) { lowestHeight = t.tx.broadcast_height } - map[t.tx.tx_hash] = t + const confirmedIncoming: (PendingTx & { confs: number })[] = [] + const confirmedOutgoing: (PendingTx & { confs: number })[] = [] + for (const tx of pending.incoming) { + const confs = await this.getTxConfs(tx.tx_hash) + if (confs > 0) { + confirmedIncoming.push({ type: "incoming", tx: tx, confs }) + } } - pending.incoming.forEach(t => checkTx({ type: "incoming", tx: t })) - pending.outgoing.forEach(t => checkTx({ type: "outgoing", tx: t })) - const { transactions } = await this.lnd.GetTransactions(lowestHeight) - const newlyConfirmedTxs = transactions.map(tx => { - const { txHash, numConfirmations: confs, amount: amt } = tx - const t = map[txHash] - if (!t || confs === 0) { - return + for (const tx of pending.outgoing) { + const confs = await this.getTxConfs(tx.tx_hash) + if (confs > 0) { + confirmedOutgoing.push({ type: "outgoing", tx: tx, confs }) } - if (confs > 2 || (amt <= confInTwo && confs > 1) || (amt <= confInOne && confs > 0)) { - return { ...t, confs } - } - }) - return newlyConfirmedTxs.filter(t => t !== undefined) as (PendingTx & { confs: number })[] + } + return confirmedIncoming.concat(confirmedOutgoing) } async CleanupOldUnpaidInvoices() { From 9e66f7d72e979e6fd3217f46783b2d7f1b710bd6 Mon Sep 17 00:00:00 2001 From: boufni95 Date: Fri, 20 Feb 2026 19:37:11 +0000 Subject: [PATCH 32/66] use debug log level, no level = ERROR --- src/services/helpers/logger.ts | 16 ++-- src/services/lnd/lnd.ts | 137 +++++++++++++++------------------ 2 files changed, 69 insertions(+), 84 deletions(-) diff --git a/src/services/helpers/logger.ts b/src/services/helpers/logger.ts index 4d6601c9..62a87eac 100644 --- a/src/services/helpers/logger.ts +++ b/src/services/helpers/logger.ts @@ -1,17 +1,17 @@ import fs from 'fs' export const DEBUG = Symbol("DEBUG") export const ERROR = Symbol("ERROR") -export const WARN = Symbol("WARN") +export const INFO = Symbol("INFO") type LoggerParams = { appName?: string, userId?: string, component?: string } export type PubLogger = (...message: (string | number | object | symbol)[]) => void type Writer = (message: string) => void const logsDir = process.env.LOGS_DIR || "logs" -const logLevel = process.env.LOG_LEVEL || "DEBUG" +const logLevel = process.env.LOG_LEVEL || "INFO" try { fs.mkdirSync(logsDir) } catch { } -if (logLevel !== "DEBUG" && logLevel !== "WARN" && logLevel !== "ERROR") { - throw new Error("Invalid log level " + logLevel + " must be one of (DEBUG, WARN, ERROR)") +if (logLevel !== "DEBUG" && logLevel !== "INFO" && logLevel !== "ERROR") { + throw new Error("Invalid log level " + logLevel + " must be one of (DEBUG, INFO, ERROR)") } const z = (n: number) => n < 10 ? `0${n}` : `${n}` // Sanitize filename to remove invalid characters for filesystem @@ -67,19 +67,17 @@ export const getLogger = (params: LoggerParams): PubLogger => { } message[0] = "DEBUG" break; - case WARN: + case INFO: if (logLevel === "ERROR") { return } - message[0] = "WARN" + message[0] = "INFO" break; case ERROR: message[0] = "ERROR" break; default: - if (logLevel !== "DEBUG") { - return - } + // treats logs without a level as ERROR level, without prefix so it can be found and fixed if needed } const now = new Date() const timestamp = `${now.getFullYear()}-${z(now.getMonth() + 1)}-${z(now.getDate())} ${z(now.getHours())}:${z(now.getMinutes())}:${z(now.getSeconds())}` diff --git a/src/services/lnd/lnd.ts b/src/services/lnd/lnd.ts index 3d66b268..6d71d424 100644 --- a/src/services/lnd/lnd.ts +++ b/src/services/lnd/lnd.ts @@ -15,7 +15,7 @@ import { AddInvoiceReq } from './addInvoiceReq.js'; import { PayInvoiceReq } from './payInvoiceReq.js'; import { SendCoinsReq } from './sendCoinsReq.js'; import { AddressPaidCb, InvoicePaidCb, NodeInfo, Invoice, DecodedInvoice, PaidInvoice, NewBlockCb, HtlcCb, BalanceInfo, ChannelEventCb } from './settings.js'; -import { ERROR, getLogger } from '../helpers/logger.js'; +import { ERROR, getLogger, DEBUG, INFO } from '../helpers/logger.js'; import { HtlcEvent_EventType } from '../../../proto/lnd/router.js'; import { LiquidityProvider } from '../main/liquidityProvider.js'; import { Utils } from '../helpers/utilsWrapper.js'; @@ -69,7 +69,7 @@ export default class { // Skip LND client initialization if using only liquidity provider if (liquidProvider.getSettings().useOnlyLiquidityProvider) { - this.log("USE_ONLY_LIQUIDITY_PROVIDER enabled, skipping LND client initialization") + this.log(INFO, "USE_ONLY_LIQUIDITY_PROVIDER enabled, skipping LND client initialization") // Create minimal dummy clients - they won't be used but prevent null reference errors // Use insecure credentials directly (can't combine them) const { lndAddr } = this.getSettings().lndNodeSettings @@ -126,14 +126,13 @@ export default class { } async Warmup() { - this.log("Warming up LND") + this.log(INFO, "Warming up LND") // Skip LND warmup if using only liquidity provider if (this.liquidProvider.getSettings().useOnlyLiquidityProvider) { - this.log("USE_ONLY_LIQUIDITY_PROVIDER enabled, skipping LND warmup") + this.log(INFO, "USE_ONLY_LIQUIDITY_PROVIDER enabled, skipping LND warmup") this.ready = true return } - // console.log("Warming up LND") this.SubscribeAddressPaid() this.SubscribeInvoicePaid() await this.SubscribeNewBlock() @@ -148,7 +147,7 @@ export default class { this.ready = true res() } catch (err) { - this.log("LND is not ready yet, will try again in 1 second") + this.log(INFO, "LND is not ready yet, will try again in 1 second") if (Date.now() - now > 1000 * 60) { rej(new Error("LND not ready after 1 minute")) } @@ -177,28 +176,26 @@ export default class { uris: [] } } - // console.log("Getting info") const res = await this.lightning.getInfo({}, DeadLineMetadata()) return res.response } async ListPendingChannels(): Promise { - this.log("Listing pending channels") + this.log(DEBUG, "Listing pending channels") if (this.liquidProvider.getSettings().useOnlyLiquidityProvider) { return { pendingOpenChannels: [], pendingClosingChannels: [], pendingForceClosingChannels: [], waitingCloseChannels: [], totalLimboBalance: 0n } } - // console.log("Listing pending channels") const res = await this.lightning.pendingChannels({ includeRawTx: false }, DeadLineMetadata()) return res.response } async ListChannels(peerLookup = false): Promise { - this.log("Listing channels") + this.log(DEBUG, "Listing channels") const res = await this.lightning.listChannels({ activeOnly: false, inactiveOnly: false, privateOnly: false, publicOnly: false, peer: Buffer.alloc(0), peerAliasLookup: peerLookup }, DeadLineMetadata()) return res.response } async ListClosedChannels(): Promise { - this.log("Listing closed channels") + this.log(DEBUG, "Listing closed channels") const res = await this.lightning.closedChannels({ abandoned: true, breach: true, @@ -215,7 +212,6 @@ export default class { if (this.liquidProvider.getSettings().useOnlyLiquidityProvider) { return } - // console.log("Checking health") if (!this.ready) { throw new Error("not ready") } @@ -226,69 +222,69 @@ export default class { } RestartStreams() { - this.log("Restarting streams") + this.log(INFO, "Restarting streams") if (!this.ready || this.abortController.signal.aborted) { return } - this.log("LND is dead, will try to reconnect in", deadLndRetrySeconds, "seconds") + this.log(INFO, "LND is dead, will try to reconnect in", deadLndRetrySeconds, "seconds") const interval = setInterval(async () => { try { await this.unlockLnd() - this.log("LND is back online") + this.log(INFO, "LND is back online") clearInterval(interval) await this.Warmup() } catch (err) { - this.log("LND still dead, will try again in", deadLndRetrySeconds, "seconds") + this.log(INFO, "LND still dead, will try again in", deadLndRetrySeconds, "seconds") } }, deadLndRetrySeconds * 1000) } async SubscribeChannelEvents() { - this.log("Subscribing to channel events") + this.log(DEBUG, "Subscribing to channel events") const stream = this.lightning.subscribeChannelEvents({}, { abort: this.abortController.signal }) stream.responses.onMessage(async channel => { const channels = await this.ListChannels() this.channelEventCb(channel, channels.channels) }) stream.responses.onError(error => { - this.log("Error with subscribeChannelEvents stream") + this.log(ERROR, "Error with subscribeChannelEvents stream") }) stream.responses.onComplete(() => { - this.log("subscribeChannelEvents stream closed") + this.log(INFO, "subscribeChannelEvents stream closed") }) } async SubscribeHtlcEvents() { - this.log("Subscribing to htlc events") + this.log(DEBUG, "Subscribing to htlc events") const stream = this.router.subscribeHtlcEvents({}, { abort: this.abortController.signal }) stream.responses.onMessage(htlc => { this.htlcCb(htlc) }) stream.responses.onError(error => { - this.log("Error with subscribeHtlcEvents stream") + this.log(ERROR, "Error with subscribeHtlcEvents stream") }) stream.responses.onComplete(() => { - this.log("subscribeHtlcEvents stream closed") + this.log(INFO, "subscribeHtlcEvents stream closed") }) } async SubscribeNewBlock() { - this.log("Subscribing to new block") + this.log(DEBUG, "Subscribing to new block") const { blockHeight } = await this.GetInfo() const stream = this.chainNotifier.registerBlockEpochNtfn({ height: blockHeight, hash: Buffer.alloc(0) }, { abort: this.abortController.signal }) stream.responses.onMessage(block => { this.newBlockCb(block.height) }) stream.responses.onError(error => { - this.log("Error with new block stream") + this.log(ERROR, "Error with new block stream") }) stream.responses.onComplete(() => { - this.log("new block stream closed") + this.log(INFO, "new block stream closed") }) } SubscribeAddressPaid(): void { - this.log("Subscribing to address paid") + this.log(DEBUG, "Subscribing to address paid") const stream = this.lightning.subscribeTransactions({ account: "", endHeight: 0, @@ -307,15 +303,15 @@ export default class { } }) stream.responses.onError(error => { - this.log("Error with onchain tx stream") + this.log(ERROR, "Error with onchain tx stream") }) stream.responses.onComplete(() => { - this.log("onchain tx stream closed") + this.log(INFO, "onchain tx stream closed") }) } SubscribeInvoicePaid(): void { - this.log("Subscribing to invoice paid") + this.log(DEBUG, "Subscribing to invoice paid") const stream = this.lightning.subscribeInvoices({ settleIndex: BigInt(this.latestKnownSettleIndex), addIndex: 0n, @@ -328,14 +324,14 @@ export default class { }) let restarted = false stream.responses.onError(error => { - this.log("Error with invoice stream") + this.log(ERROR, "Error with invoice stream") if (!restarted) { restarted = true this.RestartStreams() } }) stream.responses.onComplete(() => { - this.log("invoice stream closed") + this.log(INFO, "invoice stream closed") if (!restarted) { restarted = true this.RestartStreams() @@ -357,7 +353,7 @@ export default class { } async ListAddresses(): Promise { - this.log("Listing addresses") + this.log(DEBUG, "Listing addresses") const res = await this.walletKit.listAddresses({ accountName: "", showCustomAccounts: false }, DeadLineMetadata()) const addresses = res.response.accountWithAddresses.map(a => a.addresses.map(a => ({ address: a.address, change: a.isInternal }))).flat() addresses.forEach(a => this.addressesCache[a.address] = { isChange: a.change }) @@ -365,12 +361,11 @@ export default class { } async NewAddress(addressType: Types.AddressType, { useProvider, from }: TxActionOptions): Promise { - this.log("Creating new address") + this.log(DEBUG, "Creating new address") // 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") let lndAddressType: AddressType switch (addressType) { case Types.AddressType.NESTED_PUBKEY_HASH: @@ -400,11 +395,11 @@ export default class { } async NewInvoice(value: number, memo: string, expiry: number, { useProvider, from }: TxActionOptions, blind = false): Promise { - this.log("Creating new invoice") + this.log(DEBUG, "Creating new invoice") // Force use of provider when bypass is enabled const mustUseProvider = this.liquidProvider.getSettings().useOnlyLiquidityProvider || useProvider if (mustUseProvider) { - console.log("using provider") + this.log(INFO, "using provider") const invoice = await this.liquidProvider.AddInvoice(value, memo, from, expiry) const providerPubkey = this.liquidProvider.GetProviderPubkey() return { payRequest: invoice, providerPubkey } @@ -420,7 +415,7 @@ export default class { } async DecodeInvoice(paymentRequest: string): Promise { - this.log("Decoding invoice") + this.log(DEBUG, "Decoding invoice") if (this.liquidProvider.getSettings().useOnlyLiquidityProvider) { // Use light-bolt11-decoder when LND is bypassed try { @@ -446,25 +441,23 @@ export default class { throw new Error(`Failed to decode invoice: ${err.message}`) } } - // console.log("Decoding invoice") const res = await this.lightning.decodePayReq({ payReq: paymentRequest }, DeadLineMetadata()) return { numSatoshis: Number(res.response.numSatoshis), paymentHash: res.response.paymentHash } } async ChannelBalance(): Promise<{ local: number, remote: number }> { - this.log("Getting channel balance") + this.log(DEBUG, "Getting channel balance") if (this.liquidProvider.getSettings().useOnlyLiquidityProvider) { return { local: 0, remote: 0 } } - // console.log("Getting channel balance") const res = await this.lightning.channelBalance({}) 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, { routingFeeLimit, serviceFee }: { routingFeeLimit: number, serviceFee: number }, decodedAmount: number, { useProvider, from }: TxActionOptions, paymentIndexCb?: (index: number) => void): Promise { - this.log("Paying invoice") + this.log(DEBUG, "Paying invoice") if (this.outgoingOpsLocked) { - this.log("outgoing ops locked, rejecting payment request") + this.log(ERROR, "outgoing ops locked, rejecting payment request") throw new Error("lnd node is currently out of sync") } // Force use of provider when bypass is enabled @@ -481,7 +474,7 @@ export default class { const stream = this.router.sendPaymentV2(req, { abort: abortController.signal }) return new Promise((res, rej) => { stream.responses.onError(error => { - this.log("invoice payment failed", error) + this.log(ERROR, "invoice payment failed", error) rej(error) }) let indexSent = false @@ -493,7 +486,7 @@ export default class { } switch (payment.status) { case Payment_PaymentStatus.FAILED: - this.log("invoice payment failed", payment.failureReason) + this.log(ERROR, "invoice payment failed", payment.failureReason) rej(PaymentFailureReason[payment.failureReason]) return case Payment_PaymentStatus.SUCCEEDED: @@ -511,7 +504,7 @@ export default class { } async EstimateChainFees(address: string, amount: number, targetConf: number): Promise { - this.log("Estimating chain fees") + this.log(DEBUG, "Estimating chain fees") await this.Health() const res = await this.lightning.estimateFee({ addrToAmount: { [address]: BigInt(amount) }, @@ -524,14 +517,13 @@ export default class { } async PayAddress(address: string, amount: number, satPerVByte: number, label = "", { useProvider, from }: TxActionOptions): Promise { - this.log("Paying address") + this.log(DEBUG, "Paying address") // 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") if (this.outgoingOpsLocked) { - this.log("outgoing ops locked, rejecting payment request") + this.log(ERROR, "outgoing ops locked, rejecting payment request") throw new Error("lnd node is currently out of sync") } if (useProvider) { @@ -549,19 +541,19 @@ export default class { } async GetTransactions(startHeight: number): Promise { - this.log("Getting transactions") + this.log(DEBUG, "Getting transactions") const res = await this.lightning.getTransactions({ startHeight, endHeight: 0, account: "" }, DeadLineMetadata()) return res.response } async GetChannelInfo(chanId: string) { - this.log("Getting channel info") + this.log(DEBUG, "Getting channel info") const res = await this.lightning.getChanInfo({ chanId, chanPoint: "" }, DeadLineMetadata()) return res.response } async UpdateChannelPolicy(chanPoint: string, policy: Types.ChannelPolicy) { - this.log("Updating channel policy") + this.log(DEBUG, "Updating channel policy") const split = chanPoint.split(':') const res = await this.lightning.updateChannelPolicy({ @@ -579,19 +571,19 @@ export default class { } async GetChannelBalance() { - this.log("Getting channel balance") + this.log(DEBUG, "Getting channel balance") const res = await this.lightning.channelBalance({}, DeadLineMetadata()) return res.response } async GetWalletBalance() { - this.log("Getting wallet balance") + this.log(DEBUG, "Getting wallet balance") const res = await this.lightning.walletBalance({ account: "", minConfs: 1 }, DeadLineMetadata()) return res.response } async GetTotalBalace() { - this.log("Getting total balance") + this.log(DEBUG, "Getting total balance") const walletBalance = await this.GetWalletBalance() const confirmedWalletBalance = Number(walletBalance.confirmedBalance) this.utils.stateBundler.AddBalancePoint('walletBalance', confirmedWalletBalance) @@ -606,11 +598,10 @@ export default class { } async GetBalance(): Promise { // TODO: remove this - this.log("Getting balance") + this.log(DEBUG, "Getting balance") if (this.liquidProvider.getSettings().useOnlyLiquidityProvider) { return { confirmedBalance: 0, unconfirmedBalance: 0, totalBalance: 0, channelsBalance: [] } } - // console.log("Getting balance") const wRes = await this.lightning.walletBalance({ account: "", minConfs: 1 }, DeadLineMetadata()) const { confirmedBalance, unconfirmedBalance, totalBalance } = wRes.response const { response } = await this.lightning.listChannels({ @@ -626,36 +617,33 @@ export default class { } async GetForwardingHistory(indexOffset: number, startTime = 0, endTime = 0): Promise { - this.log("Getting forwarding history") + this.log(DEBUG, "Getting forwarding history") if (this.liquidProvider.getSettings().useOnlyLiquidityProvider) { return { forwardingEvents: [], lastOffsetIndex: indexOffset } } - // console.log("Getting forwarding history") const { response } = await this.lightning.forwardingHistory({ indexOffset, numMaxEvents: 0, startTime: BigInt(startTime), endTime: BigInt(endTime), peerAliasLookup: false }, DeadLineMetadata()) return response } async GetAllPaidInvoices(max: number) { - this.log("Getting all paid invoices") + this.log(DEBUG, "Getting all paid invoices") if (this.liquidProvider.getSettings().useOnlyLiquidityProvider) { return { invoices: [] } } - // console.log("Getting all paid invoices") const res = await this.lightning.listInvoices({ indexOffset: 0n, numMaxInvoices: BigInt(max), pendingOnly: false, reversed: true, creationDateEnd: 0n, creationDateStart: 0n }, DeadLineMetadata()) return res.response } async GetAllPayments(max: number) { - this.log("Getting all payments") + this.log(DEBUG, "Getting all payments") if (this.liquidProvider.getSettings().useOnlyLiquidityProvider) { return { payments: [] } } - // console.log("Getting all payments") const res = await this.lightning.listPayments({ countTotalPayments: false, includeIncomplete: false, indexOffset: 0n, maxPayments: BigInt(max), reversed: true, creationDateEnd: 0n, creationDateStart: 0n }) return res.response } async GetPayment(paymentIndex: number) { - this.log("Getting payment") + this.log(DEBUG, "Getting payment") if (paymentIndex === 0) { throw new Error("payment index starts from 1") } @@ -667,11 +655,10 @@ export default class { } async GetLatestPaymentIndex(from = 0) { - this.log("Getting latest payment index") + this.log(DEBUG, "Getting latest payment index") if (this.liquidProvider.getSettings().useOnlyLiquidityProvider) { return from } - // console.log("Getting latest payment index") let indexOffset = BigInt(from) while (true) { const res = await this.lightning.listPayments({ countTotalPayments: false, includeIncomplete: false, indexOffset, maxPayments: 0n, reversed: false, creationDateEnd: 0n, creationDateStart: 0n }, DeadLineMetadata()) @@ -683,7 +670,7 @@ export default class { } async ConnectPeer(addr: { pubkey: string, host: string }) { - this.log("Connecting to peer") + this.log(DEBUG, "Connecting to peer") const res = await this.lightning.connectPeer({ addr, perm: true, @@ -693,7 +680,7 @@ export default class { } async GetPaymentFromHash(paymentHash: string): Promise { - this.log("Getting payment from hash") + this.log(DEBUG, "Getting payment from hash") const abortController = new AbortController() const stream = this.router.trackPaymentV2({ paymentHash: Buffer.from(paymentHash, 'hex'), @@ -720,7 +707,7 @@ export default class { } async AddPeer(pub: string, host: string, port: number) { - this.log("Adding peer") + this.log(DEBUG, "Adding peer") const res = await this.lightning.connectPeer({ addr: { pubkey: pub, @@ -733,19 +720,19 @@ export default class { } async ListPeers() { - this.log("Listing peers") + this.log(DEBUG, "Listing peers") const res = await this.lightning.listPeers({ latestError: true }, DeadLineMetadata()) return res.response } async OpenChannel(destination: string, closeAddress: string, fundingAmount: number, pushSats: number, satsPerVByte: number): Promise { - this.log("Opening channel") + this.log(DEBUG, "Opening channel") const abortController = new AbortController() const req = OpenChannelReq(destination, closeAddress, fundingAmount, pushSats, satsPerVByte) const stream = this.lightning.openChannel(req, { abort: abortController.signal }) return new Promise((res, rej) => { stream.responses.onMessage(message => { - console.log("message", message) + this.log(DEBUG, "open channel message", message) switch (message.update.oneofKind) { case 'chanPending': res(message) @@ -753,14 +740,14 @@ export default class { } }) stream.responses.onError(error => { - console.log("error", error) + this.log(ERROR, "open channel error", error) rej(error) }) }) } async CloseChannel(fundingTx: string, outputIndex: number, force: boolean, satPerVByte: number): Promise { - this.log("Closing channel") + this.log(DEBUG, "Closing channel") const stream = this.lightning.closeChannel({ deliveryAddress: "", force: force, @@ -779,7 +766,7 @@ export default class { }, DeadLineMetadata()) return new Promise((res, rej) => { stream.responses.onMessage(message => { - console.log("message", message) + this.log(DEBUG, "close channel message", message) switch (message.update.oneofKind) { case 'closePending': res(message.update.closePending) @@ -787,7 +774,7 @@ export default class { } }) stream.responses.onError(error => { - console.log("error", error) + this.log(ERROR, "close channel error", error) rej(error) }) }) From f8fe946b406830368008d3eaa042bc09216f690b Mon Sep 17 00:00:00 2001 From: boufni95 Date: Tue, 24 Feb 2026 18:36:03 +0000 Subject: [PATCH 33/66] tx swaps polish --- datasource.js | 21 +++++--- proto/autogenerated/client.md | 9 ++-- proto/autogenerated/go/types.go | 15 +++--- proto/autogenerated/ts/types.ts | 49 ++++++++++------- proto/service/structs.proto | 10 ++-- src/services/lnd/swaps/swaps.ts | 52 +++++++++++-------- src/services/main/paymentManager.ts | 2 + .../storage/db/serializationHelpers.ts | 25 ++++++--- src/services/storage/db/storageInterface.ts | 16 +++--- .../storage/entity/TransactionSwap.ts | 6 +++ .../1771878683383-tx_swap_timestamps.ts | 20 +++++++ src/services/storage/migrations/runner.ts | 23 ++++---- src/services/storage/paymentStorage.ts | 11 ++++ 13 files changed, 174 insertions(+), 85 deletions(-) create mode 100644 src/services/storage/migrations/1771878683383-tx_swap_timestamps.ts diff --git a/datasource.js b/datasource.js index 0ad041a1..4badca25 100644 --- a/datasource.js +++ b/datasource.js @@ -37,8 +37,9 @@ import { InvoiceSwap } from "./build/src/services/storage/entity/InvoiceSwap.js" import { Initial1703170309875 } from './build/src/services/storage/migrations/1703170309875-initial.js' import { LspOrder1718387847693 } from './build/src/services/storage/migrations/1718387847693-lsp_order.js' -import { LndNodeInfo1720187506189 } from './build/src/services/storage/migrations/1720187506189-lnd_node_info.js' import { LiquidityProvider1719335699480 } from './build/src/services/storage/migrations/1719335699480-liquidity_provider.js' +import { LndNodeInfo1720187506189 } from './build/src/services/storage/migrations/1720187506189-lnd_node_info.js' +import { TrackedProvider1720814323679 } from './build/src/services/storage/migrations/1720814323679-tracked_provider.js' import { CreateInviteTokenTable1721751414878 } from './build/src/services/storage/migrations/1721751414878-create_invite_token_table.js' import { PaymentIndex1721760297610 } from './build/src/services/storage/migrations/1721760297610-payment_index.js' import { DebitAccess1726496225078 } from './build/src/services/storage/migrations/1726496225078-debit_access.js' @@ -47,6 +48,7 @@ import { DebitToPub1727105758354 } from './build/src/services/storage/migrations import { UserCbUrl1727112281043 } from './build/src/services/storage/migrations/1727112281043-user_cb_url.js' import { UserOffer1733502626042 } from './build/src/services/storage/migrations/1733502626042-user_offer.js' import { ManagementGrant1751307732346 } from './build/src/services/storage/migrations/1751307732346-management_grant.js' +import { ManagementGrantBanned1751989251513 } from './build/src/services/storage/migrations/1751989251513-management_grant_banned.js' import { InvoiceCallbackUrls1752425992291 } from './build/src/services/storage/migrations/1752425992291-invoice_callback_urls.js' import { OldSomethingLeftover1753106599604 } from './build/src/services/storage/migrations/1753106599604-old_something_leftover.js' import { UserReceivingInvoiceIdx1753109184611 } from './build/src/services/storage/migrations/1753109184611-user_receiving_invoice_idx.js' @@ -67,16 +69,19 @@ import { SwapTimestamps1771347307798 } from './build/src/services/storage/migrat + export default new DataSource({ type: "better-sqlite3", database: "db.sqlite", // logging: true, - migrations: [Initial1703170309875, LspOrder1718387847693, LiquidityProvider1719335699480, LndNodeInfo1720187506189, CreateInviteTokenTable1721751414878, - PaymentIndex1721760297610, DebitAccess1726496225078, DebitAccessFixes1726685229264, DebitToPub1727105758354, UserCbUrl1727112281043, - UserOffer1733502626042, ManagementGrant1751307732346, InvoiceCallbackUrls1752425992291, OldSomethingLeftover1753106599604, UserReceivingInvoiceIdx1753109184611, - AppUserDevice1753285173175, UserAccess1759426050669, AddBlindToUserOffer1760000000000, ApplicationAvatarUrl1761000001000, AdminSettings1761683639419, TxSwap1762890527098, - TxSwapAddress1764779178945, ClinkRequester1765497600000, TrackedProviderHeight1766504040000, SwapsServiceUrl1768413055036, InvoiceSwaps1769529793283, InvoiceSwapsFixes1769805357459, - ApplicationUserTopicId1770038768784, SwapTimestamps1771347307798], + migrations: [Initial1703170309875, LspOrder1718387847693, LiquidityProvider1719335699480, LndNodeInfo1720187506189, + TrackedProvider1720814323679, CreateInviteTokenTable1721751414878, PaymentIndex1721760297610, DebitAccess1726496225078, DebitAccessFixes1726685229264, + DebitToPub1727105758354, UserCbUrl1727112281043, UserOffer1733502626042, ManagementGrant1751307732346, ManagementGrantBanned1751989251513, + InvoiceCallbackUrls1752425992291, OldSomethingLeftover1753106599604, UserReceivingInvoiceIdx1753109184611, AppUserDevice1753285173175, + UserAccess1759426050669, AddBlindToUserOffer1760000000000, ApplicationAvatarUrl1761000001000, AdminSettings1761683639419, TxSwap1762890527098, + TxSwapAddress1764779178945, ClinkRequester1765497600000, TrackedProviderHeight1766504040000, SwapsServiceUrl1768413055036, + InvoiceSwaps1769529793283, InvoiceSwapsFixes1769805357459, ApplicationUserTopicId1770038768784, SwapTimestamps1771347307798 + ], entities: [User, UserReceivingInvoice, UserReceivingAddress, AddressReceivingTransaction, UserInvoicePayment, UserTransactionPayment, @@ -84,4 +89,4 @@ export default new DataSource({ TrackedProvider, InviteToken, DebitAccess, UserOffer, ManagementGrant, AppUserDevice, UserAccess, AdminSettings, TransactionSwap, InvoiceSwap], // synchronize: true, }) -//npx typeorm migration:generate ./src/services/storage/migrations/swap_timestamps -d ./datasource.js \ No newline at end of file +//npx typeorm migration:generate ./src/services/storage/migrations/tx_swap_timestamps -d ./datasource.js \ No newline at end of file diff --git a/proto/autogenerated/client.md b/proto/autogenerated/client.md index d5b9baab..106804e1 100644 --- a/proto/autogenerated/client.md +++ b/proto/autogenerated/client.md @@ -1740,7 +1740,10 @@ The nostr server will send back a message response, and inside the body there wi ### TransactionSwapQuote - __chain_fee_sats__: _number_ + - __completed_at_unix__: _number_ + - __expires_at_block_height__: _number_ - __invoice_amount_sats__: _number_ + - __paid_at_unix__: _number_ - __service_fee_sats__: _number_ - __service_url__: _string_ - __swap_fee_sats__: _number_ @@ -1754,13 +1757,13 @@ The nostr server will send back a message response, and inside the body there wi - __transaction_amount_sats__: _number_ ### TxSwapOperation - - __address_paid__: _string_ + - __address_paid__: _string_ *this field is optional - __failure_reason__: _string_ *this field is optional - __operation_payment__: _[UserOperation](#UserOperation)_ *this field is optional - - __swap_operation_id__: _string_ + - __quote__: _[TransactionSwapQuote](#TransactionSwapQuote)_ + - __tx_id__: _string_ *this field is optional ### TxSwapsList - - __quotes__: ARRAY of: _[TransactionSwapQuote](#TransactionSwapQuote)_ - __swaps__: ARRAY of: _[TxSwapOperation](#TxSwapOperation)_ ### UpdateChannelPolicyRequest diff --git a/proto/autogenerated/go/types.go b/proto/autogenerated/go/types.go index d0efb918..76c662cf 100644 --- a/proto/autogenerated/go/types.go +++ b/proto/autogenerated/go/types.go @@ -717,7 +717,10 @@ type SingleMetricReq struct { } type TransactionSwapQuote struct { Chain_fee_sats int64 `json:"chain_fee_sats"` + Completed_at_unix int64 `json:"completed_at_unix"` + Expires_at_block_height int64 `json:"expires_at_block_height"` Invoice_amount_sats int64 `json:"invoice_amount_sats"` + Paid_at_unix int64 `json:"paid_at_unix"` Service_fee_sats int64 `json:"service_fee_sats"` Service_url string `json:"service_url"` Swap_fee_sats int64 `json:"swap_fee_sats"` @@ -731,14 +734,14 @@ type TransactionSwapRequest struct { Transaction_amount_sats int64 `json:"transaction_amount_sats"` } type TxSwapOperation struct { - Address_paid string `json:"address_paid"` - Failure_reason string `json:"failure_reason"` - Operation_payment *UserOperation `json:"operation_payment"` - Swap_operation_id string `json:"swap_operation_id"` + Address_paid string `json:"address_paid"` + Failure_reason string `json:"failure_reason"` + Operation_payment *UserOperation `json:"operation_payment"` + Quote *TransactionSwapQuote `json:"quote"` + Tx_id string `json:"tx_id"` } type TxSwapsList struct { - Quotes []TransactionSwapQuote `json:"quotes"` - Swaps []TxSwapOperation `json:"swaps"` + Swaps []TxSwapOperation `json:"swaps"` } type UpdateChannelPolicyRequest struct { Policy *ChannelPolicy `json:"policy"` diff --git a/proto/autogenerated/ts/types.ts b/proto/autogenerated/ts/types.ts index f62fea43..64ee28f9 100644 --- a/proto/autogenerated/ts/types.ts +++ b/proto/autogenerated/ts/types.ts @@ -4232,7 +4232,10 @@ export const SingleMetricReqValidate = (o?: SingleMetricReq, opts: SingleMetricR export type TransactionSwapQuote = { chain_fee_sats: number + completed_at_unix: number + expires_at_block_height: number invoice_amount_sats: number + paid_at_unix: number service_fee_sats: number service_url: string swap_fee_sats: number @@ -4243,7 +4246,10 @@ export const TransactionSwapQuoteOptionalFields: [] = [] export type TransactionSwapQuoteOptions = OptionsBaseMessage & { checkOptionalsAreSet?: [] chain_fee_sats_CustomCheck?: (v: number) => boolean + completed_at_unix_CustomCheck?: (v: number) => boolean + expires_at_block_height_CustomCheck?: (v: number) => boolean invoice_amount_sats_CustomCheck?: (v: number) => boolean + paid_at_unix_CustomCheck?: (v: number) => boolean service_fee_sats_CustomCheck?: (v: number) => boolean service_url_CustomCheck?: (v: string) => boolean swap_fee_sats_CustomCheck?: (v: number) => boolean @@ -4257,9 +4263,18 @@ export const TransactionSwapQuoteValidate = (o?: TransactionSwapQuote, opts: Tra if (typeof o.chain_fee_sats !== 'number') return new Error(`${path}.chain_fee_sats: is not a number`) if (opts.chain_fee_sats_CustomCheck && !opts.chain_fee_sats_CustomCheck(o.chain_fee_sats)) return new Error(`${path}.chain_fee_sats: custom check failed`) + if (typeof o.completed_at_unix !== 'number') return new Error(`${path}.completed_at_unix: is not a number`) + if (opts.completed_at_unix_CustomCheck && !opts.completed_at_unix_CustomCheck(o.completed_at_unix)) return new Error(`${path}.completed_at_unix: custom check failed`) + + if (typeof o.expires_at_block_height !== 'number') return new Error(`${path}.expires_at_block_height: is not a number`) + if (opts.expires_at_block_height_CustomCheck && !opts.expires_at_block_height_CustomCheck(o.expires_at_block_height)) return new Error(`${path}.expires_at_block_height: custom check failed`) + if (typeof o.invoice_amount_sats !== 'number') return new Error(`${path}.invoice_amount_sats: is not a number`) if (opts.invoice_amount_sats_CustomCheck && !opts.invoice_amount_sats_CustomCheck(o.invoice_amount_sats)) return new Error(`${path}.invoice_amount_sats: custom check failed`) + if (typeof o.paid_at_unix !== 'number') return new Error(`${path}.paid_at_unix: is not a number`) + if (opts.paid_at_unix_CustomCheck && !opts.paid_at_unix_CustomCheck(o.paid_at_unix)) return new Error(`${path}.paid_at_unix: custom check failed`) + if (typeof o.service_fee_sats !== 'number') return new Error(`${path}.service_fee_sats: is not a number`) if (opts.service_fee_sats_CustomCheck && !opts.service_fee_sats_CustomCheck(o.service_fee_sats)) return new Error(`${path}.service_fee_sats: custom check failed`) @@ -4320,25 +4335,27 @@ export const TransactionSwapRequestValidate = (o?: TransactionSwapRequest, opts: } export type TxSwapOperation = { - address_paid: string + address_paid?: string failure_reason?: string operation_payment?: UserOperation - swap_operation_id: string + quote: TransactionSwapQuote + tx_id?: string } -export type TxSwapOperationOptionalField = 'failure_reason' | 'operation_payment' -export const TxSwapOperationOptionalFields: TxSwapOperationOptionalField[] = ['failure_reason', 'operation_payment'] +export type TxSwapOperationOptionalField = 'address_paid' | 'failure_reason' | 'operation_payment' | 'tx_id' +export const TxSwapOperationOptionalFields: TxSwapOperationOptionalField[] = ['address_paid', 'failure_reason', 'operation_payment', 'tx_id'] export type TxSwapOperationOptions = OptionsBaseMessage & { checkOptionalsAreSet?: TxSwapOperationOptionalField[] - address_paid_CustomCheck?: (v: string) => boolean + address_paid_CustomCheck?: (v?: string) => boolean failure_reason_CustomCheck?: (v?: string) => boolean operation_payment_Options?: UserOperationOptions - swap_operation_id_CustomCheck?: (v: string) => boolean + quote_Options?: TransactionSwapQuoteOptions + tx_id_CustomCheck?: (v?: string) => boolean } export const TxSwapOperationValidate = (o?: TxSwapOperation, opts: TxSwapOperationOptions = {}, path: string = 'TxSwapOperation::root.'): Error | null => { if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message') if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null') - if (typeof o.address_paid !== 'string') return new Error(`${path}.address_paid: is not a string`) + if ((o.address_paid || opts.allOptionalsAreSet || opts.checkOptionalsAreSet?.includes('address_paid')) && typeof o.address_paid !== 'string') return new Error(`${path}.address_paid: is not a string`) if (opts.address_paid_CustomCheck && !opts.address_paid_CustomCheck(o.address_paid)) return new Error(`${path}.address_paid: custom check failed`) if ((o.failure_reason || opts.allOptionalsAreSet || opts.checkOptionalsAreSet?.includes('failure_reason')) && typeof o.failure_reason !== 'string') return new Error(`${path}.failure_reason: is not a string`) @@ -4350,21 +4367,22 @@ export const TxSwapOperationValidate = (o?: TxSwapOperation, opts: TxSwapOperati } - if (typeof o.swap_operation_id !== 'string') return new Error(`${path}.swap_operation_id: is not a string`) - if (opts.swap_operation_id_CustomCheck && !opts.swap_operation_id_CustomCheck(o.swap_operation_id)) return new Error(`${path}.swap_operation_id: custom check failed`) + const quoteErr = TransactionSwapQuoteValidate(o.quote, opts.quote_Options, `${path}.quote`) + if (quoteErr !== null) return quoteErr + + + if ((o.tx_id || opts.allOptionalsAreSet || opts.checkOptionalsAreSet?.includes('tx_id')) && typeof o.tx_id !== 'string') return new Error(`${path}.tx_id: is not a string`) + if (opts.tx_id_CustomCheck && !opts.tx_id_CustomCheck(o.tx_id)) return new Error(`${path}.tx_id: custom check failed`) return null } export type TxSwapsList = { - quotes: TransactionSwapQuote[] swaps: TxSwapOperation[] } export const TxSwapsListOptionalFields: [] = [] export type TxSwapsListOptions = OptionsBaseMessage & { checkOptionalsAreSet?: [] - quotes_ItemOptions?: TransactionSwapQuoteOptions - quotes_CustomCheck?: (v: TransactionSwapQuote[]) => boolean swaps_ItemOptions?: TxSwapOperationOptions swaps_CustomCheck?: (v: TxSwapOperation[]) => boolean } @@ -4372,13 +4390,6 @@ export const TxSwapsListValidate = (o?: TxSwapsList, opts: TxSwapsListOptions = if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message') if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null') - if (!Array.isArray(o.quotes)) return new Error(`${path}.quotes: is not an array`) - for (let index = 0; index < o.quotes.length; index++) { - const quotesErr = TransactionSwapQuoteValidate(o.quotes[index], opts.quotes_ItemOptions, `${path}.quotes[${index}]`) - if (quotesErr !== null) return quotesErr - } - if (opts.quotes_CustomCheck && !opts.quotes_CustomCheck(o.quotes)) return new Error(`${path}.quotes: custom check failed`) - if (!Array.isArray(o.swaps)) return new Error(`${path}.swaps: is not an array`) for (let index = 0; index < o.swaps.length; index++) { const swapsErr = TxSwapOperationValidate(o.swaps[index], opts.swaps_ItemOptions, `${path}.swaps[${index}]`) diff --git a/proto/service/structs.proto b/proto/service/structs.proto index fb1f0867..694a6442 100644 --- a/proto/service/structs.proto +++ b/proto/service/structs.proto @@ -902,6 +902,10 @@ message TransactionSwapQuote { int64 chain_fee_sats = 5; int64 service_fee_sats = 7; string service_url = 8; + + int64 expires_at_block_height = 9; + int64 paid_at_unix = 10; + int64 completed_at_unix = 11; } message TransactionSwapQuoteList { @@ -914,15 +918,15 @@ message AdminTxSwapResponse { } message TxSwapOperation { - string swap_operation_id = 1; + TransactionSwapQuote quote = 1; optional UserOperation operation_payment = 2; optional string failure_reason = 3; - string address_paid = 4; + optional string address_paid = 4; + optional string tx_id = 5; } message TxSwapsList { repeated TxSwapOperation swaps = 1; - repeated TransactionSwapQuote quotes = 2; } message CumulativeFees { diff --git a/src/services/lnd/swaps/swaps.ts b/src/services/lnd/swaps/swaps.ts index c5abad05..dc1590b4 100644 --- a/src/services/lnd/swaps/swaps.ts +++ b/src/services/lnd/swaps/swaps.ts @@ -9,6 +9,7 @@ import { UserInvoicePayment } from '../../storage/entity/UserInvoicePayment.js'; import { ReverseSwaps, TransactionSwapData } from './reverseSwaps.js'; import { SubmarineSwaps, InvoiceSwapData } from './submarineSwaps.js'; import { InvoiceSwap } from '../../storage/entity/InvoiceSwap.js'; +import { TransactionSwap } from '../../storage/entity/TransactionSwap.js'; export class Swaps { @@ -271,32 +272,35 @@ export class Swaps { } } + private mapTransactionSwapQuote = (s: TransactionSwap, getServiceFee: (amt: number) => number): Types.TransactionSwapQuote => { + const serviceFee = getServiceFee(s.invoice_amount) + return { + swap_operation_id: s.swap_operation_id, + transaction_amount_sats: s.transaction_amount, + invoice_amount_sats: s.invoice_amount, + chain_fee_sats: s.chain_fee_sats, + service_fee_sats: serviceFee, + swap_fee_sats: s.swap_fee_sats, + expires_at_block_height: s.timeout_block_height, + service_url: s.service_url, + paid_at_unix: s.paid_at_unix, + completed_at_unix: s.completed_at_unix, + } + } + ListTxSwaps = async (appUserId: string, payments: UserInvoicePayment[], newOp: (p: UserInvoicePayment) => Types.UserOperation | undefined, getServiceFee: (amt: number) => number): Promise => { const completedSwaps = await this.storage.paymentStorage.ListCompletedTxSwaps(appUserId, payments) const pendingSwaps = await this.storage.paymentStorage.ListPendingTransactionSwaps(appUserId) + const quotes: Types.TxSwapOperation[] = pendingSwaps.map(s => ({ quote: this.mapTransactionSwapQuote(s, getServiceFee) })) + const swaps: Types.TxSwapOperation[] = completedSwaps.map(s => ({ + quote: this.mapTransactionSwapQuote(s.swap, getServiceFee), + operation_payment: s.payment ? newOp(s.payment) : undefined, + address_paid: s.swap.address_paid, + tx_id: s.swap.tx_id, + failure_reason: s.swap.failure_reason, + })) return { - swaps: completedSwaps.map(s => { - const p = s.payment - const op = p ? newOp(p) : undefined - return { - operation_payment: op, - swap_operation_id: s.swap.swap_operation_id, - address_paid: s.swap.address_paid, - failure_reason: s.swap.failure_reason, - } - }), - quotes: pendingSwaps.map(s => { - const serviceFee = getServiceFee(s.invoice_amount) - return { - swap_operation_id: s.swap_operation_id, - invoice_amount_sats: s.invoice_amount, - transaction_amount_sats: s.transaction_amount, - chain_fee_sats: s.chain_fee_sats, - service_fee_sats: serviceFee, - swap_fee_sats: s.swap_fee_sats, - service_url: s.service_url, - } - }) + swaps: swaps.concat(quotes), } } GetTxSwapQuotes = async (appUserId: string, amt: number, getServiceFee: (decodedAmt: number) => number): Promise => { @@ -364,6 +368,9 @@ export class Swaps { chain_fee_sats: minerFee, service_fee_sats: serviceFee, service_url: swapper.getHttpUrl(), + expires_at_block_height: res.createdResponse.timeoutBlockHeight, + paid_at_unix: newSwap.paid_at_unix, + completed_at_unix: newSwap.completed_at_unix, } } @@ -411,6 +418,7 @@ export class Swaps { swapResult = result }) try { + await this.storage.paymentStorage.SetTransactionSwapPaid(swapOpId) await payInvoice(txSwap.invoice, txSwap.invoice_amount) if (!swapResult.ok) { this.log("invoice payment successful, but swap failed") diff --git a/src/services/main/paymentManager.ts b/src/services/main/paymentManager.ts index 38c7658b..617641f4 100644 --- a/src/services/main/paymentManager.ts +++ b/src/services/main/paymentManager.ts @@ -625,7 +625,9 @@ export default class { } async ListTxSwaps(ctx: Types.UserContext): Promise { + console.log("listing tx swaps", { appUserId: ctx.app_user_id }) const payments = await this.storage.paymentStorage.ListTxSwapPayments(ctx.app_user_id) + console.log("payments", payments.length) const app = await this.storage.applicationStorage.GetApplication(ctx.app_id) const isManagedUser = ctx.user_id !== app.owner.user_id return this.swaps.ListTxSwaps(ctx.app_user_id, payments, p => { diff --git a/src/services/storage/db/serializationHelpers.ts b/src/services/storage/db/serializationHelpers.ts index eb27f678..ee19201f 100644 --- a/src/services/storage/db/serializationHelpers.ts +++ b/src/services/storage/db/serializationHelpers.ts @@ -8,10 +8,19 @@ type SerializedFindOperator = { } export function serializeFindOperator(operator: FindOperator): SerializedFindOperator { + let value: any; + if (Array.isArray(operator['value']) && operator['type'] !== 'between') { + value = operator['value'].map(serializeFindOperator); + } else if ((operator as any).child !== undefined) { + // Not(IsNull()) etc.: TypeORM's .value getter unwraps nested FindOperators, so we'd lose the inner operator. Use .child to serialize the nested operator. + value = serializeFindOperator((operator as any).child); + } else { + value = operator['value']; + } return { _type: 'FindOperator', type: operator['type'], - value: (Array.isArray(operator['value']) && operator['type'] !== 'between') ? operator["value"].map(serializeFindOperator) : operator["value"], + value, }; } @@ -51,7 +60,8 @@ export function deserializeFindOperator(serialized: SerializedFindOperator): Fin } } -export function serializeRequest(r: object): T { +export function serializeRequest(r: object, debug = false): T { + if (debug) console.log("serializeRequest", r) if (!r || typeof r !== 'object') { return r; } @@ -61,23 +71,24 @@ export function serializeRequest(r: object): T { } if (Array.isArray(r)) { - return r.map(item => serializeRequest(item)) as any; + return r.map(item => serializeRequest(item, debug)) as any; } const result: any = {}; for (const [key, value] of Object.entries(r)) { - result[key] = serializeRequest(value); + result[key] = serializeRequest(value, debug); } return result; } -export function deserializeRequest(r: object): T { +export function deserializeRequest(r: object, debug = false): T { + if (debug) console.log("deserializeRequest", r) if (!r || typeof r !== 'object') { return r; } if (Array.isArray(r)) { - return r.map(item => deserializeRequest(item)) as any; + return r.map(item => deserializeRequest(item, debug)) as any; } if (r && typeof r === 'object' && (r as any)._type === 'FindOperator') { @@ -86,7 +97,7 @@ export function deserializeRequest(r: object): T { const result: any = {}; for (const [key, value] of Object.entries(r)) { - result[key] = deserializeRequest(value); + result[key] = deserializeRequest(value, debug); } return result; } diff --git a/src/services/storage/db/storageInterface.ts b/src/services/storage/db/storageInterface.ts index 85b757f5..976ec20d 100644 --- a/src/services/storage/db/storageInterface.ts +++ b/src/services/storage/db/storageInterface.ts @@ -104,9 +104,10 @@ export class StorageInterface extends EventEmitter { return this.handleOp(findOp) } - Find(entity: DBNames, q: QueryOptions, txId?: string): Promise { + Find(entity: DBNames, q: QueryOptions, txId?: string, debug = false): Promise { + if (debug) console.log("Find", { entity }) const opId = Math.random().toString() - const findOp: FindOperation = { type: 'find', entity, opId, q, txId } + const findOp: FindOperation = { type: 'find', entity, opId, q, txId, debug } return this.handleOp(findOp) } @@ -166,15 +167,16 @@ export class StorageInterface extends EventEmitter { } private handleOp(op: IStorageOperation): Promise { - if (this.debug) console.log('handleOp', op) + if (this.debug || op.debug) console.log('handleOp', op) this.checkConnected() return new Promise((resolve, reject) => { const responseHandler = (response: OperationResponse) => { - if (this.debug) console.log('responseHandler', response) + if (this.debug || op.debug) console.log('responseHandler', response) if (!response.success) { reject(new Error(response.error)); return } + if (this.debug || op.debug) console.log("response", response, op) if (response.type !== op.type) { reject(new Error('Invalid storage response type')); return @@ -186,12 +188,12 @@ export class StorageInterface extends EventEmitter { }) } - private serializeOperation(operation: IStorageOperation): IStorageOperation { + private serializeOperation(operation: IStorageOperation, debug = false): IStorageOperation { const serialized = { ...operation }; if ('q' in serialized) { - (serialized as any).q = serializeRequest((serialized as any).q); + (serialized as any).q = serializeRequest((serialized as any).q, debug); } - if (this.debug) { + if (this.debug || debug) { serialized.debug = true } return serialized; diff --git a/src/services/storage/entity/TransactionSwap.ts b/src/services/storage/entity/TransactionSwap.ts index 7403e2a1..d2a99f52 100644 --- a/src/services/storage/entity/TransactionSwap.ts +++ b/src/services/storage/entity/TransactionSwap.ts @@ -60,6 +60,12 @@ export class TransactionSwap { @Column({ default: "" }) tx_id: string + @Column({ default: 0 }) + completed_at_unix: number + + @Column({ default: 0 }) + paid_at_unix: number + @Column({ default: "" }) address_paid: string diff --git a/src/services/storage/migrations/1771878683383-tx_swap_timestamps.ts b/src/services/storage/migrations/1771878683383-tx_swap_timestamps.ts new file mode 100644 index 00000000..be9ccade --- /dev/null +++ b/src/services/storage/migrations/1771878683383-tx_swap_timestamps.ts @@ -0,0 +1,20 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class TxSwapTimestamps1771878683383 implements MigrationInterface { + name = 'TxSwapTimestamps1771878683383' + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(`CREATE TABLE "temporary_transaction_swap" ("swap_operation_id" varchar PRIMARY KEY NOT NULL, "app_user_id" varchar NOT NULL, "swap_quote_id" varchar NOT NULL, "swap_tree" varchar NOT NULL, "lockup_address" varchar NOT NULL, "refund_public_key" varchar NOT NULL, "timeout_block_height" integer NOT NULL, "invoice" varchar NOT NULL, "invoice_amount" integer NOT NULL, "transaction_amount" integer NOT NULL, "swap_fee_sats" integer NOT NULL, "chain_fee_sats" integer NOT NULL, "preimage" varchar NOT NULL, "ephemeral_public_key" varchar NOT NULL, "ephemeral_private_key" varchar NOT NULL, "used" boolean NOT NULL DEFAULT (0), "failure_reason" varchar NOT NULL DEFAULT (''), "tx_id" varchar NOT NULL DEFAULT (''), "created_at" datetime NOT NULL DEFAULT (datetime('now')), "updated_at" datetime NOT NULL DEFAULT (datetime('now')), "address_paid" varchar NOT NULL DEFAULT (''), "service_url" varchar NOT NULL DEFAULT (''), "completed_at_unix" integer NOT NULL DEFAULT (0), "paid_at_unix" integer NOT NULL DEFAULT (0))`); + await queryRunner.query(`INSERT INTO "temporary_transaction_swap"("swap_operation_id", "app_user_id", "swap_quote_id", "swap_tree", "lockup_address", "refund_public_key", "timeout_block_height", "invoice", "invoice_amount", "transaction_amount", "swap_fee_sats", "chain_fee_sats", "preimage", "ephemeral_public_key", "ephemeral_private_key", "used", "failure_reason", "tx_id", "created_at", "updated_at", "address_paid", "service_url") SELECT "swap_operation_id", "app_user_id", "swap_quote_id", "swap_tree", "lockup_address", "refund_public_key", "timeout_block_height", "invoice", "invoice_amount", "transaction_amount", "swap_fee_sats", "chain_fee_sats", "preimage", "ephemeral_public_key", "ephemeral_private_key", "used", "failure_reason", "tx_id", "created_at", "updated_at", "address_paid", "service_url" FROM "transaction_swap"`); + await queryRunner.query(`DROP TABLE "transaction_swap"`); + await queryRunner.query(`ALTER TABLE "temporary_transaction_swap" RENAME TO "transaction_swap"`); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE "transaction_swap" RENAME TO "temporary_transaction_swap"`); + await queryRunner.query(`CREATE TABLE "transaction_swap" ("swap_operation_id" varchar PRIMARY KEY NOT NULL, "app_user_id" varchar NOT NULL, "swap_quote_id" varchar NOT NULL, "swap_tree" varchar NOT NULL, "lockup_address" varchar NOT NULL, "refund_public_key" varchar NOT NULL, "timeout_block_height" integer NOT NULL, "invoice" varchar NOT NULL, "invoice_amount" integer NOT NULL, "transaction_amount" integer NOT NULL, "swap_fee_sats" integer NOT NULL, "chain_fee_sats" integer NOT NULL, "preimage" varchar NOT NULL, "ephemeral_public_key" varchar NOT NULL, "ephemeral_private_key" varchar NOT NULL, "used" boolean NOT NULL DEFAULT (0), "failure_reason" varchar NOT NULL DEFAULT (''), "tx_id" varchar NOT NULL DEFAULT (''), "created_at" datetime NOT NULL DEFAULT (datetime('now')), "updated_at" datetime NOT NULL DEFAULT (datetime('now')), "address_paid" varchar NOT NULL DEFAULT (''), "service_url" varchar NOT NULL DEFAULT (''))`); + await queryRunner.query(`INSERT INTO "transaction_swap"("swap_operation_id", "app_user_id", "swap_quote_id", "swap_tree", "lockup_address", "refund_public_key", "timeout_block_height", "invoice", "invoice_amount", "transaction_amount", "swap_fee_sats", "chain_fee_sats", "preimage", "ephemeral_public_key", "ephemeral_private_key", "used", "failure_reason", "tx_id", "created_at", "updated_at", "address_paid", "service_url") SELECT "swap_operation_id", "app_user_id", "swap_quote_id", "swap_tree", "lockup_address", "refund_public_key", "timeout_block_height", "invoice", "invoice_amount", "transaction_amount", "swap_fee_sats", "chain_fee_sats", "preimage", "ephemeral_public_key", "ephemeral_private_key", "used", "failure_reason", "tx_id", "created_at", "updated_at", "address_paid", "service_url" FROM "temporary_transaction_swap"`); + await queryRunner.query(`DROP TABLE "temporary_transaction_swap"`); + } + +} diff --git a/src/services/storage/migrations/runner.ts b/src/services/storage/migrations/runner.ts index 1b5537d6..c78af2eb 100644 --- a/src/services/storage/migrations/runner.ts +++ b/src/services/storage/migrations/runner.ts @@ -1,28 +1,21 @@ import { Initial1703170309875 } from './1703170309875-initial.js' -import { LndMetrics1703170330183 } from './1703170330183-lnd_metrics.js' -import { ChannelRouting1709316653538 } from './1709316653538-channel_routing.js' import { LspOrder1718387847693 } from './1718387847693-lsp_order.js' import { LiquidityProvider1719335699480 } from './1719335699480-liquidity_provider.js' import { LndNodeInfo1720187506189 } from './1720187506189-lnd_node_info.js' import { TrackedProvider1720814323679 } from './1720814323679-tracked_provider.js' import { CreateInviteTokenTable1721751414878 } from "./1721751414878-create_invite_token_table.js" import { PaymentIndex1721760297610 } from './1721760297610-payment_index.js' -import { HtlcCount1724266887195 } from './1724266887195-htlc_count.js' -import { BalanceEvents1724860966825 } from './1724860966825-balance_events.js' import { DebitAccess1726496225078 } from './1726496225078-debit_access.js' import { DebitAccessFixes1726685229264 } from './1726685229264-debit_access_fixes.js' import { DebitToPub1727105758354 } from './1727105758354-debit_to_pub.js' import { UserCbUrl1727112281043 } from './1727112281043-user_cb_url.js' -import { RootOps1732566440447 } from './1732566440447-root_ops.js' import { UserOffer1733502626042 } from './1733502626042-user_offer.js' -import { RootOpsTime1745428134124 } from './1745428134124-root_ops_time.js' -import { ChannelEvents1750777346411 } from './1750777346411-channel_events.js' import { ManagementGrant1751307732346 } from './1751307732346-management_grant.js' import { ManagementGrantBanned1751989251513 } from './1751989251513-management_grant_banned.js' import { InvoiceCallbackUrls1752425992291 } from './1752425992291-invoice_callback_urls.js' -import { AppUserDevice1753285173175 } from './1753285173175-app_user_device.js' import { OldSomethingLeftover1753106599604 } from './1753106599604-old_something_leftover.js' import { UserReceivingInvoiceIdx1753109184611 } from './1753109184611-user_receiving_invoice_idx.js' +import { AppUserDevice1753285173175 } from './1753285173175-app_user_device.js' import { UserAccess1759426050669 } from './1759426050669-user_access.js' import { AddBlindToUserOffer1760000000000 } from './1760000000000-add_blind_to_user_offer.js' import { ApplicationAvatarUrl1761000001000 } from './1761000001000-application_avatar_url.js' @@ -32,11 +25,20 @@ import { TxSwapAddress1764779178945 } from './1764779178945-tx_swap_address.js' import { ClinkRequester1765497600000 } from './1765497600000-clink_requester.js' import { TrackedProviderHeight1766504040000 } from './1766504040000-tracked_provider_height.js' import { SwapsServiceUrl1768413055036 } from './1768413055036-swaps_service_url.js' - import { InvoiceSwaps1769529793283 } from './1769529793283-invoice_swaps.js' import { InvoiceSwapsFixes1769805357459 } from './1769805357459-invoice_swaps_fixes.js' import { ApplicationUserTopicId1770038768784 } from './1770038768784-application_user_topic_id.js' import { SwapTimestamps1771347307798 } from './1771347307798-swap_timestamps.js' +import { TxSwapTimestamps1771878683383 } from './1771878683383-tx_swap_timestamps.js' + +import { LndMetrics1703170330183 } from './1703170330183-lnd_metrics.js' +import { ChannelRouting1709316653538 } from './1709316653538-channel_routing.js' +import { HtlcCount1724266887195 } from './1724266887195-htlc_count.js' +import { BalanceEvents1724860966825 } from './1724860966825-balance_events.js' +import { RootOps1732566440447 } from './1732566440447-root_ops.js' +import { RootOpsTime1745428134124 } from './1745428134124-root_ops_time.js' +import { ChannelEvents1750777346411 } from './1750777346411-channel_events.js' + import { RootOpPending1771524665409 } from './1771524665409-root_op_pending.js' @@ -48,7 +50,8 @@ export const allMigrations = [Initial1703170309875, LspOrder1718387847693, Liqui InvoiceCallbackUrls1752425992291, OldSomethingLeftover1753106599604, UserReceivingInvoiceIdx1753109184611, AppUserDevice1753285173175, UserAccess1759426050669, AddBlindToUserOffer1760000000000, ApplicationAvatarUrl1761000001000, AdminSettings1761683639419, TxSwap1762890527098, TxSwapAddress1764779178945, ClinkRequester1765497600000, TrackedProviderHeight1766504040000, SwapsServiceUrl1768413055036, - InvoiceSwaps1769529793283, InvoiceSwapsFixes1769805357459, ApplicationUserTopicId1770038768784, SwapTimestamps1771347307798] + InvoiceSwaps1769529793283, InvoiceSwapsFixes1769805357459, ApplicationUserTopicId1770038768784, SwapTimestamps1771347307798, + TxSwapTimestamps1771878683383] export const allMetricsMigrations = [LndMetrics1703170330183, ChannelRouting1709316653538, HtlcCount1724266887195, BalanceEvents1724860966825, diff --git a/src/services/storage/paymentStorage.ts b/src/services/storage/paymentStorage.ts index 785f9909..fd6e6b30 100644 --- a/src/services/storage/paymentStorage.ts +++ b/src/services/storage/paymentStorage.ts @@ -473,19 +473,30 @@ export default class { return this.dbs.FindOne('TransactionSwap', { where: { swap_operation_id: swapOperationId, used: false, app_user_id: appUserId } }, txId) } + async SetTransactionSwapPaid(swapOperationId: string, txId?: string) { + const now = Math.floor(Date.now() / 1000) + return this.dbs.Update('TransactionSwap', { swap_operation_id: swapOperationId }, { + paid_at_unix: now, + }, txId) + } + async FinalizeTransactionSwap(swapOperationId: string, address: string, chainTxId: string, txId?: string) { + const now = Math.floor(Date.now() / 1000) return this.dbs.Update('TransactionSwap', { swap_operation_id: swapOperationId }, { used: true, tx_id: chainTxId, address_paid: address, + completed_at_unix: now, }, txId) } async FailTransactionSwap(swapOperationId: string, address: string, failureReason: string, txId?: string) { + const now = Math.floor(Date.now() / 1000) return this.dbs.Update('TransactionSwap', { swap_operation_id: swapOperationId }, { used: true, failure_reason: failureReason, address_paid: address, + completed_at_unix: now, }, txId) } From 2c8d57dd6e186f33297ce3b43e00f9a1f7816cd3 Mon Sep 17 00:00:00 2001 From: boufni95 Date: Wed, 25 Feb 2026 18:14:56 +0000 Subject: [PATCH 34/66] address amt validation --- src/services/main/paymentManager.ts | 6 ++++++ src/services/serverMethods/index.ts | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/services/main/paymentManager.ts b/src/services/main/paymentManager.ts index 617641f4..07021be5 100644 --- a/src/services/main/paymentManager.ts +++ b/src/services/main/paymentManager.ts @@ -595,9 +595,15 @@ export default class { async PayInternalAddress(ctx: Types.UserContext, req: Types.PayAddressRequest): Promise { this.log("paying internal address") + let amount = req.amountSats if (req.swap_operation_id) { + const swap = await this.storage.paymentStorage.GetTransactionSwap(req.swap_operation_id, ctx.app_user_id) + amount = amount > 0 ? amount : swap?.invoice_amount || 0 await this.storage.paymentStorage.DeleteTransactionSwap(req.swap_operation_id) } + if (amount <= 0) { + throw new Error("invalid tx amount") + } const { blockHeight } = await this.lnd.GetInfo() const app = await this.storage.applicationStorage.GetApplication(ctx.app_id) const isManagedUser = ctx.user_id !== app.owner.user_id diff --git a/src/services/serverMethods/index.ts b/src/services/serverMethods/index.ts index 21668449..6783e03d 100644 --- a/src/services/serverMethods/index.ts +++ b/src/services/serverMethods/index.ts @@ -184,7 +184,7 @@ export default (mainHandler: Main): Types.ServerMethods => { PayAddress: async ({ ctx, req }) => { const err = Types.PayAddressRequestValidate(req, { address_CustomCheck: addr => addr !== '', - amountSats_CustomCheck: amt => amt > 0, + // amountSats_CustomCheck: amt => amt > 0, // satsPerVByte_CustomCheck: spb => spb > 0 }) if (err != null) throw new Error(err.message) From ef14ec9ddfbd1762fff12d6a3dfaa51ff3f27be4 Mon Sep 17 00:00:00 2001 From: boufni95 Date: Thu, 26 Feb 2026 21:54:28 +0000 Subject: [PATCH 35/66] assets and liabilities --- proto/autogenerated/client.md | 58 +++++ proto/autogenerated/go/http_client.go | 30 +++ proto/autogenerated/go/types.go | 49 ++++ proto/autogenerated/ts/express_server.ts | 22 ++ proto/autogenerated/ts/http_client.ts | 14 + proto/autogenerated/ts/nostr_client.ts | 15 ++ proto/autogenerated/ts/nostr_transport.ts | 16 ++ proto/autogenerated/ts/types.ts | 303 +++++++++++++++++++++- proto/service/methods.proto | 7 + proto/service/structs.proto | 57 ++++ src/services/lnd/lnd.ts | 4 +- src/services/main/adminManager.ts | 256 ++++++++++++++++++ src/services/main/index.ts | 1 + src/services/main/liquidityProvider.ts | 4 +- src/services/main/paymentManager.ts | 2 +- src/services/main/sanityChecker.ts | 2 +- src/services/metrics/index.ts | 4 +- src/services/serverMethods/index.ts | 3 + src/services/storage/metricsStorage.ts | 3 + src/services/storage/paymentStorage.ts | 4 + 20 files changed, 843 insertions(+), 11 deletions(-) diff --git a/proto/autogenerated/client.md b/proto/autogenerated/client.md index d5b9baab..47db491b 100644 --- a/proto/autogenerated/client.md +++ b/proto/autogenerated/client.md @@ -108,6 +108,11 @@ The nostr server will send back a message response, and inside the body there wi - input: [AppsMetricsRequest](#AppsMetricsRequest) - output: [AppsMetrics](#AppsMetrics) +- GetAssetsAndLiabilities + - auth type: __Admin__ + - input: [AssetsAndLiabilitiesReq](#AssetsAndLiabilitiesReq) + - output: [AssetsAndLiabilities](#AssetsAndLiabilities) + - GetBundleMetrics - auth type: __Metrics__ - input: [LatestBundleMetricReq](#LatestBundleMetricReq) @@ -602,6 +607,13 @@ The nostr server will send back a message response, and inside the body there wi - input: [AppsMetricsRequest](#AppsMetricsRequest) - output: [AppsMetrics](#AppsMetrics) +- GetAssetsAndLiabilities + - auth type: __Admin__ + - http method: __post__ + - http route: __/api/admin/assets/liabilities__ + - input: [AssetsAndLiabilitiesReq](#AssetsAndLiabilitiesReq) + - output: [AssetsAndLiabilities](#AssetsAndLiabilities) + - GetBundleMetrics - auth type: __Metrics__ - http method: __post__ @@ -1186,6 +1198,21 @@ The nostr server will send back a message response, and inside the body there wi - __include_operations__: _boolean_ *this field is optional - __to_unix__: _number_ *this field is optional +### AssetOperation + - __amount__: _number_ + - __tracked__: _[TrackedOperation](#TrackedOperation)_ *this field is optional + - __ts__: _number_ + +### AssetsAndLiabilities + - __liquidity_providers__: ARRAY of: _[LiquidityAssetProvider](#LiquidityAssetProvider)_ + - __lnds__: ARRAY of: _[LndAssetProvider](#LndAssetProvider)_ + - __users_balance__: _number_ + +### AssetsAndLiabilitiesReq + - __limit_invoices__: _number_ *this field is optional + - __limit_payments__: _number_ *this field is optional + - __limit_providers__: _number_ *this field is optional + ### AuthApp - __app__: _[Application](#Application)_ - __auth_token__: _string_ @@ -1421,6 +1448,10 @@ The nostr server will send back a message response, and inside the body there wi ### LinkNPubThroughTokenRequest - __token__: _string_ +### LiquidityAssetProvider + - __pubkey__: _string_ + - __tracked__: _[TrackedLiquidityProvider](#TrackedLiquidityProvider)_ *this field is optional + ### LiveDebitRequest - __debit__: _[LiveDebitRequest_debit](#LiveDebitRequest_debit)_ - __npub__: _string_ @@ -1434,6 +1465,10 @@ The nostr server will send back a message response, and inside the body there wi - __latest_balance__: _number_ - __operation__: _[UserOperation](#UserOperation)_ +### LndAssetProvider + - __pubkey__: _string_ + - __tracked__: _[TrackedLndProvider](#TrackedLndProvider)_ *this field is optional + ### LndChannels - __open_channels__: ARRAY of: _[OpenChannel](#OpenChannel)_ @@ -1738,6 +1773,25 @@ The nostr server will send back a message response, and inside the body there wi - __page__: _number_ - __request_id__: _number_ *this field is optional +### TrackedLiquidityProvider + - __balance__: _number_ + - __invoices__: ARRAY of: _[AssetOperation](#AssetOperation)_ + - __payments__: ARRAY of: _[AssetOperation](#AssetOperation)_ + +### TrackedLndProvider + - __channels_balance__: _number_ + - __confirmed_balance__: _number_ + - __incoming_tx__: ARRAY of: _[AssetOperation](#AssetOperation)_ + - __invoices__: ARRAY of: _[AssetOperation](#AssetOperation)_ + - __outgoing_tx__: ARRAY of: _[AssetOperation](#AssetOperation)_ + - __payments__: ARRAY of: _[AssetOperation](#AssetOperation)_ + - __unconfirmed_balance__: _number_ + +### TrackedOperation + - __amount__: _number_ + - __ts__: _number_ + - __type__: _[TrackedOperationType](#TrackedOperationType)_ + ### TransactionSwapQuote - __chain_fee_sats__: _number_ - __invoice_amount_sats__: _number_ @@ -1870,6 +1924,10 @@ The nostr server will send back a message response, and inside the body there wi - __BUNDLE_METRIC__ - __USAGE_METRIC__ +### TrackedOperationType + - __ROOT__ + - __USER__ + ### UserOperationType - __INCOMING_INVOICE__ - __INCOMING_TX__ diff --git a/proto/autogenerated/go/http_client.go b/proto/autogenerated/go/http_client.go index 98c9c648..1d5219a6 100644 --- a/proto/autogenerated/go/http_client.go +++ b/proto/autogenerated/go/http_client.go @@ -80,6 +80,7 @@ type Client struct { GetAppUser func(req GetAppUserRequest) (*AppUser, error) GetAppUserLNURLInfo func(req GetAppUserLNURLInfoRequest) (*LnurlPayInfoResponse, error) GetAppsMetrics func(req AppsMetricsRequest) (*AppsMetrics, error) + GetAssetsAndLiabilities func(req AssetsAndLiabilitiesReq) (*AssetsAndLiabilities, error) GetBundleMetrics func(req LatestBundleMetricReq) (*BundleMetrics, error) GetDebitAuthorizations func() (*DebitAuthorizations, error) GetErrorStats func() (*ErrorStats, error) @@ -842,6 +843,35 @@ func NewClient(params ClientParams) *Client { } return &res, nil }, + GetAssetsAndLiabilities: func(req AssetsAndLiabilitiesReq) (*AssetsAndLiabilities, error) { + auth, err := params.RetrieveAdminAuth() + if err != nil { + return nil, err + } + finalRoute := "/api/admin/assets/liabilities" + body, err := json.Marshal(req) + if err != nil { + return nil, err + } + resBody, err := doPostRequest(params.BaseURL+finalRoute, body, auth) + if err != nil { + return nil, err + } + result := ResultError{} + err = json.Unmarshal(resBody, &result) + if err != nil { + return nil, err + } + if result.Status == "ERROR" { + return nil, fmt.Errorf(result.Reason) + } + res := AssetsAndLiabilities{} + err = json.Unmarshal(resBody, &res) + if err != nil { + return nil, err + } + return &res, nil + }, GetBundleMetrics: func(req LatestBundleMetricReq) (*BundleMetrics, error) { auth, err := params.RetrieveMetricsAuth() if err != nil { diff --git a/proto/autogenerated/go/types.go b/proto/autogenerated/go/types.go index d0efb918..e8a0c431 100644 --- a/proto/autogenerated/go/types.go +++ b/proto/autogenerated/go/types.go @@ -79,6 +79,13 @@ const ( USAGE_METRIC SingleMetricType = "USAGE_METRIC" ) +type TrackedOperationType string + +const ( + ROOT TrackedOperationType = "ROOT" + USER TrackedOperationType = "USER" +) + type UserOperationType string const ( @@ -163,6 +170,21 @@ type AppsMetricsRequest struct { Include_operations bool `json:"include_operations"` To_unix int64 `json:"to_unix"` } +type AssetOperation struct { + Amount int64 `json:"amount"` + Tracked *TrackedOperation `json:"tracked"` + Ts int64 `json:"ts"` +} +type AssetsAndLiabilities struct { + Liquidity_providers []LiquidityAssetProvider `json:"liquidity_providers"` + Lnds []LndAssetProvider `json:"lnds"` + Users_balance int64 `json:"users_balance"` +} +type AssetsAndLiabilitiesReq struct { + Limit_invoices int64 `json:"limit_invoices"` + Limit_payments int64 `json:"limit_payments"` + Limit_providers int64 `json:"limit_providers"` +} type AuthApp struct { App *Application `json:"app"` Auth_token string `json:"auth_token"` @@ -398,6 +420,10 @@ type LatestUsageMetricReq struct { type LinkNPubThroughTokenRequest struct { Token string `json:"token"` } +type LiquidityAssetProvider struct { + Pubkey string `json:"pubkey"` + Tracked *TrackedLiquidityProvider `json:"tracked"` +} type LiveDebitRequest struct { Debit *LiveDebitRequest_debit `json:"debit"` Npub string `json:"npub"` @@ -411,6 +437,10 @@ type LiveUserOperation struct { Latest_balance int64 `json:"latest_balance"` Operation *UserOperation `json:"operation"` } +type LndAssetProvider struct { + Pubkey string `json:"pubkey"` + Tracked *TrackedLndProvider `json:"tracked"` +} type LndChannels struct { Open_channels []OpenChannel `json:"open_channels"` } @@ -715,6 +745,25 @@ type SingleMetricReq struct { Page int64 `json:"page"` Request_id int64 `json:"request_id"` } +type TrackedLiquidityProvider struct { + Balance int64 `json:"balance"` + Invoices []AssetOperation `json:"invoices"` + Payments []AssetOperation `json:"payments"` +} +type TrackedLndProvider struct { + Channels_balance int64 `json:"channels_balance"` + Confirmed_balance int64 `json:"confirmed_balance"` + Incoming_tx []AssetOperation `json:"incoming_tx"` + Invoices []AssetOperation `json:"invoices"` + Outgoing_tx []AssetOperation `json:"outgoing_tx"` + Payments []AssetOperation `json:"payments"` + Unconfirmed_balance int64 `json:"unconfirmed_balance"` +} +type TrackedOperation struct { + Amount int64 `json:"amount"` + Ts int64 `json:"ts"` + Type TrackedOperationType `json:"type"` +} type TransactionSwapQuote struct { Chain_fee_sats int64 `json:"chain_fee_sats"` Invoice_amount_sats int64 `json:"invoice_amount_sats"` diff --git a/proto/autogenerated/ts/express_server.ts b/proto/autogenerated/ts/express_server.ts index 03ff728a..c0378ffa 100644 --- a/proto/autogenerated/ts/express_server.ts +++ b/proto/autogenerated/ts/express_server.ts @@ -998,6 +998,28 @@ export default (methods: Types.ServerMethods, opts: ServerOptions) => { opts.metricsCallback([{ ...info, ...stats, ...authContext }]) } catch (ex) { const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback); if (opts.throwErrors) throw e } }) + if (!opts.allowNotImplementedMethods && !methods.GetAssetsAndLiabilities) throw new Error('method: GetAssetsAndLiabilities is not implemented') + app.post('/api/admin/assets/liabilities', async (req, res) => { + const info: Types.RequestInfo = { rpcName: 'GetAssetsAndLiabilities', batch: false, nostr: false, batchSize: 0} + const stats: Types.RequestStats = { startMs:req.startTimeMs || 0, start:req.startTime || 0n, parse: process.hrtime.bigint(), guard: 0n, validate: 0n, handle: 0n } + let authCtx: Types.AuthContext = {} + try { + if (!methods.GetAssetsAndLiabilities) throw new Error('method: GetAssetsAndLiabilities is not implemented') + const authContext = await opts.AdminAuthGuard(req.headers['authorization']) + authCtx = authContext + stats.guard = process.hrtime.bigint() + const request = req.body + const error = Types.AssetsAndLiabilitiesReqValidate(request) + stats.validate = process.hrtime.bigint() + if (error !== null) return logErrorAndReturnResponse(error, 'invalid request body', res, logger, { ...info, ...stats, ...authContext }, opts.metricsCallback) + const query = req.query + const params = req.params + const response = await methods.GetAssetsAndLiabilities({rpcName:'GetAssetsAndLiabilities', ctx:authContext , req: request}) + stats.handle = process.hrtime.bigint() + res.json({status: 'OK', ...response}) + opts.metricsCallback([{ ...info, ...stats, ...authContext }]) + } catch (ex) { const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback); if (opts.throwErrors) throw e } + }) if (!opts.allowNotImplementedMethods && !methods.GetBundleMetrics) throw new Error('method: GetBundleMetrics is not implemented') app.post('/api/reports/bundle', async (req, res) => { const info: Types.RequestInfo = { rpcName: 'GetBundleMetrics', batch: false, nostr: false, batchSize: 0} diff --git a/proto/autogenerated/ts/http_client.ts b/proto/autogenerated/ts/http_client.ts index 195737be..ed68348f 100644 --- a/proto/autogenerated/ts/http_client.ts +++ b/proto/autogenerated/ts/http_client.ts @@ -357,6 +357,20 @@ export default (params: ClientParams) => ({ } return { status: 'ERROR', reason: 'invalid response' } }, + GetAssetsAndLiabilities: async (request: Types.AssetsAndLiabilitiesReq): Promise => { + const auth = await params.retrieveAdminAuth() + if (auth === null) throw new Error('retrieveAdminAuth() returned null') + let finalRoute = '/api/admin/assets/liabilities' + const { data } = await axios.post(params.baseUrl + finalRoute, request, { headers: { 'authorization': auth } }) + if (data.status === 'ERROR' && typeof data.reason === 'string') return data + if (data.status === 'OK') { + const result = data + if(!params.checkResult) return { status: 'OK', ...result } + const error = Types.AssetsAndLiabilitiesValidate(result) + if (error === null) { return { status: 'OK', ...result } } else return { status: 'ERROR', reason: error.message } + } + return { status: 'ERROR', reason: 'invalid response' } + }, GetBundleMetrics: async (request: Types.LatestBundleMetricReq): Promise => { const auth = await params.retrieveMetricsAuth() if (auth === null) throw new Error('retrieveMetricsAuth() returned null') diff --git a/proto/autogenerated/ts/nostr_client.ts b/proto/autogenerated/ts/nostr_client.ts index d174d247..b00e8f1a 100644 --- a/proto/autogenerated/ts/nostr_client.ts +++ b/proto/autogenerated/ts/nostr_client.ts @@ -275,6 +275,21 @@ export default (params: NostrClientParams, send: (to:string, message: NostrRequ } return { status: 'ERROR', reason: 'invalid response' } }, + GetAssetsAndLiabilities: async (request: Types.AssetsAndLiabilitiesReq): Promise => { + const auth = await params.retrieveNostrAdminAuth() + if (auth === null) throw new Error('retrieveNostrAdminAuth() returned null') + const nostrRequest: NostrRequest = {} + nostrRequest.body = request + const data = await send(params.pubDestination, {rpcName:'GetAssetsAndLiabilities',authIdentifier:auth, ...nostrRequest }) + if (data.status === 'ERROR' && typeof data.reason === 'string') return data + if (data.status === 'OK') { + const result = data + if(!params.checkResult) return { status: 'OK', ...result } + const error = Types.AssetsAndLiabilitiesValidate(result) + if (error === null) { return { status: 'OK', ...result } } else return { status: 'ERROR', reason: error.message } + } + return { status: 'ERROR', reason: 'invalid response' } + }, GetBundleMetrics: async (request: Types.LatestBundleMetricReq): Promise => { const auth = await params.retrieveNostrMetricsAuth() if (auth === null) throw new Error('retrieveNostrMetricsAuth() returned null') diff --git a/proto/autogenerated/ts/nostr_transport.ts b/proto/autogenerated/ts/nostr_transport.ts index 4f9307b3..c58b3283 100644 --- a/proto/autogenerated/ts/nostr_transport.ts +++ b/proto/autogenerated/ts/nostr_transport.ts @@ -735,6 +735,22 @@ export default (methods: Types.ServerMethods, opts: NostrOptions) => { opts.metricsCallback([{ ...info, ...stats, ...authContext }]) }catch(ex){ const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback); if (opts.throwErrors) throw e } break + case 'GetAssetsAndLiabilities': + try { + if (!methods.GetAssetsAndLiabilities) throw new Error('method: GetAssetsAndLiabilities is not implemented') + const authContext = await opts.NostrAdminAuthGuard(req.appId, req.authIdentifier) + stats.guard = process.hrtime.bigint() + authCtx = authContext + const request = req.body + const error = Types.AssetsAndLiabilitiesReqValidate(request) + stats.validate = process.hrtime.bigint() + if (error !== null) return logErrorAndReturnResponse(error, 'invalid request body', res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback) + const response = await methods.GetAssetsAndLiabilities({rpcName:'GetAssetsAndLiabilities', ctx:authContext , req: request}) + stats.handle = process.hrtime.bigint() + res({status: 'OK', ...response}) + opts.metricsCallback([{ ...info, ...stats, ...authContext }]) + }catch(ex){ const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback); if (opts.throwErrors) throw e } + break case 'GetBundleMetrics': try { if (!methods.GetBundleMetrics) throw new Error('method: GetBundleMetrics is not implemented') diff --git a/proto/autogenerated/ts/types.ts b/proto/autogenerated/ts/types.ts index f62fea43..1f1de167 100644 --- a/proto/autogenerated/ts/types.ts +++ b/proto/autogenerated/ts/types.ts @@ -7,8 +7,8 @@ export type RequestMetric = AuthContext & RequestInfo & RequestStats & { error?: export type AdminContext = { admin_id: string } -export type AdminMethodInputs = AddApp_Input | AddPeer_Input | AuthApp_Input | BanUser_Input | CloseChannel_Input | CreateOneTimeInviteLink_Input | GetAdminInvoiceSwapQuotes_Input | GetAdminTransactionSwapQuotes_Input | GetInviteLinkState_Input | GetSeed_Input | ListAdminInvoiceSwaps_Input | ListAdminTxSwaps_Input | ListChannels_Input | LndGetInfo_Input | OpenChannel_Input | PayAdminInvoiceSwap_Input | PayAdminTransactionSwap_Input | RefundAdminInvoiceSwap_Input | UpdateChannelPolicy_Input -export type AdminMethodOutputs = AddApp_Output | AddPeer_Output | AuthApp_Output | BanUser_Output | CloseChannel_Output | CreateOneTimeInviteLink_Output | GetAdminInvoiceSwapQuotes_Output | GetAdminTransactionSwapQuotes_Output | GetInviteLinkState_Output | GetSeed_Output | ListAdminInvoiceSwaps_Output | ListAdminTxSwaps_Output | ListChannels_Output | LndGetInfo_Output | OpenChannel_Output | PayAdminInvoiceSwap_Output | PayAdminTransactionSwap_Output | RefundAdminInvoiceSwap_Output | UpdateChannelPolicy_Output +export type AdminMethodInputs = AddApp_Input | AddPeer_Input | AuthApp_Input | BanUser_Input | CloseChannel_Input | CreateOneTimeInviteLink_Input | GetAdminInvoiceSwapQuotes_Input | GetAdminTransactionSwapQuotes_Input | GetAssetsAndLiabilities_Input | GetInviteLinkState_Input | GetSeed_Input | ListAdminInvoiceSwaps_Input | ListAdminTxSwaps_Input | ListChannels_Input | LndGetInfo_Input | OpenChannel_Input | PayAdminInvoiceSwap_Input | PayAdminTransactionSwap_Input | RefundAdminInvoiceSwap_Input | UpdateChannelPolicy_Input +export type AdminMethodOutputs = AddApp_Output | AddPeer_Output | AuthApp_Output | BanUser_Output | CloseChannel_Output | CreateOneTimeInviteLink_Output | GetAdminInvoiceSwapQuotes_Output | GetAdminTransactionSwapQuotes_Output | GetAssetsAndLiabilities_Output | GetInviteLinkState_Output | GetSeed_Output | ListAdminInvoiceSwaps_Output | ListAdminTxSwaps_Output | ListChannels_Output | LndGetInfo_Output | OpenChannel_Output | PayAdminInvoiceSwap_Output | PayAdminTransactionSwap_Output | RefundAdminInvoiceSwap_Output | UpdateChannelPolicy_Output export type AppContext = { app_id: string } @@ -117,6 +117,9 @@ export type GetAppUserLNURLInfo_Output = ResultError | ({ status: 'OK' } & Lnurl export type GetAppsMetrics_Input = {rpcName:'GetAppsMetrics', req: AppsMetricsRequest} export type GetAppsMetrics_Output = ResultError | ({ status: 'OK' } & AppsMetrics) +export type GetAssetsAndLiabilities_Input = {rpcName:'GetAssetsAndLiabilities', req: AssetsAndLiabilitiesReq} +export type GetAssetsAndLiabilities_Output = ResultError | ({ status: 'OK' } & AssetsAndLiabilities) + export type GetBundleMetrics_Input = {rpcName:'GetBundleMetrics', req: LatestBundleMetricReq} export type GetBundleMetrics_Output = ResultError | ({ status: 'OK' } & BundleMetrics) @@ -375,6 +378,7 @@ export type ServerMethods = { GetAppUser?: (req: GetAppUser_Input & {ctx: AppContext }) => Promise GetAppUserLNURLInfo?: (req: GetAppUserLNURLInfo_Input & {ctx: AppContext }) => Promise GetAppsMetrics?: (req: GetAppsMetrics_Input & {ctx: MetricsContext }) => Promise + GetAssetsAndLiabilities?: (req: GetAssetsAndLiabilities_Input & {ctx: AdminContext }) => Promise GetBundleMetrics?: (req: GetBundleMetrics_Input & {ctx: MetricsContext }) => Promise GetDebitAuthorizations?: (req: GetDebitAuthorizations_Input & {ctx: UserContext }) => Promise GetErrorStats?: (req: GetErrorStats_Input & {ctx: MetricsContext }) => Promise @@ -481,6 +485,14 @@ export const enumCheckSingleMetricType = (e?: SingleMetricType): boolean => { for (const v in SingleMetricType) if (e === v) return true return false } +export enum TrackedOperationType { + ROOT = 'ROOT', + USER = 'USER', +} +export const enumCheckTrackedOperationType = (e?: TrackedOperationType): boolean => { + for (const v in TrackedOperationType) if (e === v) return true + return false +} export enum UserOperationType { INCOMING_INVOICE = 'INCOMING_INVOICE', INCOMING_TX = 'INCOMING_TX', @@ -929,6 +941,105 @@ export const AppsMetricsRequestValidate = (o?: AppsMetricsRequest, opts: AppsMet return null } +export type AssetOperation = { + amount: number + tracked?: TrackedOperation + ts: number +} +export type AssetOperationOptionalField = 'tracked' +export const AssetOperationOptionalFields: AssetOperationOptionalField[] = ['tracked'] +export type AssetOperationOptions = OptionsBaseMessage & { + checkOptionalsAreSet?: AssetOperationOptionalField[] + amount_CustomCheck?: (v: number) => boolean + tracked_Options?: TrackedOperationOptions + ts_CustomCheck?: (v: number) => boolean +} +export const AssetOperationValidate = (o?: AssetOperation, opts: AssetOperationOptions = {}, path: string = 'AssetOperation::root.'): Error | null => { + if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message') + if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null') + + if (typeof o.amount !== 'number') return new Error(`${path}.amount: is not a number`) + if (opts.amount_CustomCheck && !opts.amount_CustomCheck(o.amount)) return new Error(`${path}.amount: custom check failed`) + + if (typeof o.tracked === 'object' || opts.allOptionalsAreSet || opts.checkOptionalsAreSet?.includes('tracked')) { + const trackedErr = TrackedOperationValidate(o.tracked, opts.tracked_Options, `${path}.tracked`) + if (trackedErr !== null) return trackedErr + } + + + if (typeof o.ts !== 'number') return new Error(`${path}.ts: is not a number`) + if (opts.ts_CustomCheck && !opts.ts_CustomCheck(o.ts)) return new Error(`${path}.ts: custom check failed`) + + return null +} + +export type AssetsAndLiabilities = { + liquidity_providers: LiquidityAssetProvider[] + lnds: LndAssetProvider[] + users_balance: number +} +export const AssetsAndLiabilitiesOptionalFields: [] = [] +export type AssetsAndLiabilitiesOptions = OptionsBaseMessage & { + checkOptionalsAreSet?: [] + liquidity_providers_ItemOptions?: LiquidityAssetProviderOptions + liquidity_providers_CustomCheck?: (v: LiquidityAssetProvider[]) => boolean + lnds_ItemOptions?: LndAssetProviderOptions + lnds_CustomCheck?: (v: LndAssetProvider[]) => boolean + users_balance_CustomCheck?: (v: number) => boolean +} +export const AssetsAndLiabilitiesValidate = (o?: AssetsAndLiabilities, opts: AssetsAndLiabilitiesOptions = {}, path: string = 'AssetsAndLiabilities::root.'): Error | null => { + if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message') + if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null') + + if (!Array.isArray(o.liquidity_providers)) return new Error(`${path}.liquidity_providers: is not an array`) + for (let index = 0; index < o.liquidity_providers.length; index++) { + const liquidity_providersErr = LiquidityAssetProviderValidate(o.liquidity_providers[index], opts.liquidity_providers_ItemOptions, `${path}.liquidity_providers[${index}]`) + if (liquidity_providersErr !== null) return liquidity_providersErr + } + if (opts.liquidity_providers_CustomCheck && !opts.liquidity_providers_CustomCheck(o.liquidity_providers)) return new Error(`${path}.liquidity_providers: custom check failed`) + + if (!Array.isArray(o.lnds)) return new Error(`${path}.lnds: is not an array`) + for (let index = 0; index < o.lnds.length; index++) { + const lndsErr = LndAssetProviderValidate(o.lnds[index], opts.lnds_ItemOptions, `${path}.lnds[${index}]`) + if (lndsErr !== null) return lndsErr + } + if (opts.lnds_CustomCheck && !opts.lnds_CustomCheck(o.lnds)) return new Error(`${path}.lnds: custom check failed`) + + if (typeof o.users_balance !== 'number') return new Error(`${path}.users_balance: is not a number`) + if (opts.users_balance_CustomCheck && !opts.users_balance_CustomCheck(o.users_balance)) return new Error(`${path}.users_balance: custom check failed`) + + return null +} + +export type AssetsAndLiabilitiesReq = { + limit_invoices?: number + limit_payments?: number + limit_providers?: number +} +export type AssetsAndLiabilitiesReqOptionalField = 'limit_invoices' | 'limit_payments' | 'limit_providers' +export const AssetsAndLiabilitiesReqOptionalFields: AssetsAndLiabilitiesReqOptionalField[] = ['limit_invoices', 'limit_payments', 'limit_providers'] +export type AssetsAndLiabilitiesReqOptions = OptionsBaseMessage & { + checkOptionalsAreSet?: AssetsAndLiabilitiesReqOptionalField[] + limit_invoices_CustomCheck?: (v?: number) => boolean + limit_payments_CustomCheck?: (v?: number) => boolean + limit_providers_CustomCheck?: (v?: number) => boolean +} +export const AssetsAndLiabilitiesReqValidate = (o?: AssetsAndLiabilitiesReq, opts: AssetsAndLiabilitiesReqOptions = {}, path: string = 'AssetsAndLiabilitiesReq::root.'): Error | null => { + if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message') + if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null') + + if ((o.limit_invoices || opts.allOptionalsAreSet || opts.checkOptionalsAreSet?.includes('limit_invoices')) && typeof o.limit_invoices !== 'number') return new Error(`${path}.limit_invoices: is not a number`) + if (opts.limit_invoices_CustomCheck && !opts.limit_invoices_CustomCheck(o.limit_invoices)) return new Error(`${path}.limit_invoices: custom check failed`) + + if ((o.limit_payments || opts.allOptionalsAreSet || opts.checkOptionalsAreSet?.includes('limit_payments')) && typeof o.limit_payments !== 'number') return new Error(`${path}.limit_payments: is not a number`) + if (opts.limit_payments_CustomCheck && !opts.limit_payments_CustomCheck(o.limit_payments)) return new Error(`${path}.limit_payments: custom check failed`) + + if ((o.limit_providers || opts.allOptionalsAreSet || opts.checkOptionalsAreSet?.includes('limit_providers')) && typeof o.limit_providers !== 'number') return new Error(`${path}.limit_providers: is not a number`) + if (opts.limit_providers_CustomCheck && !opts.limit_providers_CustomCheck(o.limit_providers)) return new Error(`${path}.limit_providers: custom check failed`) + + return null +} + export type AuthApp = { app: Application auth_token: string @@ -2358,6 +2469,33 @@ export const LinkNPubThroughTokenRequestValidate = (o?: LinkNPubThroughTokenRequ return null } +export type LiquidityAssetProvider = { + pubkey: string + tracked?: TrackedLiquidityProvider +} +export type LiquidityAssetProviderOptionalField = 'tracked' +export const LiquidityAssetProviderOptionalFields: LiquidityAssetProviderOptionalField[] = ['tracked'] +export type LiquidityAssetProviderOptions = OptionsBaseMessage & { + checkOptionalsAreSet?: LiquidityAssetProviderOptionalField[] + pubkey_CustomCheck?: (v: string) => boolean + tracked_Options?: TrackedLiquidityProviderOptions +} +export const LiquidityAssetProviderValidate = (o?: LiquidityAssetProvider, opts: LiquidityAssetProviderOptions = {}, path: string = 'LiquidityAssetProvider::root.'): Error | null => { + if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message') + if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null') + + if (typeof o.pubkey !== 'string') return new Error(`${path}.pubkey: is not a string`) + if (opts.pubkey_CustomCheck && !opts.pubkey_CustomCheck(o.pubkey)) return new Error(`${path}.pubkey: custom check failed`) + + if (typeof o.tracked === 'object' || opts.allOptionalsAreSet || opts.checkOptionalsAreSet?.includes('tracked')) { + const trackedErr = TrackedLiquidityProviderValidate(o.tracked, opts.tracked_Options, `${path}.tracked`) + if (trackedErr !== null) return trackedErr + } + + + return null +} + export type LiveDebitRequest = { debit: LiveDebitRequest_debit npub: string @@ -2434,6 +2572,33 @@ export const LiveUserOperationValidate = (o?: LiveUserOperation, opts: LiveUserO return null } +export type LndAssetProvider = { + pubkey: string + tracked?: TrackedLndProvider +} +export type LndAssetProviderOptionalField = 'tracked' +export const LndAssetProviderOptionalFields: LndAssetProviderOptionalField[] = ['tracked'] +export type LndAssetProviderOptions = OptionsBaseMessage & { + checkOptionalsAreSet?: LndAssetProviderOptionalField[] + pubkey_CustomCheck?: (v: string) => boolean + tracked_Options?: TrackedLndProviderOptions +} +export const LndAssetProviderValidate = (o?: LndAssetProvider, opts: LndAssetProviderOptions = {}, path: string = 'LndAssetProvider::root.'): Error | null => { + if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message') + if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null') + + if (typeof o.pubkey !== 'string') return new Error(`${path}.pubkey: is not a string`) + if (opts.pubkey_CustomCheck && !opts.pubkey_CustomCheck(o.pubkey)) return new Error(`${path}.pubkey: custom check failed`) + + if (typeof o.tracked === 'object' || opts.allOptionalsAreSet || opts.checkOptionalsAreSet?.includes('tracked')) { + const trackedErr = TrackedLndProviderValidate(o.tracked, opts.tracked_Options, `${path}.tracked`) + if (trackedErr !== null) return trackedErr + } + + + return null +} + export type LndChannels = { open_channels: OpenChannel[] } @@ -4230,6 +4395,140 @@ export const SingleMetricReqValidate = (o?: SingleMetricReq, opts: SingleMetricR return null } +export type TrackedLiquidityProvider = { + balance: number + invoices: AssetOperation[] + payments: AssetOperation[] +} +export const TrackedLiquidityProviderOptionalFields: [] = [] +export type TrackedLiquidityProviderOptions = OptionsBaseMessage & { + checkOptionalsAreSet?: [] + balance_CustomCheck?: (v: number) => boolean + invoices_ItemOptions?: AssetOperationOptions + invoices_CustomCheck?: (v: AssetOperation[]) => boolean + payments_ItemOptions?: AssetOperationOptions + payments_CustomCheck?: (v: AssetOperation[]) => boolean +} +export const TrackedLiquidityProviderValidate = (o?: TrackedLiquidityProvider, opts: TrackedLiquidityProviderOptions = {}, path: string = 'TrackedLiquidityProvider::root.'): Error | null => { + if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message') + if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null') + + if (typeof o.balance !== 'number') return new Error(`${path}.balance: is not a number`) + if (opts.balance_CustomCheck && !opts.balance_CustomCheck(o.balance)) return new Error(`${path}.balance: custom check failed`) + + if (!Array.isArray(o.invoices)) return new Error(`${path}.invoices: is not an array`) + for (let index = 0; index < o.invoices.length; index++) { + const invoicesErr = AssetOperationValidate(o.invoices[index], opts.invoices_ItemOptions, `${path}.invoices[${index}]`) + if (invoicesErr !== null) return invoicesErr + } + if (opts.invoices_CustomCheck && !opts.invoices_CustomCheck(o.invoices)) return new Error(`${path}.invoices: custom check failed`) + + if (!Array.isArray(o.payments)) return new Error(`${path}.payments: is not an array`) + for (let index = 0; index < o.payments.length; index++) { + const paymentsErr = AssetOperationValidate(o.payments[index], opts.payments_ItemOptions, `${path}.payments[${index}]`) + if (paymentsErr !== null) return paymentsErr + } + if (opts.payments_CustomCheck && !opts.payments_CustomCheck(o.payments)) return new Error(`${path}.payments: custom check failed`) + + return null +} + +export type TrackedLndProvider = { + channels_balance: number + confirmed_balance: number + incoming_tx: AssetOperation[] + invoices: AssetOperation[] + outgoing_tx: AssetOperation[] + payments: AssetOperation[] + unconfirmed_balance: number +} +export const TrackedLndProviderOptionalFields: [] = [] +export type TrackedLndProviderOptions = OptionsBaseMessage & { + checkOptionalsAreSet?: [] + channels_balance_CustomCheck?: (v: number) => boolean + confirmed_balance_CustomCheck?: (v: number) => boolean + incoming_tx_ItemOptions?: AssetOperationOptions + incoming_tx_CustomCheck?: (v: AssetOperation[]) => boolean + invoices_ItemOptions?: AssetOperationOptions + invoices_CustomCheck?: (v: AssetOperation[]) => boolean + outgoing_tx_ItemOptions?: AssetOperationOptions + outgoing_tx_CustomCheck?: (v: AssetOperation[]) => boolean + payments_ItemOptions?: AssetOperationOptions + payments_CustomCheck?: (v: AssetOperation[]) => boolean + unconfirmed_balance_CustomCheck?: (v: number) => boolean +} +export const TrackedLndProviderValidate = (o?: TrackedLndProvider, opts: TrackedLndProviderOptions = {}, path: string = 'TrackedLndProvider::root.'): Error | null => { + if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message') + if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null') + + if (typeof o.channels_balance !== 'number') return new Error(`${path}.channels_balance: is not a number`) + if (opts.channels_balance_CustomCheck && !opts.channels_balance_CustomCheck(o.channels_balance)) return new Error(`${path}.channels_balance: custom check failed`) + + if (typeof o.confirmed_balance !== 'number') return new Error(`${path}.confirmed_balance: is not a number`) + if (opts.confirmed_balance_CustomCheck && !opts.confirmed_balance_CustomCheck(o.confirmed_balance)) return new Error(`${path}.confirmed_balance: custom check failed`) + + if (!Array.isArray(o.incoming_tx)) return new Error(`${path}.incoming_tx: is not an array`) + for (let index = 0; index < o.incoming_tx.length; index++) { + const incoming_txErr = AssetOperationValidate(o.incoming_tx[index], opts.incoming_tx_ItemOptions, `${path}.incoming_tx[${index}]`) + if (incoming_txErr !== null) return incoming_txErr + } + if (opts.incoming_tx_CustomCheck && !opts.incoming_tx_CustomCheck(o.incoming_tx)) return new Error(`${path}.incoming_tx: custom check failed`) + + if (!Array.isArray(o.invoices)) return new Error(`${path}.invoices: is not an array`) + for (let index = 0; index < o.invoices.length; index++) { + const invoicesErr = AssetOperationValidate(o.invoices[index], opts.invoices_ItemOptions, `${path}.invoices[${index}]`) + if (invoicesErr !== null) return invoicesErr + } + if (opts.invoices_CustomCheck && !opts.invoices_CustomCheck(o.invoices)) return new Error(`${path}.invoices: custom check failed`) + + if (!Array.isArray(o.outgoing_tx)) return new Error(`${path}.outgoing_tx: is not an array`) + for (let index = 0; index < o.outgoing_tx.length; index++) { + const outgoing_txErr = AssetOperationValidate(o.outgoing_tx[index], opts.outgoing_tx_ItemOptions, `${path}.outgoing_tx[${index}]`) + if (outgoing_txErr !== null) return outgoing_txErr + } + if (opts.outgoing_tx_CustomCheck && !opts.outgoing_tx_CustomCheck(o.outgoing_tx)) return new Error(`${path}.outgoing_tx: custom check failed`) + + if (!Array.isArray(o.payments)) return new Error(`${path}.payments: is not an array`) + for (let index = 0; index < o.payments.length; index++) { + const paymentsErr = AssetOperationValidate(o.payments[index], opts.payments_ItemOptions, `${path}.payments[${index}]`) + if (paymentsErr !== null) return paymentsErr + } + if (opts.payments_CustomCheck && !opts.payments_CustomCheck(o.payments)) return new Error(`${path}.payments: custom check failed`) + + if (typeof o.unconfirmed_balance !== 'number') return new Error(`${path}.unconfirmed_balance: is not a number`) + if (opts.unconfirmed_balance_CustomCheck && !opts.unconfirmed_balance_CustomCheck(o.unconfirmed_balance)) return new Error(`${path}.unconfirmed_balance: custom check failed`) + + return null +} + +export type TrackedOperation = { + amount: number + ts: number + type: TrackedOperationType +} +export const TrackedOperationOptionalFields: [] = [] +export type TrackedOperationOptions = OptionsBaseMessage & { + checkOptionalsAreSet?: [] + amount_CustomCheck?: (v: number) => boolean + ts_CustomCheck?: (v: number) => boolean + type_CustomCheck?: (v: TrackedOperationType) => boolean +} +export const TrackedOperationValidate = (o?: TrackedOperation, opts: TrackedOperationOptions = {}, path: string = 'TrackedOperation::root.'): Error | null => { + if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message') + if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null') + + if (typeof o.amount !== 'number') return new Error(`${path}.amount: is not a number`) + if (opts.amount_CustomCheck && !opts.amount_CustomCheck(o.amount)) return new Error(`${path}.amount: custom check failed`) + + if (typeof o.ts !== 'number') return new Error(`${path}.ts: is not a number`) + if (opts.ts_CustomCheck && !opts.ts_CustomCheck(o.ts)) return new Error(`${path}.ts: custom check failed`) + + if (!enumCheckTrackedOperationType(o.type)) return new Error(`${path}.type: is not a valid TrackedOperationType`) + if (opts.type_CustomCheck && !opts.type_CustomCheck(o.type)) return new Error(`${path}.type: custom check failed`) + + return null +} + export type TransactionSwapQuote = { chain_fee_sats: number invoice_amount_sats: number diff --git a/proto/service/methods.proto b/proto/service/methods.proto index 3eeef126..d7f97860 100644 --- a/proto/service/methods.proto +++ b/proto/service/methods.proto @@ -112,6 +112,13 @@ service LightningPub { option (nostr) = true; }; + rpc GetAssetsAndLiabilities(structs.AssetsAndLiabilitiesReq) returns (structs.AssetsAndLiabilities) { + option (auth_type) = "Admin"; + option (http_method) = "post"; + option (http_route) = "/api/admin/assets/liabilities"; + option (nostr) = true; + } + rpc AddApp(structs.AddAppRequest) returns (structs.AuthApp) { option (auth_type) = "Admin"; option (http_method) = "post"; diff --git a/proto/service/structs.proto b/proto/service/structs.proto index fb1f0867..44d17dec 100644 --- a/proto/service/structs.proto +++ b/proto/service/structs.proto @@ -19,6 +19,61 @@ message EncryptionExchangeRequest { string deviceId = 2; } +message AssetsAndLiabilitiesReq { + optional int64 limit_invoices = 1; + optional int64 limit_payments = 2; + optional int64 limit_providers = 4; +} + +enum TrackedOperationType { + USER = 0; + ROOT = 1; +} + +message TrackedOperation { + int64 ts = 1; + int64 amount = 2; + TrackedOperationType type = 3; +} + +message AssetOperation { + int64 ts = 1; + int64 amount = 2; + optional TrackedOperation tracked = 3; +} + +message TrackedLndProvider { + int64 confirmed_balance = 1; + int64 unconfirmed_balance = 2; + int64 channels_balance = 3; + repeated AssetOperation payments = 4; + repeated AssetOperation invoices = 5; + repeated AssetOperation incoming_tx = 6; + repeated AssetOperation outgoing_tx = 7; +} + +message TrackedLiquidityProvider { + int64 balance = 1; + repeated AssetOperation payments = 2; + repeated AssetOperation invoices = 3; +} + +message LndAssetProvider { + string pubkey = 1; + optional TrackedLndProvider tracked = 2; +} + +message LiquidityAssetProvider { + string pubkey = 1; + optional TrackedLiquidityProvider tracked = 2; +} + +message AssetsAndLiabilities { + int64 users_balance = 1; + repeated LndAssetProvider lnds = 2; + repeated LiquidityAssetProvider liquidity_providers = 3; +} + message UserHealthState { string downtime_reason = 1; } @@ -37,6 +92,8 @@ message ErrorStats { ErrorStat past1m = 5; } + + message MetricsFile { } diff --git a/src/services/lnd/lnd.ts b/src/services/lnd/lnd.ts index 6d71d424..673ff073 100644 --- a/src/services/lnd/lnd.ts +++ b/src/services/lnd/lnd.ts @@ -542,7 +542,7 @@ export default class { async GetTransactions(startHeight: number): Promise { this.log(DEBUG, "Getting transactions") - const res = await this.lightning.getTransactions({ startHeight, endHeight: 0, account: "" }, DeadLineMetadata()) + const res = await this.lightning.getTransactions({ startHeight, endHeight: 0, account: "", }, DeadLineMetadata()) return res.response } @@ -625,7 +625,7 @@ export default class { return response } - async GetAllPaidInvoices(max: number) { + async GetAllInvoices(max: number) { this.log(DEBUG, "Getting all paid invoices") if (this.liquidProvider.getSettings().useOnlyLiquidityProvider) { return { invoices: [] } diff --git a/src/services/main/adminManager.ts b/src/services/main/adminManager.ts index e8147aa6..d605dbe6 100644 --- a/src/services/main/adminManager.ts +++ b/src/services/main/adminManager.ts @@ -7,8 +7,48 @@ import LND from "../lnd/lnd.js"; import SettingsManager from "./settingsManager.js"; import { Swaps } from "../lnd/swaps/swaps.js"; import { defaultInvoiceExpiry } from "../storage/paymentStorage.js"; +import { TrackedProvider } from "../storage/entity/TrackedProvider.js"; +import { NodeInfo } from "../lnd/settings.js"; +import { Invoice, Payment, OutputDetail, Transaction, Payment_PaymentStatus, Invoice_InvoiceState } from "../../../proto/lnd/lightning.js"; +import { LiquidityProvider } from "./liquidityProvider.js"; +/* type TrackedOperation = { + ts: number + amount: number + type: 'user' | 'root' +} + +type AssetOperation = { + ts: number + amount: number + tracked?: TrackedOperation +} +type TrackedLndProvider = { + confirmedBalance: number + unconfirmedBalance: number + channelsBalace: number + payments: AssetOperation[] + invoices: AssetOperation[] + incomingTx: AssetOperation[] + outgoingTx: AssetOperation[] +} +type LndAssetProvider = { + pubkey: string + tracked?: TrackedLndProvider +} +type TrackedLiquidityProvider = { + balance: number + payments: AssetOperation[] + invoices: AssetOperation[] +} +type ProviderAssetProvider = { + pubkey: string + tracked?: TrackedLiquidityProvider +} */ +const ROOT_OP = Types.TrackedOperationType.ROOT +const USER_OP = Types.TrackedOperationType.USER export class AdminManager { settings: SettingsManager + liquidityProvider: LiquidityProvider | null = null storage: Storage log = getLogger({ component: "adminManager" }) adminNpub = "" @@ -41,6 +81,10 @@ export class AdminManager { this.start() } + attachLiquidityProvider(liquidityProvider: LiquidityProvider) { + this.liquidityProvider = liquidityProvider + } + attachNostrReset(f: () => Promise) { this.nostrReset = f } @@ -332,6 +376,218 @@ export class AdminManager { network_fee: swap.network_fee, } } + + async GetAssetsAndLiabilities(req: Types.AssetsAndLiabilitiesReq): Promise { + const providers = await this.storage.liquidityStorage.GetTrackedProviders() + + const lnds: Types.LndAssetProvider[] = [] + const liquidityProviders: Types.LiquidityAssetProvider[] = [] + for (const provider of providers) { + if (provider.provider_type === 'lnd') { + const lndEntry = await this.GetLndAssetsAndLiabilities(req, provider) + lnds.push(lndEntry) + } else if (provider.provider_type === 'lnPub') { + const liquidityEntry = await this.GetProviderAssetsAndLiabilities(req, provider) + liquidityProviders.push(liquidityEntry) + } + } + const usersBalance = await this.storage.paymentStorage.GetTotalUsersBalance() + return { + users_balance: usersBalance, + lnds, + liquidity_providers: liquidityProviders, + } + } + + async GetProviderAssetsAndLiabilities(req: Types.AssetsAndLiabilitiesReq, provider: TrackedProvider): Promise { + if (!this.liquidityProvider) { + throw new Error("liquidity provider not attached") + } + if (this.liquidityProvider.GetProviderPubkey() !== provider.provider_pubkey) { + return { pubkey: provider.provider_pubkey, tracked: undefined } + } + const providerOps = await this.liquidityProvider.GetOperations(req.limit_providers || 100) + // we only care about invoices cuz they are the only ops we can generate with a provider + const invoices: Types.AssetOperation[] = [] + const payments: Types.AssetOperation[] = [] + for (const op of providerOps.latestIncomingInvoiceOperations.operations) { + const assetOp = await this.GetProviderInvoiceAssetOperation(op) + invoices.push(assetOp) + } + for (const op of providerOps.latestOutgoingInvoiceOperations.operations) { + const assetOp = await this.GetProviderPaymentAssetOperation(op) + payments.push(assetOp) + } + const balance = await this.liquidityProvider.GetUserState() + return { + pubkey: provider.provider_pubkey, + tracked: { + balance: balance.status === 'OK' ? balance.balance : 0, + payments, + invoices, + } + } + } + + async GetProviderInvoiceAssetOperation(op: Types.UserOperation): Promise { + const ts = Number(op.paidAtUnix) + const amount = Number(op.amount) + const invoice = op.identifier + const userInvoice = await this.storage.paymentStorage.GetInvoiceOwner(invoice) + if (userInvoice) { + const tracked: Types.TrackedOperation = { ts: userInvoice.paid_at_unix, amount: userInvoice.paid_amount, type: USER_OP } + return { ts, amount, tracked } + } + const rootOp = await this.storage.metricsStorage.GetRootOperation("invoice", invoice) + if (rootOp) { + const tracked: Types.TrackedOperation = { ts: rootOp.at_unix, amount: rootOp.operation_amount, type: ROOT_OP } + return { ts, amount, tracked } + } + return { ts, amount, tracked: undefined } + } + + async GetProviderPaymentAssetOperation(op: Types.UserOperation): Promise { + const ts = Number(op.paidAtUnix) + const amount = Number(op.amount) + const invoice = op.identifier + const userInvoice = await this.storage.paymentStorage.GetPaymentOwner(invoice) + if (userInvoice) { + const tracked: Types.TrackedOperation = { ts: userInvoice.paid_at_unix, amount: userInvoice.paid_amount, type: USER_OP } + return { ts, amount, tracked } + } + const rootOp = await this.storage.metricsStorage.GetRootOperation("invoice_payment", invoice) + if (rootOp) { + const tracked: Types.TrackedOperation = { ts: rootOp.at_unix, amount: rootOp.operation_amount, type: ROOT_OP } + return { ts, amount, tracked } + } + return { ts, amount, tracked: undefined } + } + + async GetLndAssetsAndLiabilities(req: Types.AssetsAndLiabilitiesReq, provider: TrackedProvider): Promise { + const info = await this.lnd.GetInfo() + if (provider.provider_pubkey !== info.identityPubkey) { + return { pubkey: provider.provider_pubkey, tracked: undefined } + } + + const latestLndPayments = await this.lnd.GetAllPayments(req.limit_payments || 50) + const payments: Types.AssetOperation[] = [] + for (const payment of latestLndPayments.payments) { + if (payment.status !== Payment_PaymentStatus.SUCCEEDED) { + continue + } + const assetOp = await this.GetPaymentAssetOperation(payment) + payments.push(assetOp) + } + const invoices: Types.AssetOperation[] = [] + const paidInvoices = await this.lnd.GetAllInvoices(req.limit_invoices || 100) + for (const invoiceEntry of paidInvoices.invoices) { + if (invoiceEntry.state !== Invoice_InvoiceState.SETTLED) { + continue + } + const assetOp = await this.GetInvoiceAssetOperation(invoiceEntry) + invoices.push(assetOp) + } + const latestLndTransactions = await this.lnd.GetTransactions(info.blockHeight) + const txOuts: Types.AssetOperation[] = [] + const txIns: Types.AssetOperation[] = [] + for (const transaction of latestLndTransactions.transactions) { + for (const output of transaction.outputDetails) { + if (output.isOurAddress) { + const assetOp = await this.GetTxOutAssetOperation(transaction, output) + txOuts.push(assetOp) + } + } + // we only produce TXs with a single output + const input = transaction.previousOutpoints.find(p => p.isOurOutput) + if (input) { + const assetOp = await this.GetTxInAssetOperation(transaction) + txIns.push(assetOp) + } + } + const balance = await this.lnd.GetBalance() + const channelsBalance = balance.channelsBalance.reduce((acc, c) => acc + Number(c.localBalanceSats), 0) + return { + pubkey: provider.provider_pubkey, + tracked: { + confirmed_balance: Number(balance.confirmedBalance), + unconfirmed_balance: Number(balance.unconfirmedBalance), + channels_balance: channelsBalance, + payments, + invoices, + incoming_tx: txOuts, // tx outputs, are incoming sats + outgoing_tx: txIns, // tx inputs, are outgoing sats + } + } + } + + async GetPaymentAssetOperation(payment: Payment): Promise { + const invoice = payment.paymentRequest + const userInvoice = await this.storage.paymentStorage.GetPaymentOwner(invoice) + const ts = Number(payment.creationTimeNs / (BigInt(1000_000_000))) + const amount = Number(payment.valueSat) + if (userInvoice) { + const tracked: Types.TrackedOperation = { ts: userInvoice.paid_at_unix, amount: userInvoice.paid_amount, type: USER_OP } + return { ts, amount, tracked } + } + const rootOp = await this.storage.metricsStorage.GetRootOperation("invoice_payment", invoice) + if (rootOp) { + const tracked: Types.TrackedOperation = { ts: rootOp.at_unix, amount: rootOp.operation_amount, type: ROOT_OP } + return { ts, amount, tracked } + } + return { ts, amount, tracked: undefined } + } + + async GetInvoiceAssetOperation(invoiceEntry: Invoice): Promise { + const invoice = invoiceEntry.paymentRequest + const ts = Number(invoiceEntry.settleDate) + const amount = Number(invoiceEntry.amtPaidSat) + const userInvoice = await this.storage.paymentStorage.GetInvoiceOwner(invoice) + if (userInvoice) { + const tracked: Types.TrackedOperation = { ts: userInvoice.paid_at_unix, amount: userInvoice.paid_amount, type: USER_OP } + return { ts, amount, tracked } + } + const rootOp = await this.storage.metricsStorage.GetRootOperation("invoice", invoice) + if (rootOp) { + const tracked: Types.TrackedOperation = { ts: rootOp.at_unix, amount: rootOp.operation_amount, type: ROOT_OP } + return { ts, amount, tracked } + } + return { ts, amount, tracked: undefined } + } + + async GetTxInAssetOperation(tx: Transaction): Promise { + const ts = Number(tx.timeStamp) + const amount = Number(tx.amount) + const userOp = await this.storage.paymentStorage.GetTxHashPaymentOwner(tx.txHash) + if (userOp) { + // user transaction payments are actually deprecated from lnd, but we keep this for consstency + const tracked: Types.TrackedOperation = { ts: userOp.paid_at_unix, amount: userOp.paid_amount, type: USER_OP } + return { ts, amount, tracked } + } + const rootOp = await this.storage.metricsStorage.GetRootOperation("chain_payment", tx.txHash) + if (rootOp) { + const tracked: Types.TrackedOperation = { ts: rootOp.at_unix, amount: rootOp.operation_amount, type: ROOT_OP } + return { ts, amount, tracked } + } + return { ts, amount, tracked: undefined } + } + + async GetTxOutAssetOperation(tx: Transaction, output: OutputDetail): Promise { + const ts = Number(tx.timeStamp) + const amount = Number(output.amount) + const outputIndex = Number(output.outputIndex) + const userOp = await this.storage.paymentStorage.GetAddressReceivingTransactionOwner(output.address, tx.txHash) + if (userOp) { + const tracked: Types.TrackedOperation = { ts: userOp.paid_at_unix, amount: userOp.paid_amount, type: USER_OP } + return { ts, amount, tracked } + } + const rootOp = await this.storage.metricsStorage.GetRootAddressTransaction(output.address, tx.txHash, outputIndex) + if (rootOp) { + const tracked: Types.TrackedOperation = { ts: rootOp.at_unix, amount: rootOp.operation_amount, type: ROOT_OP } + return { ts, amount, tracked } + } + return { ts, amount, tracked: undefined } + } + } const getDataPath = (dataDir: string, dataPath: string) => { diff --git a/src/services/main/index.ts b/src/services/main/index.ts index 3d5a976c..81de5ada 100644 --- a/src/services/main/index.ts +++ b/src/services/main/index.ts @@ -72,6 +72,7 @@ export default class { this.unlocker = unlocker const updateProviderBalance = (b: number) => this.storage.liquidityStorage.IncrementTrackedProviderBalance('lnPub', settings.getSettings().liquiditySettings.liquidityProviderPub, b) this.liquidityProvider = new LiquidityProvider(() => this.settings.getSettings().liquiditySettings, this.utils, this.invoicePaidCb, updateProviderBalance) + adminManager.attachLiquidityProvider(this.liquidityProvider) this.rugPullTracker = new RugPullTracker(this.storage, this.liquidityProvider) const lndGetSettings = () => ({ lndSettings: settings.getSettings().lndSettings, diff --git a/src/services/main/liquidityProvider.ts b/src/services/main/liquidityProvider.ts index 1f8fe2dd..a39f86a6 100644 --- a/src/services/main/liquidityProvider.ts +++ b/src/services/main/liquidityProvider.ts @@ -277,14 +277,14 @@ export class LiquidityProvider { return res } - GetOperations = async () => { + GetOperations = async (max = 200) => { if (!this.IsReady()) { throw new Error("liquidity provider is not ready yet, disabled or unreachable") } const res = await this.client.GetUserOperations({ latestIncomingInvoice: { ts: 0, id: 0 }, latestOutgoingInvoice: { ts: 0, id: 0 }, latestIncomingTx: { ts: 0, id: 0 }, latestOutgoingTx: { ts: 0, id: 0 }, latestIncomingUserToUserPayment: { ts: 0, id: 0 }, - latestOutgoingUserToUserPayment: { ts: 0, id: 0 }, max_size: 200 + latestOutgoingUserToUserPayment: { ts: 0, id: 0 }, max_size: max }) if (res.status === 'ERROR') { this.log("error getting operations", res.reason) diff --git a/src/services/main/paymentManager.ts b/src/services/main/paymentManager.ts index 38c7658b..964699be 100644 --- a/src/services/main/paymentManager.ts +++ b/src/services/main/paymentManager.ts @@ -267,7 +267,7 @@ export default class { return false } const outputIndex = Number(output.outputIndex) - const existingRootOp = await this.metrics.GetRootAddressTransaction(output.address, tx.txHash, outputIndex) + const existingRootOp = await this.storage.metricsStorage.GetRootAddressTransaction(output.address, tx.txHash, outputIndex) if (existingRootOp) { return false } diff --git a/src/services/main/sanityChecker.ts b/src/services/main/sanityChecker.ts index 6ef7419a..cb0ecb75 100644 --- a/src/services/main/sanityChecker.ts +++ b/src/services/main/sanityChecker.ts @@ -226,7 +226,7 @@ export default class SanityChecker { async VerifyEventsLog() { this.events = await this.storage.eventsLog.GetAllLogs() - this.invoices = (await this.lnd.GetAllPaidInvoices(1000)).invoices + this.invoices = (await this.lnd.GetAllInvoices(1000)).invoices this.payments = (await this.lnd.GetAllPayments(1000)).payments this.incrementSources = {} diff --git a/src/services/metrics/index.ts b/src/services/metrics/index.ts index 20c92a95..9e23b665 100644 --- a/src/services/metrics/index.ts +++ b/src/services/metrics/index.ts @@ -414,9 +414,7 @@ export default class Handler { await this.storage.metricsStorage.AddRootOperation("chain", `${address}:${txOutput.hash}:${txOutput.index}`, amount) } - async GetRootAddressTransaction(address: string, txHash: string, index: number) { - return this.storage.metricsStorage.GetRootOperation("chain", `${address}:${txHash}:${index}`) - } + async AddRootInvoicePaid(paymentRequest: string, amount: number) { await this.storage.metricsStorage.AddRootOperation("invoice", paymentRequest, amount) diff --git a/src/services/serverMethods/index.ts b/src/services/serverMethods/index.ts index 21668449..46fc30cc 100644 --- a/src/services/serverMethods/index.ts +++ b/src/services/serverMethods/index.ts @@ -133,6 +133,9 @@ export default (mainHandler: Main): Types.ServerMethods => { if (err != null) throw new Error(err.message) return mainHandler.adminManager.PayAdminInvoiceSwap(req) }, + GetAssetsAndLiabilities: async ({ ctx, req }) => { + return mainHandler.adminManager.GetAssetsAndLiabilities(req) + }, GetProvidersDisruption: async () => { return mainHandler.metricsManager.GetProvidersDisruption() }, diff --git a/src/services/storage/metricsStorage.ts b/src/services/storage/metricsStorage.ts index b388a587..d80d11c9 100644 --- a/src/services/storage/metricsStorage.ts +++ b/src/services/storage/metricsStorage.ts @@ -156,6 +156,9 @@ export default class { async GetRootOperation(opType: RootOperationType, id: string, txId?: string) { return this.dbs.FindOne('RootOperation', { where: { operation_type: opType, operation_identifier: id } }, txId) } + async GetRootAddressTransaction(address: string, txHash: string, index: number) { + return this.GetRootOperation("chain", `${address}:${txHash}:${index}`) + } async GetPendingChainPayments() { return this.dbs.Find('RootOperation', { where: { operation_type: 'chain_payment', pending: true } }) diff --git a/src/services/storage/paymentStorage.ts b/src/services/storage/paymentStorage.ts index 785f9909..fd9fb157 100644 --- a/src/services/storage/paymentStorage.ts +++ b/src/services/storage/paymentStorage.ts @@ -152,6 +152,10 @@ export default class { return this.dbs.FindOne('UserTransactionPayment', { where: { address, tx_hash: txHash } }, txId) } + async GetTxHashPaymentOwner(txHash: string, txId?: string): Promise { + return this.dbs.FindOne('UserTransactionPayment', { where: { tx_hash: txHash } }, txId) + } + async GetInvoiceOwner(paymentRequest: string, txId?: string): Promise { return this.dbs.FindOne('UserReceivingInvoice', { where: { invoice: paymentRequest } }, txId) } From 574f229cee322b760f2c4e85dbd8287e6f4ba3d3 Mon Sep 17 00:00:00 2001 From: boufni95 Date: Mon, 2 Mar 2026 18:49:22 +0000 Subject: [PATCH 36/66] activte cleanup --- src/services/main/adminManager.ts | 2 +- src/services/main/appUserManager.ts | 12 ++++++++++-- src/services/storage/paymentStorage.ts | 8 ++++++-- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/services/main/adminManager.ts b/src/services/main/adminManager.ts index d605dbe6..e0639547 100644 --- a/src/services/main/adminManager.ts +++ b/src/services/main/adminManager.ts @@ -391,7 +391,7 @@ export class AdminManager { liquidityProviders.push(liquidityEntry) } } - const usersBalance = await this.storage.paymentStorage.GetTotalUsersBalance() + const usersBalance = await this.storage.paymentStorage.GetTotalUsersBalance(true) return { users_balance: usersBalance, lnds, diff --git a/src/services/main/appUserManager.ts b/src/services/main/appUserManager.ts index e1db3637..2a2ade08 100644 --- a/src/services/main/appUserManager.ts +++ b/src/services/main/appUserManager.ts @@ -132,7 +132,7 @@ export default class { } this.log("Found", toDelete.length, "inactive users to delete") - // await this.RemoveUsers(toDelete) + await this.LockUsers(toDelete.map(u => u.userId)) } async CleanupNeverActiveUsers() { @@ -161,7 +161,15 @@ export default class { } this.log("Found", toDelete.length, "never active users to delete") - // await this.RemoveUsers(toDelete) TODO: activate deletion + await this.RemoveUsers(toDelete) + } + + async LockUsers(toLock: string[]) { + this.log("Locking", toLock.length, "users") + for (const userId of toLock) { + await this.storage.userStorage.BanUser(userId) + } + this.log("Locked users") } async RemoveUsers(toDelete: { userId: string, appUserIds: string[] }[]) { diff --git a/src/services/storage/paymentStorage.ts b/src/services/storage/paymentStorage.ts index 2d5417e4..dc2ec847 100644 --- a/src/services/storage/paymentStorage.ts +++ b/src/services/storage/paymentStorage.ts @@ -452,8 +452,12 @@ export default class { } } - async GetTotalUsersBalance(txId?: string) { - const total = await this.dbs.Sum('User', "balance_sats", {}) + async GetTotalUsersBalance(excludeLocked?: boolean, txId?: string) { + const where: { locked?: boolean } = {} + if (excludeLocked) { + where.locked = false + } + const total = await this.dbs.Sum('User', "balance_sats", where, txId) return total || 0 } From 432f9d0b42529961a65e103b14fa3fd130ebbd21 Mon Sep 17 00:00:00 2001 From: shocknet-justin Date: Mon, 2 Mar 2026 14:33:53 -0500 Subject: [PATCH 37/66] bump never active to 90 --- src/services/main/appUserManager.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/services/main/appUserManager.ts b/src/services/main/appUserManager.ts index 2a2ade08..b81f8e2e 100644 --- a/src/services/main/appUserManager.ts +++ b/src/services/main/appUserManager.ts @@ -137,7 +137,7 @@ export default class { async CleanupNeverActiveUsers() { this.log("Cleaning up never active users") - const inactiveUsers = await this.storage.userStorage.GetInactiveUsers(30) + const inactiveUsers = await this.storage.userStorage.GetInactiveUsers(90) const toDelete: { userId: string, appUserIds: string[] }[] = [] for (const u of inactiveUsers) { const user = await this.storage.userStorage.GetUser(u.user_id) From 7af841c33047dcc036030aea2bfcd43b26b1a6d3 Mon Sep 17 00:00:00 2001 From: shocknet-justin Date: Mon, 2 Mar 2026 14:44:32 -0500 Subject: [PATCH 38/66] cleanup db fix --- src/services/storage/paymentStorage.ts | 20 ++++++++++++++++++-- src/services/storage/productStorage.ts | 10 +++++++++- 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/src/services/storage/paymentStorage.ts b/src/services/storage/paymentStorage.ts index dc2ec847..092ef8df 100644 --- a/src/services/storage/paymentStorage.ts +++ b/src/services/storage/paymentStorage.ts @@ -138,7 +138,15 @@ export default class { } async RemoveUserInvoices(userId: string, txId?: string) { - return this.dbs.Delete('UserReceivingInvoice', { user: { user_id: userId } }, txId) + const invoices = await this.dbs.Find('UserReceivingInvoice', { where: { user: { user_id: userId } } }, txId) + if (invoices.length === 0) { + return 0 + } + let deleted = 0 + for (const invoice of invoices) { + deleted += await this.dbs.Delete('UserReceivingInvoice', invoice.serial_id, txId) + } + return deleted } async GetAddressOwner(address: string, txId?: string): Promise { @@ -322,7 +330,15 @@ export default class { } async RemoveUserEphemeralKeys(userId: string, txId?: string) { - return this.dbs.Delete('UserEphemeralKey', { user: { user_id: userId } }, txId) + const keys = await this.dbs.Find('UserEphemeralKey', { where: { user: { user_id: userId } } }, txId) + if (keys.length === 0) { + return 0 + } + let deleted = 0 + for (const key of keys) { + deleted += await this.dbs.Delete('UserEphemeralKey', key.serial_id, txId) + } + return deleted } async AddPendingUserToUserPayment(fromUserId: string, toUserId: string, amount: number, fee: number, linkedApplication: Application, txId: string) { diff --git a/src/services/storage/productStorage.ts b/src/services/storage/productStorage.ts index e6f2f662..75f3da0d 100644 --- a/src/services/storage/productStorage.ts +++ b/src/services/storage/productStorage.ts @@ -21,6 +21,14 @@ export default class { } async RemoveUserProducts(userId: string, txId?: string) { - return this.dbs.Delete('Product', { owner: { user_id: userId } }, txId) + const products = await this.dbs.Find('Product', { where: { owner: { user_id: userId } } }, txId) + if (products.length === 0) { + return 0 + } + let deleted = 0 + for (const product of products) { + deleted += await this.dbs.Delete('Product', { product_id: product.product_id }, txId) + } + return deleted } } \ No newline at end of file From be6f48427fb82b97571928a4b007674a1dbdbec1 Mon Sep 17 00:00:00 2001 From: shocknet-justin Date: Mon, 2 Mar 2026 14:56:48 -0500 Subject: [PATCH 39/66] clean users table --- src/services/main/appUserManager.ts | 3 ++- src/services/storage/userStorage.ts | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/services/main/appUserManager.ts b/src/services/main/appUserManager.ts index b81f8e2e..8bb56e21 100644 --- a/src/services/main/appUserManager.ts +++ b/src/services/main/appUserManager.ts @@ -183,11 +183,12 @@ export default class { await this.storage.offerStorage.DeleteUserOffers(appUserId, tx) await this.storage.debitStorage.RemoveUserDebitAccess(appUserId, tx) await this.storage.applicationStorage.RemoveAppUserDevices(appUserId, tx) - } await this.storage.paymentStorage.RemoveUserInvoices(userId, tx) await this.storage.productStorage.RemoveUserProducts(userId, tx) await this.storage.paymentStorage.RemoveUserEphemeralKeys(userId, tx) + await this.storage.userStorage.DeleteUserAccess(userId, tx) + await this.storage.applicationStorage.RemoveAppUsersAndBaseUsers(appUserIds, userId, tx) }) } this.log("Cleaned up inactive users") diff --git a/src/services/storage/userStorage.ts b/src/services/storage/userStorage.ts index d3453346..a1541bac 100644 --- a/src/services/storage/userStorage.ts +++ b/src/services/storage/userStorage.ts @@ -126,4 +126,8 @@ export default class { const lastSeenAtUnix = now - seconds return this.dbs.Find('UserAccess', { where: { last_seen_at_unix: LessThan(lastSeenAtUnix) } }) } + + async DeleteUserAccess(userId: string, txId?: string) { + return this.dbs.Delete('UserAccess', { user_id: userId }, txId) + } } From cfb7dd1e6ecfde1f96ee62d6da3608601df143c2 Mon Sep 17 00:00:00 2001 From: shocknet-justin Date: Mon, 2 Mar 2026 15:01:12 -0500 Subject: [PATCH 40/66] serial id --- src/services/main/appUserManager.ts | 5 +++++ src/services/storage/applicationStorage.ts | 14 ++++++++++---- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/services/main/appUserManager.ts b/src/services/main/appUserManager.ts index 8bb56e21..b87a648d 100644 --- a/src/services/main/appUserManager.ts +++ b/src/services/main/appUserManager.ts @@ -176,6 +176,11 @@ export default class { this.log("Deleting", toDelete.length, "inactive users") for (let i = 0; i < toDelete.length; i++) { const { userId, appUserIds } = toDelete[i] + const user = await this.storage.userStorage.FindUser(userId) + if (!user || user.balance_sats > 0) { + if (user) this.log("Skipping user", userId, "has balance", user.balance_sats) + continue + } this.log("Deleting user", userId, "progress", i + 1, "/", toDelete.length) await this.storage.StartTransaction(async tx => { for (const appUserId of appUserIds) { diff --git a/src/services/storage/applicationStorage.ts b/src/services/storage/applicationStorage.ts index 08aad37a..77438ee3 100644 --- a/src/services/storage/applicationStorage.ts +++ b/src/services/storage/applicationStorage.ts @@ -161,10 +161,16 @@ export default class { this.dbs.Remove('User', baseUser, txId) } - async RemoveAppUsersAndBaseUsers(appUserIds: string[],baseUser:string, txId?: string) { - await this.dbs.Delete('ApplicationUser', { identifier: In(appUserIds) }, txId) - await this.dbs.Delete('User', { user_id: baseUser }, txId) - + async RemoveAppUsersAndBaseUsers(appUserIds: string[], baseUser: string, txId?: string) { + if (appUserIds.length > 0) { + const appUsers = await this.dbs.Find('ApplicationUser', { where: { identifier: In(appUserIds) } }, txId) + for (const appUser of appUsers) { + await this.dbs.Delete('ApplicationUser', appUser.serial_id, txId) + } + } + const user = await this.userStorage.FindUser(baseUser, txId) + if (!user) return + await this.dbs.Delete('User', user.serial_id, txId) } From bfa71f743918ccaaf9025c63224a234e8a258bd8 Mon Sep 17 00:00:00 2001 From: shocknet-justin Date: Mon, 2 Mar 2026 15:08:56 -0500 Subject: [PATCH 41/66] cleanup fix --- src/services/storage/applicationStorage.ts | 12 ++++++------ src/services/storage/paymentStorage.ts | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/services/storage/applicationStorage.ts b/src/services/storage/applicationStorage.ts index 77438ee3..dba5b466 100644 --- a/src/services/storage/applicationStorage.ts +++ b/src/services/storage/applicationStorage.ts @@ -1,5 +1,5 @@ import crypto from 'crypto'; -import { Between, FindOperator, IsNull, LessThanOrEqual, MoreThanOrEqual, In } from "typeorm" +import { Between, FindOperator, IsNull, LessThanOrEqual, MoreThanOrEqual } from "typeorm" import { generateSecretKey, getPublicKey } from 'nostr-tools'; import { Application } from "./entity/Application.js" import UserStorage from './userStorage.js'; @@ -162,15 +162,15 @@ export default class { } async RemoveAppUsersAndBaseUsers(appUserIds: string[], baseUser: string, txId?: string) { - if (appUserIds.length > 0) { - const appUsers = await this.dbs.Find('ApplicationUser', { where: { identifier: In(appUserIds) } }, txId) - for (const appUser of appUsers) { - await this.dbs.Delete('ApplicationUser', appUser.serial_id, txId) + for (const appUserId of appUserIds) { + const appUser = await this.dbs.FindOne('ApplicationUser', { where: { identifier: appUserId } }, txId) + if (appUser) { + await this.dbs.Delete('ApplicationUser', { serial_id: appUser.serial_id }, txId) } } const user = await this.userStorage.FindUser(baseUser, txId) if (!user) return - await this.dbs.Delete('User', user.serial_id, txId) + await this.dbs.Delete('User', { serial_id: user.serial_id }, txId) } diff --git a/src/services/storage/paymentStorage.ts b/src/services/storage/paymentStorage.ts index 092ef8df..16f17f75 100644 --- a/src/services/storage/paymentStorage.ts +++ b/src/services/storage/paymentStorage.ts @@ -144,7 +144,7 @@ export default class { } let deleted = 0 for (const invoice of invoices) { - deleted += await this.dbs.Delete('UserReceivingInvoice', invoice.serial_id, txId) + deleted += await this.dbs.Delete('UserReceivingInvoice', { serial_id: invoice.serial_id }, txId) } return deleted } @@ -336,7 +336,7 @@ export default class { } let deleted = 0 for (const key of keys) { - deleted += await this.dbs.Delete('UserEphemeralKey', key.serial_id, txId) + deleted += await this.dbs.Delete('UserEphemeralKey', { serial_id: key.serial_id }, txId) } return deleted } From c18b79dc5033cfacd4516cccd2470a0d8427f9b3 Mon Sep 17 00:00:00 2001 From: shocknet-justin Date: Mon, 2 Mar 2026 15:10:24 -0500 Subject: [PATCH 42/66] use number --- src/services/storage/applicationStorage.ts | 4 ++-- src/services/storage/paymentStorage.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/services/storage/applicationStorage.ts b/src/services/storage/applicationStorage.ts index dba5b466..402e7773 100644 --- a/src/services/storage/applicationStorage.ts +++ b/src/services/storage/applicationStorage.ts @@ -165,12 +165,12 @@ export default class { for (const appUserId of appUserIds) { const appUser = await this.dbs.FindOne('ApplicationUser', { where: { identifier: appUserId } }, txId) if (appUser) { - await this.dbs.Delete('ApplicationUser', { serial_id: appUser.serial_id }, txId) + await this.dbs.Delete('ApplicationUser', appUser.serial_id, txId) } } const user = await this.userStorage.FindUser(baseUser, txId) if (!user) return - await this.dbs.Delete('User', { serial_id: user.serial_id }, txId) + await this.dbs.Delete('User', user.serial_id, txId) } diff --git a/src/services/storage/paymentStorage.ts b/src/services/storage/paymentStorage.ts index 16f17f75..092ef8df 100644 --- a/src/services/storage/paymentStorage.ts +++ b/src/services/storage/paymentStorage.ts @@ -144,7 +144,7 @@ export default class { } let deleted = 0 for (const invoice of invoices) { - deleted += await this.dbs.Delete('UserReceivingInvoice', { serial_id: invoice.serial_id }, txId) + deleted += await this.dbs.Delete('UserReceivingInvoice', invoice.serial_id, txId) } return deleted } @@ -336,7 +336,7 @@ export default class { } let deleted = 0 for (const key of keys) { - deleted += await this.dbs.Delete('UserEphemeralKey', { serial_id: key.serial_id }, txId) + deleted += await this.dbs.Delete('UserEphemeralKey', key.serial_id, txId) } return deleted } From 595e5bb2578ecbc0a4048f6c29609cf35c913f8d Mon Sep 17 00:00:00 2001 From: shocknet-justin Date: Mon, 2 Mar 2026 15:16:08 -0500 Subject: [PATCH 43/66] fk fix --- src/services/main/appUserManager.ts | 4 +++ src/services/storage/paymentStorage.ts | 36 ++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/src/services/main/appUserManager.ts b/src/services/main/appUserManager.ts index b87a648d..b9bf8742 100644 --- a/src/services/main/appUserManager.ts +++ b/src/services/main/appUserManager.ts @@ -192,6 +192,10 @@ export default class { await this.storage.paymentStorage.RemoveUserInvoices(userId, tx) await this.storage.productStorage.RemoveUserProducts(userId, tx) await this.storage.paymentStorage.RemoveUserEphemeralKeys(userId, tx) + await this.storage.paymentStorage.RemoveUserInvoicePayments(userId, tx) + await this.storage.paymentStorage.RemoveUserTransactionPayments(userId, tx) + await this.storage.paymentStorage.RemoveUserToUserPayments(userId, tx) + await this.storage.paymentStorage.RemoveUserReceivingAddresses(userId, tx) await this.storage.userStorage.DeleteUserAccess(userId, tx) await this.storage.applicationStorage.RemoveAppUsersAndBaseUsers(appUserIds, userId, tx) }) diff --git a/src/services/storage/paymentStorage.ts b/src/services/storage/paymentStorage.ts index 092ef8df..af96b6c5 100644 --- a/src/services/storage/paymentStorage.ts +++ b/src/services/storage/paymentStorage.ts @@ -341,6 +341,42 @@ export default class { return deleted } + async RemoveUserReceivingAddresses(userId: string, txId?: string) { + const addresses = await this.dbs.Find('UserReceivingAddress', { where: { user: { user_id: userId } } }, txId) + for (const addr of addresses) { + const txs = await this.dbs.Find('AddressReceivingTransaction', { where: { user_address: { serial_id: addr.serial_id } } }, txId) + for (const tx of txs) { + await this.dbs.Delete('AddressReceivingTransaction', tx.serial_id, txId) + } + await this.dbs.Delete('UserReceivingAddress', addr.serial_id, txId) + } + } + + async RemoveUserInvoicePayments(userId: string, txId?: string) { + const payments = await this.dbs.Find('UserInvoicePayment', { where: { user: { user_id: userId } } }, txId) + for (const p of payments) { + await this.dbs.Delete('UserInvoicePayment', p.serial_id, txId) + } + } + + async RemoveUserTransactionPayments(userId: string, txId?: string) { + const payments = await this.dbs.Find('UserTransactionPayment', { where: { user: { user_id: userId } } }, txId) + for (const p of payments) { + await this.dbs.Delete('UserTransactionPayment', p.serial_id, txId) + } + } + + async RemoveUserToUserPayments(userId: string, txId?: string) { + const asSender = await this.dbs.Find('UserToUserPayment', { where: { from_user: { user_id: userId } } }, txId) + const asReceiver = await this.dbs.Find('UserToUserPayment', { where: { to_user: { user_id: userId } } }, txId) + const seen = new Set() + for (const p of [...asSender, ...asReceiver]) { + if (seen.has(p.serial_id)) continue + seen.add(p.serial_id) + await this.dbs.Delete('UserToUserPayment', p.serial_id, txId) + } + } + async AddPendingUserToUserPayment(fromUserId: string, toUserId: string, amount: number, fee: number, linkedApplication: Application, txId: string) { return this.dbs.CreateAndSave('UserToUserPayment', { from_user: await this.userStorage.GetUser(fromUserId, txId), From 7c8cca0a557f69cbcccf96176a580dc611660436 Mon Sep 17 00:00:00 2001 From: boufni95 Date: Tue, 3 Mar 2026 19:49:54 +0000 Subject: [PATCH 44/66] refund failed swaps --- src/services/lnd/swaps/submarineSwaps.ts | 48 ++++++++++++++++++------ src/services/lnd/swaps/swaps.ts | 2 + 2 files changed, 39 insertions(+), 11 deletions(-) diff --git a/src/services/lnd/swaps/submarineSwaps.ts b/src/services/lnd/swaps/submarineSwaps.ts index 462f4751..ffd8a5d5 100644 --- a/src/services/lnd/swaps/submarineSwaps.ts +++ b/src/services/lnd/swaps/submarineSwaps.ts @@ -140,7 +140,9 @@ export class SubmarineSwaps { privateKey: ECPairInterface, refundAddress: string, feePerVbyte: number, - cooperative: boolean = true + cooperative: boolean = true, + allowUncooperativeFallback: boolean = true, + cooperativeErrorMessage?: string ): Promise<{ ok: true, transaction: Transaction, @@ -192,7 +194,11 @@ export class SubmarineSwaps { ) if (!cooperative) { - return { ok: true, transaction: refundTx } + return { + ok: true, + transaction: refundTx, + cooperativeError: cooperativeErrorMessage, + } } // For cooperative refund, get Boltz's partial signature @@ -210,7 +216,11 @@ export class SubmarineSwaps { ) if (!boltzSigRes.ok) { - this.log(ERROR, 'Failed to get Boltz partial signature, falling back to uncooperative refund') + this.log(ERROR, 'Failed to get Boltz partial signature') + if (!allowUncooperativeFallback) { + return { ok: false, error: `Failed to get Boltz partial signature: ${boltzSigRes.error}` } + } + this.log(ERROR, 'Falling back to uncooperative refund') // Fallback to uncooperative refund return await this.constructTaprootRefund( swapId, @@ -221,7 +231,9 @@ export class SubmarineSwaps { privateKey, refundAddress, feePerVbyte, - false + false, + allowUncooperativeFallback, + boltzSigRes.error ) } @@ -253,6 +265,9 @@ export class SubmarineSwaps { return { ok: true, transaction: refundTx } } catch (error: any) { this.log(ERROR, 'Cooperative refund failed:', error.message) + if (!allowUncooperativeFallback) { + return { ok: false, error: `Cooperative refund failed: ${error.message}` } + } // Fallback to uncooperative refund return await this.constructTaprootRefund( swapId, @@ -263,7 +278,9 @@ export class SubmarineSwaps { privateKey, refundAddress, feePerVbyte, - false + false, + allowUncooperativeFallback, + error.message ) } } @@ -304,9 +321,10 @@ export class SubmarineSwaps { refundAddress: string, currentHeight: number, lockupTxHex?: string, - feePerVbyte?: number + feePerVbyte?: number, + allowEarlyRefund?: boolean }): Promise<{ ok: true, publish: { done: false, txHex: string, txId: string } | { done: true, txId: string } } | { ok: false, error: string }> => { - const { swapId, claimPublicKey, swapTree, timeoutBlockHeight, privateKeyHex, refundAddress, currentHeight, lockupTxHex, feePerVbyte = 2 } = params + const { swapId, claimPublicKey, swapTree, timeoutBlockHeight, privateKeyHex, refundAddress, currentHeight, lockupTxHex, feePerVbyte = 2, allowEarlyRefund = false } = params this.log('Starting refund process for swap:', swapId) @@ -325,14 +343,21 @@ export class SubmarineSwaps { } this.log('Lockup transaction retrieved:', lockupTx.getId()) - // Check if swap has timed out - if (currentHeight < timeoutBlockHeight) { + const hasTimedOut = currentHeight >= timeoutBlockHeight + + // For stuck swaps, only allow refund after timeout. For completed (failed) swaps, + // we may attempt a cooperative refund before timeout. + if (!hasTimedOut && !allowEarlyRefund) { return { ok: false, error: `Swap has not timed out yet. Current height: ${currentHeight}, timeout: ${timeoutBlockHeight}` } } - this.log(`Swap has timed out. Current height: ${currentHeight}, timeout: ${timeoutBlockHeight}`) + if (hasTimedOut) { + this.log(`Swap has timed out. Current height: ${currentHeight}, timeout: ${timeoutBlockHeight}`) + } else { + this.log(`Swap has not timed out yet, attempting cooperative refund`) + } // Parse the private key const privateKey = ECPairFactory(ecc).fromPrivateKey(Buffer.from(privateKeyHex, 'hex')) @@ -347,7 +372,8 @@ export class SubmarineSwaps { privateKey, refundAddress, feePerVbyte, - true // Try cooperative first + true, // Try cooperative first + hasTimedOut // only allow uncooperative fallback once timeout has passed ) if (!refundTxRes.ok) { diff --git a/src/services/lnd/swaps/swaps.ts b/src/services/lnd/swaps/swaps.ts index dc1590b4..0aaf9e32 100644 --- a/src/services/lnd/swaps/swaps.ts +++ b/src/services/lnd/swaps/swaps.ts @@ -112,6 +112,7 @@ export class Swaps { if (!swap) { throw new Error("Swap not found or already used") } + const allowEarlyRefund = !!swap.failure_reason const swapper = this.subSwappers[swap.service_url] if (!swapper) { throw new Error("swapper service not found") @@ -124,6 +125,7 @@ export class Swaps { refundAddress, swapTree: swap.swap_tree, timeoutBlockHeight: swap.timeout_block_height, + allowEarlyRefund, feePerVbyte: satPerVByte, lockupTxHex: swap.lockup_tx_hex, }) From 169284021f610339912f484bc400d9ebbf26f087 Mon Sep 17 00:00:00 2001 From: boufni95 Date: Wed, 4 Mar 2026 17:19:42 +0000 Subject: [PATCH 45/66] bump fee api --- proto/autogenerated/client.md | 17 +++++++++++ proto/autogenerated/go/http_client.go | 25 ++++++++++++++++ proto/autogenerated/go/types.go | 5 ++++ proto/autogenerated/ts/express_server.ts | 22 ++++++++++++++ proto/autogenerated/ts/http_client.ts | 11 +++++++ proto/autogenerated/ts/nostr_client.ts | 12 ++++++++ proto/autogenerated/ts/nostr_transport.ts | 16 ++++++++++ proto/autogenerated/ts/types.ts | 36 +++++++++++++++++++++-- proto/service/methods.proto | 9 +++++- proto/service/structs.proto | 7 +++++ src/services/lnd/lnd.ts | 14 +++++++++ src/services/main/adminManager.ts | 4 +++ 12 files changed, 175 insertions(+), 3 deletions(-) diff --git a/proto/autogenerated/client.md b/proto/autogenerated/client.md index eb71d022..d42fc9ac 100644 --- a/proto/autogenerated/client.md +++ b/proto/autogenerated/client.md @@ -58,6 +58,11 @@ The nostr server will send back a message response, and inside the body there wi - This methods has an __empty__ __request__ body - This methods has an __empty__ __response__ body +- BumpTx + - auth type: __Admin__ + - input: [BumpTx](#BumpTx) + - This methods has an __empty__ __response__ body + - CloseChannel - auth type: __Admin__ - input: [CloseChannelRequest](#CloseChannelRequest) @@ -509,6 +514,13 @@ The nostr server will send back a message response, and inside the body there wi - This methods has an __empty__ __request__ body - This methods has an __empty__ __response__ body +- BumpTx + - auth type: __Admin__ + - http method: __post__ + - http route: __/api/admin/tx/bump__ + - input: [BumpTx](#BumpTx) + - This methods has an __empty__ __response__ body + - CloseChannel - auth type: __Admin__ - http method: __post__ @@ -1241,6 +1253,11 @@ The nostr server will send back a message response, and inside the body there wi - __nextRelay__: _string_ *this field is optional - __type__: _string_ +### BumpTx + - __output_index__: _number_ + - __sat_per_vbyte__: _number_ + - __txid__: _string_ + ### BundleData - __available_chunks__: ARRAY of: _number_ - __base_64_data__: ARRAY of: _string_ diff --git a/proto/autogenerated/go/http_client.go b/proto/autogenerated/go/http_client.go index 1d5219a6..43d60ce2 100644 --- a/proto/autogenerated/go/http_client.go +++ b/proto/autogenerated/go/http_client.go @@ -66,6 +66,7 @@ type Client struct { BanDebit func(req DebitOperation) error BanUser func(req BanUserRequest) (*BanUserResponse, error) // batching method: BatchUser not implemented + BumpTx func(req BumpTx) error CloseChannel func(req CloseChannelRequest) (*CloseChannelResponse, error) CreateOneTimeInviteLink func(req CreateOneTimeInviteLinkRequest) (*CreateOneTimeInviteLinkResponse, error) DecodeInvoice func(req DecodeInvoiceRequest) (*DecodeInvoiceResponse, error) @@ -465,6 +466,30 @@ func NewClient(params ClientParams) *Client { return &res, nil }, // batching method: BatchUser not implemented + BumpTx: func(req BumpTx) error { + auth, err := params.RetrieveAdminAuth() + if err != nil { + return err + } + finalRoute := "/api/admin/tx/bump" + body, err := json.Marshal(req) + if err != nil { + return err + } + resBody, err := doPostRequest(params.BaseURL+finalRoute, body, auth) + if err != nil { + return err + } + result := ResultError{} + err = json.Unmarshal(resBody, &result) + if err != nil { + return err + } + if result.Status == "ERROR" { + return fmt.Errorf(result.Reason) + } + return nil + }, CloseChannel: func(req CloseChannelRequest) (*CloseChannelResponse, error) { auth, err := params.RetrieveAdminAuth() if err != nil { diff --git a/proto/autogenerated/go/types.go b/proto/autogenerated/go/types.go index fd20980a..cff46783 100644 --- a/proto/autogenerated/go/types.go +++ b/proto/autogenerated/go/types.go @@ -213,6 +213,11 @@ type BeaconData struct { Nextrelay string `json:"nextRelay"` Type string `json:"type"` } +type BumpTx struct { + Output_index int64 `json:"output_index"` + Sat_per_vbyte int64 `json:"sat_per_vbyte"` + Txid string `json:"txid"` +} type BundleData struct { Available_chunks []int64 `json:"available_chunks"` Base_64_data []string `json:"base_64_data"` diff --git a/proto/autogenerated/ts/express_server.ts b/proto/autogenerated/ts/express_server.ts index c0378ffa..aa809166 100644 --- a/proto/autogenerated/ts/express_server.ts +++ b/proto/autogenerated/ts/express_server.ts @@ -693,6 +693,28 @@ export default (methods: Types.ServerMethods, opts: ServerOptions) => { opts.metricsCallback([{ ...info, ...stats, ...ctx }, ...callsMetrics]) } catch (ex) { const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback); if (opts.throwErrors) throw e } }) + if (!opts.allowNotImplementedMethods && !methods.BumpTx) throw new Error('method: BumpTx is not implemented') + app.post('/api/admin/tx/bump', async (req, res) => { + const info: Types.RequestInfo = { rpcName: 'BumpTx', batch: false, nostr: false, batchSize: 0} + const stats: Types.RequestStats = { startMs:req.startTimeMs || 0, start:req.startTime || 0n, parse: process.hrtime.bigint(), guard: 0n, validate: 0n, handle: 0n } + let authCtx: Types.AuthContext = {} + try { + if (!methods.BumpTx) throw new Error('method: BumpTx is not implemented') + const authContext = await opts.AdminAuthGuard(req.headers['authorization']) + authCtx = authContext + stats.guard = process.hrtime.bigint() + const request = req.body + const error = Types.BumpTxValidate(request) + stats.validate = process.hrtime.bigint() + if (error !== null) return logErrorAndReturnResponse(error, 'invalid request body', res, logger, { ...info, ...stats, ...authContext }, opts.metricsCallback) + const query = req.query + const params = req.params + await methods.BumpTx({rpcName:'BumpTx', ctx:authContext , req: request}) + stats.handle = process.hrtime.bigint() + res.json({status: 'OK'}) + opts.metricsCallback([{ ...info, ...stats, ...authContext }]) + } catch (ex) { const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback); if (opts.throwErrors) throw e } + }) if (!opts.allowNotImplementedMethods && !methods.CloseChannel) throw new Error('method: CloseChannel is not implemented') app.post('/api/admin/channel/close', async (req, res) => { const info: Types.RequestInfo = { rpcName: 'CloseChannel', batch: false, nostr: false, batchSize: 0} diff --git a/proto/autogenerated/ts/http_client.ts b/proto/autogenerated/ts/http_client.ts index ed68348f..21597e2c 100644 --- a/proto/autogenerated/ts/http_client.ts +++ b/proto/autogenerated/ts/http_client.ts @@ -176,6 +176,17 @@ export default (params: ClientParams) => ({ } return { status: 'ERROR', reason: 'invalid response' } }, + BumpTx: async (request: Types.BumpTx): Promise => { + const auth = await params.retrieveAdminAuth() + if (auth === null) throw new Error('retrieveAdminAuth() returned null') + let finalRoute = '/api/admin/tx/bump' + const { data } = await axios.post(params.baseUrl + finalRoute, request, { headers: { 'authorization': auth } }) + if (data.status === 'ERROR' && typeof data.reason === 'string') return data + if (data.status === 'OK') { + return data + } + return { status: 'ERROR', reason: 'invalid response' } + }, CloseChannel: async (request: Types.CloseChannelRequest): Promise => { const auth = await params.retrieveAdminAuth() if (auth === null) throw new Error('retrieveAdminAuth() returned null') diff --git a/proto/autogenerated/ts/nostr_client.ts b/proto/autogenerated/ts/nostr_client.ts index b00e8f1a..64e517e6 100644 --- a/proto/autogenerated/ts/nostr_client.ts +++ b/proto/autogenerated/ts/nostr_client.ts @@ -137,6 +137,18 @@ export default (params: NostrClientParams, send: (to:string, message: NostrRequ } return { status: 'ERROR', reason: 'invalid response' } }, + BumpTx: async (request: Types.BumpTx): Promise => { + const auth = await params.retrieveNostrAdminAuth() + if (auth === null) throw new Error('retrieveNostrAdminAuth() returned null') + const nostrRequest: NostrRequest = {} + nostrRequest.body = request + const data = await send(params.pubDestination, {rpcName:'BumpTx',authIdentifier:auth, ...nostrRequest }) + if (data.status === 'ERROR' && typeof data.reason === 'string') return data + if (data.status === 'OK') { + return data + } + return { status: 'ERROR', reason: 'invalid response' } + }, CloseChannel: async (request: Types.CloseChannelRequest): Promise => { const auth = await params.retrieveNostrAdminAuth() if (auth === null) throw new Error('retrieveNostrAdminAuth() returned null') diff --git a/proto/autogenerated/ts/nostr_transport.ts b/proto/autogenerated/ts/nostr_transport.ts index c58b3283..80284e10 100644 --- a/proto/autogenerated/ts/nostr_transport.ts +++ b/proto/autogenerated/ts/nostr_transport.ts @@ -575,6 +575,22 @@ export default (methods: Types.ServerMethods, opts: NostrOptions) => { opts.metricsCallback([{ ...info, ...stats, ...ctx }, ...callsMetrics]) }catch(ex){ const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback); if (opts.throwErrors) throw e } break + case 'BumpTx': + try { + if (!methods.BumpTx) throw new Error('method: BumpTx is not implemented') + const authContext = await opts.NostrAdminAuthGuard(req.appId, req.authIdentifier) + stats.guard = process.hrtime.bigint() + authCtx = authContext + const request = req.body + const error = Types.BumpTxValidate(request) + stats.validate = process.hrtime.bigint() + if (error !== null) return logErrorAndReturnResponse(error, 'invalid request body', res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback) + await methods.BumpTx({rpcName:'BumpTx', ctx:authContext , req: request}) + stats.handle = process.hrtime.bigint() + res({status: 'OK'}) + opts.metricsCallback([{ ...info, ...stats, ...authContext }]) + }catch(ex){ const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback); if (opts.throwErrors) throw e } + break case 'CloseChannel': try { if (!methods.CloseChannel) throw new Error('method: CloseChannel is not implemented') diff --git a/proto/autogenerated/ts/types.ts b/proto/autogenerated/ts/types.ts index 1980e49b..90cd1724 100644 --- a/proto/autogenerated/ts/types.ts +++ b/proto/autogenerated/ts/types.ts @@ -7,8 +7,8 @@ export type RequestMetric = AuthContext & RequestInfo & RequestStats & { error?: export type AdminContext = { admin_id: string } -export type AdminMethodInputs = AddApp_Input | AddPeer_Input | AuthApp_Input | BanUser_Input | CloseChannel_Input | CreateOneTimeInviteLink_Input | GetAdminInvoiceSwapQuotes_Input | GetAdminTransactionSwapQuotes_Input | GetAssetsAndLiabilities_Input | GetInviteLinkState_Input | GetSeed_Input | ListAdminInvoiceSwaps_Input | ListAdminTxSwaps_Input | ListChannels_Input | LndGetInfo_Input | OpenChannel_Input | PayAdminInvoiceSwap_Input | PayAdminTransactionSwap_Input | RefundAdminInvoiceSwap_Input | UpdateChannelPolicy_Input -export type AdminMethodOutputs = AddApp_Output | AddPeer_Output | AuthApp_Output | BanUser_Output | CloseChannel_Output | CreateOneTimeInviteLink_Output | GetAdminInvoiceSwapQuotes_Output | GetAdminTransactionSwapQuotes_Output | GetAssetsAndLiabilities_Output | GetInviteLinkState_Output | GetSeed_Output | ListAdminInvoiceSwaps_Output | ListAdminTxSwaps_Output | ListChannels_Output | LndGetInfo_Output | OpenChannel_Output | PayAdminInvoiceSwap_Output | PayAdminTransactionSwap_Output | RefundAdminInvoiceSwap_Output | UpdateChannelPolicy_Output +export type AdminMethodInputs = AddApp_Input | AddPeer_Input | AuthApp_Input | BanUser_Input | BumpTx_Input | CloseChannel_Input | CreateOneTimeInviteLink_Input | GetAdminInvoiceSwapQuotes_Input | GetAdminTransactionSwapQuotes_Input | GetAssetsAndLiabilities_Input | GetInviteLinkState_Input | GetSeed_Input | ListAdminInvoiceSwaps_Input | ListAdminTxSwaps_Input | ListChannels_Input | LndGetInfo_Input | OpenChannel_Input | PayAdminInvoiceSwap_Input | PayAdminTransactionSwap_Input | RefundAdminInvoiceSwap_Input | UpdateChannelPolicy_Input +export type AdminMethodOutputs = AddApp_Output | AddPeer_Output | AuthApp_Output | BanUser_Output | BumpTx_Output | CloseChannel_Output | CreateOneTimeInviteLink_Output | GetAdminInvoiceSwapQuotes_Output | GetAdminTransactionSwapQuotes_Output | GetAssetsAndLiabilities_Output | GetInviteLinkState_Output | GetSeed_Output | ListAdminInvoiceSwaps_Output | ListAdminTxSwaps_Output | ListChannels_Output | LndGetInfo_Output | OpenChannel_Output | PayAdminInvoiceSwap_Output | PayAdminTransactionSwap_Output | RefundAdminInvoiceSwap_Output | UpdateChannelPolicy_Output export type AppContext = { app_id: string } @@ -75,6 +75,9 @@ export type BanUser_Output = ResultError | ({ status: 'OK' } & BanUserResponse) export type BatchUser_Input = UserMethodInputs export type BatchUser_Output = UserMethodOutputs +export type BumpTx_Input = {rpcName:'BumpTx', req: BumpTx} +export type BumpTx_Output = ResultError | { status: 'OK' } + export type CloseChannel_Input = {rpcName:'CloseChannel', req: CloseChannelRequest} export type CloseChannel_Output = ResultError | ({ status: 'OK' } & CloseChannelResponse) @@ -364,6 +367,7 @@ export type ServerMethods = { AuthorizeManage?: (req: AuthorizeManage_Input & {ctx: UserContext }) => Promise BanDebit?: (req: BanDebit_Input & {ctx: UserContext }) => Promise BanUser?: (req: BanUser_Input & {ctx: AdminContext }) => Promise + BumpTx?: (req: BumpTx_Input & {ctx: AdminContext }) => Promise CloseChannel?: (req: CloseChannel_Input & {ctx: AdminContext }) => Promise CreateOneTimeInviteLink?: (req: CreateOneTimeInviteLink_Input & {ctx: AdminContext }) => Promise DecodeInvoice?: (req: DecodeInvoice_Input & {ctx: UserContext }) => Promise @@ -1209,6 +1213,34 @@ export const BeaconDataValidate = (o?: BeaconData, opts: BeaconDataOptions = {}, return null } +export type BumpTx = { + output_index: number + sat_per_vbyte: number + txid: string +} +export const BumpTxOptionalFields: [] = [] +export type BumpTxOptions = OptionsBaseMessage & { + checkOptionalsAreSet?: [] + output_index_CustomCheck?: (v: number) => boolean + sat_per_vbyte_CustomCheck?: (v: number) => boolean + txid_CustomCheck?: (v: string) => boolean +} +export const BumpTxValidate = (o?: BumpTx, opts: BumpTxOptions = {}, path: string = 'BumpTx::root.'): Error | null => { + if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message') + if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null') + + if (typeof o.output_index !== 'number') return new Error(`${path}.output_index: is not a number`) + if (opts.output_index_CustomCheck && !opts.output_index_CustomCheck(o.output_index)) return new Error(`${path}.output_index: custom check failed`) + + if (typeof o.sat_per_vbyte !== 'number') return new Error(`${path}.sat_per_vbyte: is not a number`) + if (opts.sat_per_vbyte_CustomCheck && !opts.sat_per_vbyte_CustomCheck(o.sat_per_vbyte)) return new Error(`${path}.sat_per_vbyte: custom check failed`) + + if (typeof o.txid !== 'string') return new Error(`${path}.txid: is not a string`) + if (opts.txid_CustomCheck && !opts.txid_CustomCheck(o.txid)) return new Error(`${path}.txid: custom check failed`) + + return null +} + export type BundleData = { available_chunks: number[] base_64_data: string[] diff --git a/proto/service/methods.proto b/proto/service/methods.proto index d7f97860..2a54767b 100644 --- a/proto/service/methods.proto +++ b/proto/service/methods.proto @@ -117,7 +117,14 @@ service LightningPub { option (http_method) = "post"; option (http_route) = "/api/admin/assets/liabilities"; option (nostr) = true; - } + }; + + rpc BumpTx(structs.BumpTx) returns (structs.Empty) { + option (auth_type) = "Admin"; + option (http_method) = "post"; + option (http_route) = "/api/admin/tx/bump"; + option (nostr) = true; + }; rpc AddApp(structs.AddAppRequest) returns (structs.AuthApp) { option (auth_type) = "Admin"; diff --git a/proto/service/structs.proto b/proto/service/structs.proto index 8e91d9c4..3d64ef67 100644 --- a/proto/service/structs.proto +++ b/proto/service/structs.proto @@ -25,6 +25,13 @@ message AssetsAndLiabilitiesReq { optional int64 limit_providers = 4; } +message BumpTx { + string txid = 1; + int64 output_index = 2; + int64 sat_per_vbyte = 3; +} + + enum TrackedOperationType { USER = 0; ROOT = 1; diff --git a/src/services/lnd/lnd.ts b/src/services/lnd/lnd.ts index 673ff073..eba48f6d 100644 --- a/src/services/lnd/lnd.ts +++ b/src/services/lnd/lnd.ts @@ -642,6 +642,20 @@ export default class { return res.response } + async BumpFee(txId: string, outputIndex: number, satPerVbyte: number) { + this.log(DEBUG, "Bumping fee") + const res = await this.walletKit.bumpFee({ + budget: 0n, immediate: false, targetConf: 0, satPerVbyte: BigInt(satPerVbyte), outpoint: { + txidStr: txId, + outputIndex: outputIndex, + txidBytes: Buffer.alloc(0) + }, + force: false, + satPerByte: 0 + }, DeadLineMetadata()) + return res.response + } + async GetPayment(paymentIndex: number) { this.log(DEBUG, "Getting payment") if (paymentIndex === 0) { diff --git a/src/services/main/adminManager.ts b/src/services/main/adminManager.ts index e0639547..dbde290d 100644 --- a/src/services/main/adminManager.ts +++ b/src/services/main/adminManager.ts @@ -588,6 +588,10 @@ export class AdminManager { return { ts, amount, tracked: undefined } } + async BumpTx(req: Types.BumpTx): Promise { + await this.lnd.BumpFee(req.txid, req.output_index, req.sat_per_vbyte) + } + } const getDataPath = (dataDir: string, dataPath: string) => { From 74513a14122e71830bca7a7e1d2f80fd96ae0153 Mon Sep 17 00:00:00 2001 From: boufni95 Date: Wed, 4 Mar 2026 17:57:50 +0000 Subject: [PATCH 46/66] bimp fee --- src/services/serverMethods/index.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/services/serverMethods/index.ts b/src/services/serverMethods/index.ts index 483ef0d7..d74e67fd 100644 --- a/src/services/serverMethods/index.ts +++ b/src/services/serverMethods/index.ts @@ -91,6 +91,14 @@ export default (mainHandler: Main): Types.ServerMethods => { if (err != null) throw new Error(err.message) return mainHandler.adminManager.CloseChannel(req) }, + BumpTx: async ({ ctx, req }) => { + const err = Types.BumpTxValidate(req, { + txid_CustomCheck: txid => txid !== '', + sat_per_vbyte_CustomCheck: spv => spv > 0 + }) + if (err != null) throw new Error(err.message) + return mainHandler.adminManager.BumpTx(req) + }, GetAdminTransactionSwapQuotes: async ({ ctx, req }) => { const err = Types.TransactionSwapRequestValidate(req, { transaction_amount_sats_CustomCheck: amt => amt > 0 From 70544bd5514d9565037cc10f51e5d0d2543303cc Mon Sep 17 00:00:00 2001 From: boufni95 Date: Wed, 4 Mar 2026 18:26:21 +0000 Subject: [PATCH 47/66] rate fix --- src/services/lnd/swaps/submarineSwaps.ts | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/services/lnd/swaps/submarineSwaps.ts b/src/services/lnd/swaps/submarineSwaps.ts index ffd8a5d5..6e4beba8 100644 --- a/src/services/lnd/swaps/submarineSwaps.ts +++ b/src/services/lnd/swaps/submarineSwaps.ts @@ -3,7 +3,7 @@ const zkpInit = (secp256k1ZkpModule as any).default || secp256k1ZkpModule; // import bolt11 from 'bolt11'; import { Musig, SwapTreeSerializer, TaprootUtils, constructRefundTransaction, - detectSwap, OutputType + detectSwap, OutputType, targetFee } from 'boltz-core'; import { randomBytes, createHash } from 'crypto'; import { ECPairFactory, ECPairInterface } from 'ecpair'; @@ -184,13 +184,16 @@ export class SubmarineSwaps { } ] const outputScript = address.toOutputScript(refundAddress, network) - // Construct the refund transaction - const refundTx = constructRefundTransaction( - details, - outputScript, - cooperative ? 0 : timeoutBlockHeight, + // Construct the refund transaction: targetFee converts sat/vbyte rate to flat fee + const refundTx = targetFee( feePerVbyte, - true + (fee) => constructRefundTransaction( + details, + outputScript, + cooperative ? 0 : timeoutBlockHeight, + fee, + true + ) ) if (!cooperative) { From e9b5dacb3b1b4a41fc40f9873edea9bfcada4430 Mon Sep 17 00:00:00 2001 From: Patrick Mulligan Date: Sun, 25 Jan 2026 14:37:56 -0500 Subject: [PATCH 48/66] fix(nostr): update NostrSend type to Promise with error handling The NostrSend type was incorrectly typed as returning void when it actually returns Promise. This caused async errors to be silently swallowed. Changes: - Update NostrSend type signature to return Promise - Make NostrSender._nostrSend default to async function - Add .catch() error handling in NostrSender.Send() to log failures - Add logging to track event publishing status Co-Authored-By: Claude Opus 4.5 --- src/services/nostr/nostrPool.ts | 9 +++++---- src/services/nostr/sender.ts | 18 +++++++++++++----- 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/src/services/nostr/nostrPool.ts b/src/services/nostr/nostrPool.ts index d41da382..d5e47d7f 100644 --- a/src/services/nostr/nostrPool.ts +++ b/src/services/nostr/nostrPool.ts @@ -16,7 +16,7 @@ export type SendDataContent = { type: "content", content: string, pub: string } export type SendDataEvent = { type: "event", event: UnsignedEvent, encrypt?: { toPub: string } } export type SendData = SendDataContent | SendDataEvent export type SendInitiator = { type: 'app', appId: string } | { type: 'client', clientId: string } -export type NostrSend = (initiator: SendInitiator, data: SendData, relays?: string[] | undefined) => void +export type NostrSend = (initiator: SendInitiator, data: SendData, relays?: string[] | undefined) => Promise export type LinkedProviderInfo = { pubkey: string, clientId: string, relayUrl: string } export type AppInfo = { appId: string, publicKey: string, privateKey: string, name: string, provider?: LinkedProviderInfo } @@ -203,21 +203,22 @@ export class NostrPool { const signed = finalizeEvent(event, Buffer.from(keys.privateKey, 'hex')) let sent = false const log = getLogger({ appName: keys.name }) - // const r = relays ? relays : this.getServiceRelays() + this.log(`📤 Publishing Kind ${event.kind} event to ${relays.length} relay(s): ${relays.join(', ')}`) const pool = new SimplePool() await Promise.all(pool.publish(relays, signed).map(async p => { try { await p sent = true } catch (e: any) { - console.log(e) + this.log(ERROR, `Failed to publish Kind ${event.kind} event:`, e.message || e) log(e) } })) if (!sent) { + this.log(ERROR, `Failed to send Kind ${event.kind} event to any relay`) log("failed to send event") } else { - //log("sent event") + this.log(`✅ Kind ${event.kind} event published successfully (id: ${signed.id.slice(0, 16)}...)`) } } diff --git a/src/services/nostr/sender.ts b/src/services/nostr/sender.ts index 1fd336a5..8437b9af 100644 --- a/src/services/nostr/sender.ts +++ b/src/services/nostr/sender.ts @@ -1,7 +1,7 @@ import { NostrSend, SendData, SendInitiator } from "./nostrPool.js" -import { getLogger } from "../helpers/logger.js" +import { ERROR, getLogger } from "../helpers/logger.js" export class NostrSender { - private _nostrSend: NostrSend = () => { throw new Error('nostr send not initialized yet') } + private _nostrSend: NostrSend = async () => { throw new Error('nostr send not initialized yet') } private isReady: boolean = false private onReadyCallbacks: (() => void)[] = [] private pendingSends: { initiator: SendInitiator, data: SendData, relays?: string[] | undefined }[] = [] @@ -12,7 +12,12 @@ export class NostrSender { this.isReady = true this.onReadyCallbacks.forEach(cb => cb()) this.onReadyCallbacks = [] - this.pendingSends.forEach(send => this._nostrSend(send.initiator, send.data, send.relays)) + // Process pending sends with proper error handling + this.pendingSends.forEach(send => { + this._nostrSend(send.initiator, send.data, send.relays).catch(e => { + this.log(ERROR, "failed to send pending event", e.message || e) + }) + }) this.pendingSends = [] } OnReady(callback: () => void) { @@ -22,13 +27,16 @@ export class NostrSender { this.onReadyCallbacks.push(callback) } } - Send(initiator: SendInitiator, data: SendData, relays?: string[] | undefined) { + Send(initiator: SendInitiator, data: SendData, relays?: string[] | undefined): void { if (!this.isReady) { this.log("tried to send before nostr was ready, caching request") this.pendingSends.push({ initiator, data, relays }) return } - this._nostrSend(initiator, data, relays) + // Fire and forget but log errors + this._nostrSend(initiator, data, relays).catch(e => { + this.log(ERROR, "failed to send event", e.message || e) + }) } IsReady() { return this.isReady From 6512e10f08915eec27dbfd2703195e2208b18725 Mon Sep 17 00:00:00 2001 From: Patrick Mulligan Date: Sun, 25 Jan 2026 14:38:24 -0500 Subject: [PATCH 49/66] fix(handlers): await NostrSend calls throughout codebase Update all NostrSend call sites to properly handle the async nature of the function now that it returns Promise. Changes: - handler.ts: Add async to sendResponse, await nostrSend calls - debitManager.ts: Add logging for Kind 21002 response sending - nostrMiddleware.ts: Update nostrSend signature - tlvFilesStorageProcessor.ts: Update nostrSend signature - webRTC/index.ts: Add async/await for nostrSend calls This ensures Kind 21002 (ndebit) responses are properly sent to wallet clients, fixing the "Debit request failed" issue in ShockWallet. Co-Authored-By: Claude Opus 4.5 --- src/nostrMiddleware.ts | 2 +- src/services/main/debitManager.ts | 3 ++- src/services/nostr/handler.ts | 4 ++-- src/services/storage/tlv/tlvFilesStorageProcessor.ts | 2 +- src/services/webRTC/index.ts | 4 ++-- 5 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/nostrMiddleware.ts b/src/nostrMiddleware.ts index 034dbce8..4dd3b281 100644 --- a/src/nostrMiddleware.ts +++ b/src/nostrMiddleware.ts @@ -105,7 +105,7 @@ export default (serverMethods: Types.ServerMethods, mainHandler: Main, nostrSett return { Stop: () => { mainHandler.adminManager.setNostrConnected(false); return nostr.Stop }, - Send: (...args) => nostr.Send(...args), + Send: async (...args) => nostr.Send(...args), Ping: () => nostr.Ping(), Reset: (settings: NostrSettings) => nostr.Reset(settings) } diff --git a/src/services/main/debitManager.ts b/src/services/main/debitManager.ts index 28579d31..53375217 100644 --- a/src/services/main/debitManager.ts +++ b/src/services/main/debitManager.ts @@ -153,13 +153,14 @@ export class DebitManager { } notifyPaymentSuccess = (debitRes: NdebitSuccess, event: { pub: string, id: string, appId: string }) => { + this.logger("✅ [DEBIT REQUEST] Payment successful, sending OK response to", event.pub.slice(0, 16) + "...", "for event", event.id.slice(0, 16) + "...") this.sendDebitResponse(debitRes, event) } sendDebitResponse = (debitRes: NdebitFailure | NdebitSuccess, event: { pub: string, id: string, appId: string }) => { + this.logger("📤 [DEBIT RESPONSE] Sending Kind 21002 response:", JSON.stringify(debitRes), "to", event.pub.slice(0, 16) + "...") const e = newNdebitResponse(JSON.stringify(debitRes), event) this.storage.NostrSender().Send({ type: 'app', appId: event.appId }, { type: 'event', event: e, encrypt: { toPub: event.pub } }) - } payNdebitInvoice = async (event: NostrEvent, pointerdata: NdebitData): Promise => { diff --git a/src/services/nostr/handler.ts b/src/services/nostr/handler.ts index d1fa46ec..b9ecfe70 100644 --- a/src/services/nostr/handler.ts +++ b/src/services/nostr/handler.ts @@ -132,12 +132,12 @@ const handleNostrSettings = (settings: NostrSettings) => { send(event) }) } */ -const sendToNostr: NostrSend = (initiator, data, relays) => { +const sendToNostr: NostrSend = async (initiator, data, relays) => { if (!subProcessHandler) { getLogger({ component: "nostrMiddleware" })(ERROR, "nostr was not initialized") return } - subProcessHandler.Send(initiator, data, relays) + await subProcessHandler.Send(initiator, data, relays) } send({ type: 'ready' }) diff --git a/src/services/storage/tlv/tlvFilesStorageProcessor.ts b/src/services/storage/tlv/tlvFilesStorageProcessor.ts index 2b4189e4..caccb949 100644 --- a/src/services/storage/tlv/tlvFilesStorageProcessor.ts +++ b/src/services/storage/tlv/tlvFilesStorageProcessor.ts @@ -126,7 +126,7 @@ class TlvFilesStorageProcessor { throw new Error('Unknown metric type: ' + t) } }) - this.wrtc.attachNostrSend((initiator: SendInitiator, data: SendData, relays?: string[] | undefined) => { + this.wrtc.attachNostrSend(async (initiator: SendInitiator, data: SendData, relays?: string[] | undefined) => { this.sendResponse({ success: true, type: 'nostrSend', diff --git a/src/services/webRTC/index.ts b/src/services/webRTC/index.ts index 8ee8d884..a2cc90af 100644 --- a/src/services/webRTC/index.ts +++ b/src/services/webRTC/index.ts @@ -27,11 +27,11 @@ export default class webRTC { attachNostrSend(f: NostrSend) { this._nostrSend = f } - private nostrSend: NostrSend = (initiator: SendInitiator, data: SendData, relays?: string[] | undefined) => { + private nostrSend: NostrSend = async (initiator: SendInitiator, data: SendData, relays?: string[] | undefined) => { if (!this._nostrSend) { throw new Error("No nostrSend attached") } - this._nostrSend(initiator, data, relays) + await this._nostrSend(initiator, data, relays) } private sendCandidate = (u: WebRtcUserInfo, candidate: string) => { From 611eb4fc04726be8dd8c4e2f32a542ebfe800f12 Mon Sep 17 00:00:00 2001 From: Patrick Mulligan Date: Sat, 28 Feb 2026 07:53:09 -0500 Subject: [PATCH 50/66] fix(nostr): close SimplePool after publishing to prevent connection leak Each sendEvent() call created a new SimplePool() but never closed it, causing relay WebSocket connections to accumulate indefinitely (~20/min). Co-Authored-By: Claude Opus 4.6 --- src/services/nostr/nostrPool.ts | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/src/services/nostr/nostrPool.ts b/src/services/nostr/nostrPool.ts index d5e47d7f..ee610a35 100644 --- a/src/services/nostr/nostrPool.ts +++ b/src/services/nostr/nostrPool.ts @@ -205,20 +205,24 @@ export class NostrPool { const log = getLogger({ appName: keys.name }) this.log(`📤 Publishing Kind ${event.kind} event to ${relays.length} relay(s): ${relays.join(', ')}`) const pool = new SimplePool() - await Promise.all(pool.publish(relays, signed).map(async p => { - try { - await p - sent = true - } catch (e: any) { - this.log(ERROR, `Failed to publish Kind ${event.kind} event:`, e.message || e) - log(e) + try { + await Promise.all(pool.publish(relays, signed).map(async p => { + try { + await p + sent = true + } catch (e: any) { + this.log(ERROR, `Failed to publish Kind ${event.kind} event:`, e.message || e) + log(e) + } + })) + if (!sent) { + this.log(ERROR, `Failed to send Kind ${event.kind} event to any relay`) + log("failed to send event") + } else { + this.log(`✅ Kind ${event.kind} event published successfully (id: ${signed.id.slice(0, 16)}...)`) } - })) - if (!sent) { - this.log(ERROR, `Failed to send Kind ${event.kind} event to any relay`) - log("failed to send event") - } else { - this.log(`✅ Kind ${event.kind} event published successfully (id: ${signed.id.slice(0, 16)}...)`) + } finally { + pool.close(relays) } } From 5e5e30c7a2e48fd1107b52d5814c784457e30d3d Mon Sep 17 00:00:00 2001 From: Patrick Mulligan Date: Sun, 1 Mar 2026 17:12:20 -0500 Subject: [PATCH 51/66] fix(lnd): wait for chain/graph sync before marking LND ready Warmup() previously only checked that LND responded to GetInfo(), but did not verify syncedToChain/syncedToGraph. This caused LP to accept requests while LND was still syncing, leading to "not synced" errors on every Health() check. Now waits for full sync with a 10min timeout. Co-Authored-By: Claude Opus 4.6 --- src/services/lnd/lnd.ts | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/services/lnd/lnd.ts b/src/services/lnd/lnd.ts index eba48f6d..8ccc42ee 100644 --- a/src/services/lnd/lnd.ts +++ b/src/services/lnd/lnd.ts @@ -142,15 +142,20 @@ export default class { return new Promise((res, rej) => { const interval = setInterval(async () => { try { - await this.GetInfo() + const info = await this.GetInfo() + if (!info.syncedToChain || !info.syncedToGraph) { + this.log("LND responding but not synced yet, waiting...") + return + } clearInterval(interval) this.ready = true res() } catch (err) { this.log(INFO, "LND is not ready yet, will try again in 1 second") - if (Date.now() - now > 1000 * 60) { - rej(new Error("LND not ready after 1 minute")) - } + } + if (Date.now() - now > 1000 * 60 * 10) { + clearInterval(interval) + rej(new Error("LND not synced after 10 minutes")) } }, 1000) }) From 72c9872b23e418e28df55838d92df580982183a7 Mon Sep 17 00:00:00 2001 From: Patrick Mulligan Date: Wed, 4 Mar 2026 12:23:14 -0500 Subject: [PATCH 52/66] fix(watchdog): handle LND restarts without locking outgoing operations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When the payment index advances (e.g. after an LND restart or external payment), update the cached offset instead of immediately locking. Only lock if both a history mismatch AND a balance discrepancy are detected — indicating a real security concern rather than a benign LND restart. Co-Authored-By: Claude Opus 4.6 --- src/services/main/watchdog.ts | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/services/main/watchdog.ts b/src/services/main/watchdog.ts index d9d585ba..3c12b676 100644 --- a/src/services/main/watchdog.ts +++ b/src/services/main/watchdog.ts @@ -238,13 +238,17 @@ export class Watchdog { const knownMaxIndex = Math.max(maxFromDb, this.latestPaymentIndexOffset) const newLatest = await this.lnd.GetLatestPaymentIndex(knownMaxIndex) const historyMismatch = newLatest > knownMaxIndex - const deny = await this.checkBalanceUpdate(deltaLnd, deltaUsers) if (historyMismatch) { - getLogger({ component: 'bark' })("History mismatch detected in absolute update, locking outgoing operations") - this.lnd.LockOutgoingOperations() - return + this.log("Payment index advanced from", knownMaxIndex, "to", newLatest, "- updating offset (likely LND restart or external payment)") + this.latestPaymentIndexOffset = newLatest } + const deny = await this.checkBalanceUpdate(deltaLnd, deltaUsers) if (deny) { + if (historyMismatch) { + getLogger({ component: 'bark' })("Balance mismatch with unexpected payment history, locking outgoing operations") + this.lnd.LockOutgoingOperations() + return + } this.log("Balance mismatch detected in absolute update, but history is ok") } this.lnd.UnlockOutgoingOperations() From 77e5772afd086eacd63a3dbb332fb2d5aaf81d80 Mon Sep 17 00:00:00 2001 From: padreug Date: Thu, 2 Apr 2026 18:47:55 +0000 Subject: [PATCH 53/66] feat(extensions): add extension loader infrastructure (#3) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary - Adds a modular extension system for Lightning.Pub enabling third-party plugins - Provides isolated SQLite databases per extension for data safety - Implements ExtensionContext API for accessing Lightning.Pub services (payments, Nostr, storage) - Supports RPC method registration with automatic namespacing - Includes HTTP route handling for protocols like LNURL - Event routing for payment receipts and Nostr events - Comprehensive documentation with architecture overview and working examples ## Key Components - `src/extensions/types.ts` - Core extension interfaces - `src/extensions/loader.ts` - Extension discovery, loading, and lifecycle management - `src/extensions/context.ts` - Bridge between extensions and Lightning.Pub services - `src/extensions/database.ts` - SQLite isolation with WAL mode - `src/extensions/README.md` - Full documentation with examples ## ExtensionContext API | Method | Description | |--------|-------------| | `getApplication()` | Get application info | | `createInvoice()` | Create Lightning invoice | | `payInvoice()` | Pay Lightning invoice | | `getLnurlPayInfo()` | Get LNURL-pay info for a user (enables Lightning Address/zaps) | | `sendEncryptedDM()` | Send Nostr DM (NIP-44) | | `publishNostrEvent()` | Publish Nostr event | | `registerMethod()` | Register RPC method | | `onPaymentReceived()` | Subscribe to payment callbacks | | `onNostrEvent()` | Subscribe to Nostr events | ## Test plan - [x] Review extension loader code for correctness - [x] Verify TypeScript compilation succeeds - [x] Test extension discovery from `src/extensions/` directory - [x] Test RPC method registration and routing - [x] Test database isolation between extensions 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: boufni95 Co-authored-by: Patrick Mulligan Reviewed-on: https://git.atitlan.io/aiolabs/lightning-pub/pulls/3 --- .dockerignore | 18 + Dockerfile | 2 +- datasource.js | 6 +- package-lock.json | 2926 ++++------ package.json | 3 +- proto/autogenerated/client.md | 3 + proto/autogenerated/go/types.go | 3 + proto/autogenerated/ts/types.ts | 19 +- proto/lnd/chainnotifier.client.ts | 14 +- proto/lnd/chainnotifier.ts | 119 +- proto/lnd/invoices.client.ts | 98 +- proto/lnd/invoices.ts | 445 +- proto/lnd/lightning.client.ts | 322 +- proto/lnd/lightning.ts | 4814 +++++++++++------ proto/lnd/router.client.ts | 228 +- proto/lnd/router.ts | 1690 ++++-- proto/lnd/signer.client.ts | 46 +- proto/lnd/signer.ts | 339 +- proto/lnd/walletkit.client.ts | 116 +- proto/lnd/walletkit.ts | 831 +-- proto/lnd/walletunlocker.client.ts | 18 +- proto/lnd/walletunlocker.ts | 140 +- proto/others/invoices.proto | 94 +- proto/others/lightning.proto | 205 +- proto/others/router.proto | 383 +- proto/others/walletkit.proto | 36 +- proto/service/structs.proto | 4 + src/extensions/README.md | 731 +++ src/extensions/context.ts | 309 ++ src/extensions/database.ts | 148 + src/extensions/index.ts | 56 + src/extensions/loader.ts | 406 ++ src/extensions/types.ts | 285 + src/services/lnd/lnd.ts | 10 +- src/services/lnd/payInvoiceReq.ts | 4 +- src/services/lnd/swaps/swaps.ts | 6 +- src/services/main/appUserManager.ts | 11 +- src/services/main/applicationManager.ts | 4 +- src/services/main/index.ts | 6 +- src/services/main/paymentManager.ts | 4 +- src/services/metrics/index.ts | 63 +- src/services/nostr/nip44v1.ts | 6 +- src/services/storage/db/transactionsQueue.ts | 2 +- src/services/storage/entity/InvoiceSwap.ts | 10 +- .../1773082318982-refund_swap_info.ts | 20 + src/services/storage/migrations/runner.ts | 3 +- src/services/storage/paymentStorage.ts | 9 + 47 files changed, 10187 insertions(+), 4828 deletions(-) create mode 100644 src/extensions/README.md create mode 100644 src/extensions/context.ts create mode 100644 src/extensions/database.ts create mode 100644 src/extensions/index.ts create mode 100644 src/extensions/loader.ts create mode 100644 src/extensions/types.ts create mode 100644 src/services/storage/migrations/1773082318982-refund_swap_info.ts diff --git a/.dockerignore b/.dockerignore index 7fab354e..135641f4 100644 --- a/.dockerignore +++ b/.dockerignore @@ -2,3 +2,21 @@ .github build node_modules + +# Runtime state files (should not be baked into image) +*.sqlite +*.sqlite-journal +*.sqlite-wal +*.sqlite-shm +*.db +admin.connect +admin.enroll +admin.npub +app.nprofile +.jwt_secret + +# Runtime data directories +metric_cache/ +metric_events/ +bundler_events/ +logs/ diff --git a/Dockerfile b/Dockerfile index 6001419a..1d3df65b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM node:18 +FROM node:20 WORKDIR /app diff --git a/datasource.js b/datasource.js index 4badca25..924e667c 100644 --- a/datasource.js +++ b/datasource.js @@ -66,6 +66,7 @@ import { InvoiceSwaps1769529793283 } from './build/src/services/storage/migratio import { InvoiceSwapsFixes1769805357459 } from './build/src/services/storage/migrations/1769805357459-invoice_swaps_fixes.js' import { ApplicationUserTopicId1770038768784 } from './build/src/services/storage/migrations/1770038768784-application_user_topic_id.js' import { SwapTimestamps1771347307798 } from './build/src/services/storage/migrations/1771347307798-swap_timestamps.js' +import { TxSwapTimestamps1771878683383 } from './build/src/services/storage/migrations/1771878683383-tx_swap_timestamps.js' @@ -80,7 +81,8 @@ export default new DataSource({ InvoiceCallbackUrls1752425992291, OldSomethingLeftover1753106599604, UserReceivingInvoiceIdx1753109184611, AppUserDevice1753285173175, UserAccess1759426050669, AddBlindToUserOffer1760000000000, ApplicationAvatarUrl1761000001000, AdminSettings1761683639419, TxSwap1762890527098, TxSwapAddress1764779178945, ClinkRequester1765497600000, TrackedProviderHeight1766504040000, SwapsServiceUrl1768413055036, - InvoiceSwaps1769529793283, InvoiceSwapsFixes1769805357459, ApplicationUserTopicId1770038768784, SwapTimestamps1771347307798 + InvoiceSwaps1769529793283, InvoiceSwapsFixes1769805357459, ApplicationUserTopicId1770038768784, SwapTimestamps1771347307798, + TxSwapTimestamps1771878683383 ], @@ -89,4 +91,4 @@ export default new DataSource({ TrackedProvider, InviteToken, DebitAccess, UserOffer, ManagementGrant, AppUserDevice, UserAccess, AdminSettings, TransactionSwap, InvoiceSwap], // synchronize: true, }) -//npx typeorm migration:generate ./src/services/storage/migrations/tx_swap_timestamps -d ./datasource.js \ No newline at end of file +//npx typeorm migration:generate ./src/services/storage/migrations/refund_swap_info -d ./datasource.js \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 701b7072..47556424 100644 --- a/package-lock.json +++ b/package-lock.json @@ -59,6 +59,7 @@ "zip-a-folder": "^3.1.9" }, "devDependencies": { + "@types/better-sqlite3": "^7.6.13", "@types/chai": "^4.3.4", "@types/chai-string": "^1.4.5", "@types/cors": "^2.8.17", @@ -82,19 +83,19 @@ "license": "MIT" }, "node_modules/@bufbuild/protobuf": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/@bufbuild/protobuf/-/protobuf-2.7.0.tgz", - "integrity": "sha512-qn6tAIZEw5i/wiESBF4nQxZkl86aY4KoO0IkUa2Lh+rya64oTOdJQFlZuMwI1Qz9VBJQrQC4QlSA2DNek5gCOA==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@bufbuild/protobuf/-/protobuf-2.11.0.tgz", + "integrity": "sha512-sBXGT13cpmPR5BMgHE6UEEfEaShh5Ror6rfN3yEK5si7QVrtZg8LEPQb0VVhiLRUslD2yLnXtnRzG035J/mZXQ==", "license": "(Apache-2.0 AND BSD-3-Clause)" }, "node_modules/@bufbuild/protoplugin": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/@bufbuild/protoplugin/-/protoplugin-2.7.0.tgz", - "integrity": "sha512-yUdg8hXzFGR6K8ren7aXly2hT9BxClId814VB142YeZPatY0wqD3c0D8KfIz5nIeMdoPt0/Pm/RycFJCNGMD6w==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@bufbuild/protoplugin/-/protoplugin-2.11.0.tgz", + "integrity": "sha512-lyZVNFUHArIOt4W0+dwYBe5GBwbKzbOy8ObaloEqsw9Mmiwv2O48TwddDoHN4itylC+BaEGqFdI1W8WQt2vWJQ==", "license": "Apache-2.0", "dependencies": { - "@bufbuild/protobuf": "2.7.0", - "@typescript/vfs": "^1.5.2", + "@bufbuild/protobuf": "2.11.0", + "@typescript/vfs": "^1.6.2", "typescript": "5.4.5" } }, @@ -134,21 +135,13 @@ "node": ">=12" } }, - "node_modules/@gar/promisify": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", - "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", - "license": "MIT", - "optional": true, - "peer": true - }, "node_modules/@grpc/grpc-js": { - "version": "1.13.4", - "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.13.4.tgz", - "integrity": "sha512-GsFaMXCkMqkKIvwCQjCrwH+GHbPKBjhwo/8ZuUkWHqbI73Kky9I+pQltrlT0+MWpedCoosda53lgjYfyEPgxBg==", + "version": "1.14.3", + "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.14.3.tgz", + "integrity": "sha512-Iq8QQQ/7X3Sac15oB6p0FmUg/klxQvXLeileoqrTRGJYLV+/9tubbr9ipz0GKHjmXVsgFPo/+W+2cA8eNcR+XA==", "license": "Apache-2.0", "dependencies": { - "@grpc/proto-loader": "^0.7.13", + "@grpc/proto-loader": "^0.8.0", "@js-sdsl/ordered-map": "^4.4.2" }, "engines": { @@ -156,14 +149,14 @@ } }, "node_modules/@grpc/proto-loader": { - "version": "0.7.15", - "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.15.tgz", - "integrity": "sha512-tMXdRCfYVixjuFK+Hk0Q1s38gV9zDiDJfWL3h1rv4Qc39oILCu1TRTDt7+fGUI8K4G1Fj125Hx/ru3azECWTyQ==", + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.8.0.tgz", + "integrity": "sha512-rc1hOQtjIWGxcxpb9aHAfLpIctjEnsDehj0DAiVfBlmT84uvR0uUtN2hEi/ecvWVjXUGf5qPF4qEgiLOx1YIMQ==", "license": "Apache-2.0", "dependencies": { "lodash.camelcase": "^4.3.0", "long": "^5.0.0", - "protobufjs": "^7.2.5", + "protobufjs": "^7.5.3", "yargs": "^17.7.2" }, "bin": { @@ -173,121 +166,25 @@ "node": ">=6" } }, - "node_modules/@isaacs/balanced-match": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@isaacs/balanced-match/-/balanced-match-4.0.1.tgz", - "integrity": "sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==", - "license": "MIT", - "engines": { - "node": "20 || >=22" - } - }, - "node_modules/@isaacs/brace-expansion": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@isaacs/brace-expansion/-/brace-expansion-5.0.0.tgz", - "integrity": "sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA==", - "license": "MIT", - "dependencies": { - "@isaacs/balanced-match": "^4.0.1" - }, - "engines": { - "node": "20 || >=22" - } - }, "node_modules/@isaacs/cliui": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", - "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-9.0.0.tgz", + "integrity": "sha512-AokJm4tuBHillT+FpMtxQ60n8ObyXBatq7jD2/JA9dxbDDokKQm8KMht5ibGzLVU9IJDIKK4TPKgMHEYMn3lMg==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } + }, + "node_modules/@isaacs/fs-minipass": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", + "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", "license": "ISC", "dependencies": { - "string-width": "^5.1.2", - "string-width-cjs": "npm:string-width@^4.2.0", - "strip-ansi": "^7.0.1", - "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", - "wrap-ansi": "^8.1.0", - "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + "minipass": "^7.0.4" }, "engines": { - "node": ">=12" - } - }, - "node_modules/@isaacs/cliui/node_modules/ansi-regex": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.0.tgz", - "integrity": "sha512-TKY5pyBkHyADOPYlRT9Lx6F544mPl0vS5Ew7BJ45hA08Q+t3GjbueLliBWN3sMICk6+y7HdyxSzC4bWS8baBdg==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "license": "MIT" - }, - "node_modules/@isaacs/cliui/node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "license": "MIT", - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@isaacs/cliui/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + "node": ">=18.0.0" } }, "node_modules/@js-sdsl/ordered-map": { @@ -301,29 +198,30 @@ } }, "node_modules/@mapbox/node-pre-gyp": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz", - "integrity": "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-2.0.3.tgz", + "integrity": "sha512-uwPAhccfFJlsfCxMYTwOdVfOz3xqyj8xYL3zJj8f0pb30tLohnnFPhLuqp4/qoEz8sNxe4SESZedcBojRefIzg==", "license": "BSD-3-Clause", "dependencies": { + "consola": "^3.2.3", "detect-libc": "^2.0.0", - "https-proxy-agent": "^5.0.0", - "make-dir": "^3.1.0", + "https-proxy-agent": "^7.0.5", "node-fetch": "^2.6.7", - "nopt": "^5.0.0", - "npmlog": "^5.0.1", - "rimraf": "^3.0.2", - "semver": "^7.3.5", - "tar": "^6.1.11" + "nopt": "^8.0.0", + "semver": "^7.5.3", + "tar": "^7.4.0" }, "bin": { "node-pre-gyp": "bin/node-pre-gyp" + }, + "engines": { + "node": ">=18" } }, "node_modules/@mapbox/node-pre-gyp/node_modules/semver": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", - "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -333,33 +231,39 @@ } }, "node_modules/@noble/ciphers": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/@noble/ciphers/-/ciphers-0.5.3.tgz", - "integrity": "sha512-B0+6IIHiqEs3BPMT0hcRmHvEj2QHOLu+uwt+tqDDeVd0oyVzh7BPrDcPjRnV1PV/5LaknXJJQvOuRGR0zQJz+w==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@noble/ciphers/-/ciphers-2.1.1.tgz", + "integrity": "sha512-bysYuiVfhxNJuldNXlFEitTVdNnYUc+XNJZd7Qm2a5j1vZHgY+fazadNFWFaMK/2vye0JVlxV3gHmC0WDfAOQw==", "license": "MIT", + "engines": { + "node": ">= 20.19.0" + }, "funding": { "url": "https://paulmillr.com/funding/" } }, "node_modules/@noble/curves": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.2.0.tgz", - "integrity": "sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-2.0.1.tgz", + "integrity": "sha512-vs1Az2OOTBiP4q0pwjW5aF0xp9n4MxVrmkFBxc6EKZc6ddYx5gaZiAsZoq0uRRXWbi3AT/sBqn05eRPtn1JCPw==", "license": "MIT", "dependencies": { - "@noble/hashes": "1.3.2" + "@noble/hashes": "2.0.1" + }, + "engines": { + "node": ">= 20.19.0" }, "funding": { "url": "https://paulmillr.com/funding/" } }, "node_modules/@noble/curves/node_modules/@noble/hashes": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz", - "integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-2.0.1.tgz", + "integrity": "sha512-XlOlEbQcE9fmuXxrVTXCTlG2nlRXa9Rj3rr5Ue/+tX+nmkgbX720YHh0VR3hBF9xDvwnb8D2shVGOwNx+ulArw==", "license": "MIT", "engines": { - "node": ">= 16" + "node": ">= 20.19.0" }, "funding": { "url": "https://paulmillr.com/funding/" @@ -412,48 +316,6 @@ "node": ">= 8" } }, - "node_modules/@npmcli/fs": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-1.1.1.tgz", - "integrity": "sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ==", - "license": "ISC", - "optional": true, - "peer": true, - "dependencies": { - "@gar/promisify": "^1.0.1", - "semver": "^7.3.5" - } - }, - "node_modules/@npmcli/fs/node_modules/semver": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", - "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", - "license": "ISC", - "optional": true, - "peer": true, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@npmcli/move-file": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.2.tgz", - "integrity": "sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==", - "deprecated": "This functionality has been moved to @npmcli/fs", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "mkdirp": "^1.0.4", - "rimraf": "^3.0.2" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/@openzeppelin/contracts": { "version": "5.4.0", "resolved": "https://registry.npmjs.org/@openzeppelin/contracts/-/contracts-5.4.0.tgz", @@ -612,6 +474,121 @@ } }, "node_modules/@scure/bip32": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-2.0.1.tgz", + "integrity": "sha512-4Md1NI5BzoVP+bhyJaY3K6yMesEFzNS1sE/cP+9nuvE7p/b0kx9XbpDHHFl8dHtufcbdHRUUQdRqLIPHN/s7yA==", + "license": "MIT", + "dependencies": { + "@noble/curves": "2.0.1", + "@noble/hashes": "2.0.1", + "@scure/base": "2.0.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/bip32/node_modules/@noble/hashes": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-2.0.1.tgz", + "integrity": "sha512-XlOlEbQcE9fmuXxrVTXCTlG2nlRXa9Rj3rr5Ue/+tX+nmkgbX720YHh0VR3hBF9xDvwnb8D2shVGOwNx+ulArw==", + "license": "MIT", + "engines": { + "node": ">= 20.19.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/bip32/node_modules/@scure/base": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@scure/base/-/base-2.0.0.tgz", + "integrity": "sha512-3E1kpuZginKkek01ovG8krQ0Z44E3DHPjc5S2rjJw9lZn3KSQOs8S7wqikF/AH7iRanHypj85uGyxk0XAyC37w==", + "license": "MIT", + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/bip39": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-2.0.1.tgz", + "integrity": "sha512-PsxdFj/d2AcJcZDX1FXN3dDgitDDTmwf78rKZq1a6c1P1Nan1X/Sxc7667zU3U+AN60g7SxxP0YCVw2H/hBycg==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "2.0.1", + "@scure/base": "2.0.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/bip39/node_modules/@noble/hashes": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-2.0.1.tgz", + "integrity": "sha512-XlOlEbQcE9fmuXxrVTXCTlG2nlRXa9Rj3rr5Ue/+tX+nmkgbX720YHh0VR3hBF9xDvwnb8D2shVGOwNx+ulArw==", + "license": "MIT", + "engines": { + "node": ">= 20.19.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/bip39/node_modules/@scure/base": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@scure/base/-/base-2.0.0.tgz", + "integrity": "sha512-3E1kpuZginKkek01ovG8krQ0Z44E3DHPjc5S2rjJw9lZn3KSQOs8S7wqikF/AH7iRanHypj85uGyxk0XAyC37w==", + "license": "MIT", + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@shocknet/clink-sdk": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/@shocknet/clink-sdk/-/clink-sdk-1.5.4.tgz", + "integrity": "sha512-YrKR7oFjzUmBhm4p8pT6mP3YC7UdWbIlh5PMXHSwSLfJhL8Ddx91NLIfOHUTcQa1cDf27uvillMFXYrVUMCRuQ==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "^1.8.0", + "@scure/base": "^1.2.5", + "nostr-tools": "2.15.1", + "rimraf": "^6.0.1", + "typescript": "^5.8.3" + } + }, + "node_modules/@shocknet/clink-sdk/node_modules/@noble/ciphers": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/@noble/ciphers/-/ciphers-0.5.3.tgz", + "integrity": "sha512-B0+6IIHiqEs3BPMT0hcRmHvEj2QHOLu+uwt+tqDDeVd0oyVzh7BPrDcPjRnV1PV/5LaknXJJQvOuRGR0zQJz+w==", + "license": "MIT", + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@shocknet/clink-sdk/node_modules/@noble/curves": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.2.0.tgz", + "integrity": "sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "1.3.2" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@shocknet/clink-sdk/node_modules/@noble/curves/node_modules/@noble/hashes": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz", + "integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==", + "license": "MIT", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@shocknet/clink-sdk/node_modules/@scure/bip32": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.3.1.tgz", "integrity": "sha512-osvveYtyzdEVbt3OfwwXFr4P2iVBL5u1Q3q4ONBfDY/UpOuXmOlbgwc1xECEboY8wIays8Yt6onaWMUdUbfl0A==", @@ -625,7 +602,7 @@ "url": "https://paulmillr.com/funding/" } }, - "node_modules/@scure/bip32/node_modules/@noble/curves": { + "node_modules/@shocknet/clink-sdk/node_modules/@scure/bip32/node_modules/@noble/curves": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.1.0.tgz", "integrity": "sha512-091oBExgENk/kGj3AZmtBDMpxQPDtxQABR2B9lb1JbVTs6ytdzZNwvhxQ4MWasRNEzlbEH8jCWFCwhF/Obj5AA==", @@ -637,7 +614,7 @@ "url": "https://paulmillr.com/funding/" } }, - "node_modules/@scure/bip32/node_modules/@noble/curves/node_modules/@noble/hashes": { + "node_modules/@shocknet/clink-sdk/node_modules/@scure/bip32/node_modules/@noble/curves/node_modules/@noble/hashes": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.1.tgz", "integrity": "sha512-EbqwksQwz9xDRGfDST86whPBgM65E0OH/pCgqW0GBVzO22bNE+NuIbeTb714+IfSjU3aRk47EUvXIb5bTsenKA==", @@ -649,7 +626,7 @@ "url": "https://paulmillr.com/funding/" } }, - "node_modules/@scure/bip32/node_modules/@noble/hashes": { + "node_modules/@shocknet/clink-sdk/node_modules/@scure/bip32/node_modules/@noble/hashes": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.3.tgz", "integrity": "sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA==", @@ -661,7 +638,7 @@ "url": "https://paulmillr.com/funding/" } }, - "node_modules/@scure/bip32/node_modules/@scure/base": { + "node_modules/@shocknet/clink-sdk/node_modules/@scure/bip32/node_modules/@scure/base": { "version": "1.1.9", "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.9.tgz", "integrity": "sha512-8YKhl8GHiNI/pU2VMaofa2Tor7PJRAjwQLBBuilkJ9L5+13yVbC7JO/wS7piioAvPSwR3JKM1IJ/u4xQzbcXKg==", @@ -670,7 +647,7 @@ "url": "https://paulmillr.com/funding/" } }, - "node_modules/@scure/bip39": { + "node_modules/@shocknet/clink-sdk/node_modules/@scure/bip39": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.2.1.tgz", "integrity": "sha512-Z3/Fsz1yr904dduJD0NpiyRHhRYHdcnyh73FZWiV+/qhWi83wNJ3NWolYqCEN+ZWsUz2TWwajJggcRE9r1zUYg==", @@ -683,7 +660,7 @@ "url": "https://paulmillr.com/funding/" } }, - "node_modules/@scure/bip39/node_modules/@noble/hashes": { + "node_modules/@shocknet/clink-sdk/node_modules/@scure/bip39/node_modules/@noble/hashes": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.3.tgz", "integrity": "sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA==", @@ -695,7 +672,7 @@ "url": "https://paulmillr.com/funding/" } }, - "node_modules/@scure/bip39/node_modules/@scure/base": { + "node_modules/@shocknet/clink-sdk/node_modules/@scure/bip39/node_modules/@scure/base": { "version": "1.1.9", "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.9.tgz", "integrity": "sha512-8YKhl8GHiNI/pU2VMaofa2Tor7PJRAjwQLBBuilkJ9L5+13yVbC7JO/wS7piioAvPSwR3JKM1IJ/u4xQzbcXKg==", @@ -704,35 +681,40 @@ "url": "https://paulmillr.com/funding/" } }, - "node_modules/@shocknet/clink-sdk": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@shocknet/clink-sdk/-/clink-sdk-1.4.0.tgz", - "integrity": "sha512-J0PWE8CVRJrFF1Zi/UhChhvOrlmDj7LRJTpR6rbHlFPmjC5TGIW6891tVWWv+JmUR0jzez9QHFrHnc8DgIJYCQ==", + "node_modules/@shocknet/clink-sdk/node_modules/balanced-match": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.2.tgz", + "integrity": "sha512-x0K50QvKQ97fdEz2kPehIerj+YTeptKF9hyYkKf6egnwmMWAkADiO0QCzSp0R5xN8FTZgYaBfSaue46Ej62nMg==", "license": "MIT", "dependencies": { - "@noble/hashes": "^1.8.0", - "@scure/base": "^1.2.5", - "nostr-tools": "^2.13.0", - "rimraf": "^6.0.1", - "typescript": "^5.8.3" + "jackspeak": "^4.2.3" + }, + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/@shocknet/clink-sdk/node_modules/brace-expansion": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.2.tgz", + "integrity": "sha512-Pdk8c9poy+YhOgVWw1JNN22/HcivgKWwpxKq04M/jTmHyCZn12WPJebZxdjSa5TmBqISrUSgNYU3eRORljfCCw==", + "license": "MIT", + "dependencies": { + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "20 || >=22" } }, "node_modules/@shocknet/clink-sdk/node_modules/glob": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-11.0.3.tgz", - "integrity": "sha512-2Nim7dha1KVkaiF4q6Dj+ngPPMdfvLJEOpZk/jKiUAkqKebpGAWQXAq9z1xu9HKu5lWfqw/FASuccEjyznjPaA==", - "license": "ISC", + "version": "13.0.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-13.0.3.tgz", + "integrity": "sha512-/g3B0mC+4x724v1TgtBlBtt2hPi/EWptsIAmXUx9Z2rvBYleQcsrmaOzd5LyL50jf/Soi83ZDJmw2+XqvH/EeA==", + "license": "BlueOak-1.0.0", "dependencies": { - "foreground-child": "^3.3.1", - "jackspeak": "^4.1.1", - "minimatch": "^10.0.3", + "minimatch": "^10.2.0", "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", "path-scurry": "^2.0.0" }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, "engines": { "node": "20 || >=22" }, @@ -741,12 +723,12 @@ } }, "node_modules/@shocknet/clink-sdk/node_modules/minimatch": { - "version": "10.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.3.tgz", - "integrity": "sha512-IPZ167aShDZZUMdRk66cyQAW3qr0WzbHkPdMYa8bzZhlHhO3jALbKdxcaak7W9FfT2rZNpQuUu4Od7ILEpXSaw==", - "license": "ISC", + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.0.tgz", + "integrity": "sha512-ugkC31VaVg9cF0DFVoADH12k6061zNZkZON+aX8AWsR9GhPcErkcMBceb6znR8wLERM2AkkOxy2nWRLpT9Jq5w==", + "license": "BlueOak-1.0.0", "dependencies": { - "@isaacs/brace-expansion": "^5.0.0" + "brace-expansion": "^5.0.2" }, "engines": { "node": "20 || >=22" @@ -755,23 +737,61 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@shocknet/clink-sdk/node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "license": "ISC", - "engines": { - "node": ">=16 || 14 >=14.17" + "node_modules/@shocknet/clink-sdk/node_modules/nostr-tools": { + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/nostr-tools/-/nostr-tools-2.15.1.tgz", + "integrity": "sha512-LpetHDR9ltnkpJDkva/SONgyKBbsoV+5yLB8DWc0/U3lCWGtoWJw6Nbc2vR2Ai67RIQYrBQeZLyMlhwVZRK/9A==", + "license": "Unlicense", + "dependencies": { + "@noble/ciphers": "^0.5.1", + "@noble/curves": "1.2.0", + "@noble/hashes": "1.3.1", + "@scure/base": "1.1.1", + "@scure/bip32": "1.3.1", + "@scure/bip39": "1.2.1", + "nostr-wasm": "0.1.0" + }, + "peerDependencies": { + "typescript": ">=5.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, + "node_modules/@shocknet/clink-sdk/node_modules/nostr-tools/node_modules/@noble/hashes": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.1.tgz", + "integrity": "sha512-EbqwksQwz9xDRGfDST86whPBgM65E0OH/pCgqW0GBVzO22bNE+NuIbeTb714+IfSjU3aRk47EUvXIb5bTsenKA==", + "license": "MIT", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@shocknet/clink-sdk/node_modules/nostr-tools/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/@shocknet/clink-sdk/node_modules/rimraf": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-6.0.1.tgz", - "integrity": "sha512-9dkvaxAsk/xNXSJzMgFqqMCuFgt2+KsOFek3TMLfo8NCPfWpBmqwyNn5Y+NX56QUYfCtsyhF3ayiboEoUmJk/A==", - "license": "ISC", + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-6.1.2.tgz", + "integrity": "sha512-cFCkPslJv7BAXJsYlK1dZsbP8/ZNLkCAQ0bi1hf5EKX2QHegmDFEFA6QhuYJlk7UDdc+02JjO80YSOrWPpw06g==", + "license": "BlueOak-1.0.0", "dependencies": { - "glob": "^11.0.0", - "package-json-from-dist": "^1.0.0" + "glob": "^13.0.0", + "package-json-from-dist": "^1.0.1" }, "bin": { "rimraf": "dist/esm/bin.mjs" @@ -784,9 +804,9 @@ } }, "node_modules/@shocknet/clink-sdk/node_modules/typescript": { - "version": "5.9.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.2.tgz", - "integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==", + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", @@ -844,21 +864,10 @@ "@stablelib/wipe": "^1.0.1" } }, - "node_modules/@tootallnate/once": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", - "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">= 6" - } - }, "node_modules/@tsconfig/node10": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", - "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.12.tgz", + "integrity": "sha512-UCYBaeFvM11aU2y3YPZ//O5Rhj+xKyzy7mvcIoAjASbigy8mHMryP5cK7dgjlz2hWxh1g5pLw084E0a/wlUSFQ==", "devOptional": true, "license": "MIT" }, @@ -883,6 +892,16 @@ "devOptional": true, "license": "MIT" }, + "node_modules/@types/better-sqlite3": { + "version": "7.6.13", + "resolved": "https://registry.npmjs.org/@types/better-sqlite3/-/better-sqlite3-7.6.13.tgz", + "integrity": "sha512-NMv9ASNARoKksWtsq/SHakpYAYnhBrQgGD8zkLYk/jaK8jUGn08CfEdTRgYhMypUQAfzSP8W6gNLe0q19/t4VA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/body-parser": { "version": "1.19.6", "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.6.tgz", @@ -948,21 +967,21 @@ "license": "MIT" }, "node_modules/@types/express": { - "version": "4.17.23", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.23.tgz", - "integrity": "sha512-Crp6WY9aTYP3qPi2wGDo9iUe/rceX01UMhnF1jmwDcKCFM6cx7YhGP/Mpr3y9AASpfHixIG0E6azCcL5OcDHsQ==", + "version": "4.17.25", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.25.tgz", + "integrity": "sha512-dVd04UKsfpINUnK0yBoYHDF3xu7xVH4BuDotC/xGuycx4CgbP48X/KF/586bcObxT0HENHXEU8Nqtu6NR+eKhw==", "license": "MIT", "dependencies": { "@types/body-parser": "*", "@types/express-serve-static-core": "^4.17.33", "@types/qs": "*", - "@types/serve-static": "*" + "@types/serve-static": "^1" } }, "node_modules/@types/express-serve-static-core": { - "version": "4.19.6", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.6.tgz", - "integrity": "sha512-N4LZ2xG7DatVqhCZzOGb1Yi5lMbXSZcmdLDe9EzSndPV2HpWYWzRbaerl2n27irrm94EPpprqa8KpskPT085+A==", + "version": "4.19.8", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.8.tgz", + "integrity": "sha512-02S5fmqeoKzVZCHPZid4b8JH2eM5HzQLZWN2FohQEy/0eXTq8VXZfSN6Pcr3F6N9R/vNrj7cpgbhjie6m/1tCA==", "license": "MIT", "dependencies": { "@types/node": "*", @@ -989,9 +1008,9 @@ } }, "node_modules/@types/lodash": { - "version": "4.17.20", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.20.tgz", - "integrity": "sha512-H3MHACvFUEiujabxhaI/ImO6gUrd8oOurg7LQtS7mbwIXA/cUqWrvBsaeJ23aZEPk1TAYkurjfMbSELfoCXlGA==", + "version": "4.17.23", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.23.tgz", + "integrity": "sha512-RDvF6wTulMPjrNdCoYRC8gNR880JNGT8uB+REUpC2Ns4pRqQJhGz90wh7rgdXDPpCczF3VGktDuFGVnz8zP7HA==", "dev": true, "license": "MIT" }, @@ -1048,33 +1067,42 @@ "license": "MIT" }, "node_modules/@types/secp256k1": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@types/secp256k1/-/secp256k1-4.0.6.tgz", - "integrity": "sha512-hHxJU6PAEUn0TP4S/ZOzuTUvJWuZ6eIKeNKb5RBpODvSl6hp1Wrw4s7ATY50rklRCScUDpHzVA/DQdSjJ3UoYQ==", + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/@types/secp256k1/-/secp256k1-4.0.7.tgz", + "integrity": "sha512-Rcvjl6vARGAKRO6jHeKMatGrvOMGrR/AR11N1x2LqintPCyDZ7NBhrh238Z2VZc7aM7KIwnFpFQ7fnfK4H/9Qw==", "license": "MIT", "dependencies": { "@types/node": "*" } }, "node_modules/@types/send": { - "version": "0.17.5", - "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.5.tgz", - "integrity": "sha512-z6F2D3cOStZvuk2SaP6YrwkNO65iTZcwA2ZkSABegdkAh/lf+Aa/YQndZVfmEXT5vgAp6zv06VQ3ejSVjAny4w==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@types/send/-/send-1.2.1.tgz", + "integrity": "sha512-arsCikDvlU99zl1g69TcAB3mzZPpxgw0UQnaHeC1Nwb015xp8bknZv5rIfri9xTOcMuaVgvabfIRA7PSZVuZIQ==", "license": "MIT", "dependencies": { - "@types/mime": "^1", "@types/node": "*" } }, "node_modules/@types/serve-static": { - "version": "1.15.8", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.8.tgz", - "integrity": "sha512-roei0UY3LhpOJvjbIP6ZZFngyLKl5dskOtDhxY5THRSpO+ZI+nzJ+m5yUMzGrp89YRa7lvknKkMYjqQFGwA7Sg==", + "version": "1.15.10", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.10.tgz", + "integrity": "sha512-tRs1dB+g8Itk72rlSI2ZrW6vZg0YrLI81iQSTkMmOqnqCaNr/8Ek4VwWcN5vZgCYWbg/JJSGBlUaYGAOP73qBw==", "license": "MIT", "dependencies": { "@types/http-errors": "*", "@types/node": "*", - "@types/send": "*" + "@types/send": "<1" + } + }, + "node_modules/@types/serve-static/node_modules/@types/send": { + "version": "0.17.6", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.6.tgz", + "integrity": "sha512-Uqt8rPBE8SY0RK8JB1EzVOIZ32uqy8HwdxCnoCOsYrvnswqmFZ/k+9Ikidlk/ImhsdvBsloHbAlewb2IEBV/Og==", + "license": "MIT", + "dependencies": { + "@types/mime": "^1", + "@types/node": "*" } }, "node_modules/@types/uuid": { @@ -1105,9 +1133,9 @@ } }, "node_modules/@typescript/vfs": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/@typescript/vfs/-/vfs-1.6.1.tgz", - "integrity": "sha512-JwoxboBh7Oz1v38tPbkrZ62ZXNHAk9bJ7c9x0eI5zBfBnBYGhURdbnh7Z4smN/MV48Y5OCcZb58n972UtbazsA==", + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/@typescript/vfs/-/vfs-1.6.2.tgz", + "integrity": "sha512-hoBwJwcbKHmvd2QVebiytN1aELvpk9B74B4L1mFm/XT1Q/VOYAWl2vQ9AWRFtQq8zmz6enTpfTV8WRc4ATjW/g==", "license": "MIT", "dependencies": { "debug": "^4.1.1" @@ -1154,10 +1182,13 @@ } }, "node_modules/abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", - "license": "ISC" + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-3.0.1.tgz", + "integrity": "sha512-AO2ac6pjRB3SJmGJo+v5/aK6Omggp6fsLrs6wN9bd35ulu4cCwaAU9+7ZhXjeqHVkaHThLuzH0nZr0YpCDhygg==", + "license": "ISC", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } }, "node_modules/abort-controller": { "version": "3.0.0", @@ -1223,44 +1254,12 @@ } }, "node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", "license": "MIT", - "dependencies": { - "debug": "4" - }, "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/agentkeepalive": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.6.0.tgz", - "integrity": "sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "humanize-ms": "^1.2.1" - }, - "engines": { - "node": ">= 8.0.0" - } - }, - "node_modules/aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - }, - "engines": { - "node": ">=8" + "node": ">= 14" } }, "node_modules/ajv": { @@ -1304,9 +1303,9 @@ } }, "node_modules/ansis": { - "version": "3.17.0", - "resolved": "https://registry.npmjs.org/ansis/-/ansis-3.17.0.tgz", - "integrity": "sha512-0qWUglt9JEqLFr3w1I1pbrChn1grhaiAR2ocX1PP/flRmxgtwTzPFFFnfIlD6aMOLQZgSuCRlidD70lvx8yhzg==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/ansis/-/ansis-4.2.0.tgz", + "integrity": "sha512-HqZ5rWlFjGiV0tDm3UxxgNRqsOTniqoKZu0pIAfh7TZQMGuZK+hH0drySty0si0QXj1ieop4+SkSfPZBPPkHig==", "license": "ISC", "engines": { "node": ">=14" @@ -1335,12 +1334,6 @@ "node": ">= 6.0.0" } }, - "node_modules/aproba": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.1.0.tgz", - "integrity": "sha512-tLIEcj5GuR2RSTnxNKdkK0dJ/GrC7P38sUkiDmDuHfsHmbagTFAxDVIBltoklXEVIQ/f14IL8IMJ5pn9Hez1Ew==", - "license": "ISC" - }, "node_modules/archiver": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/archiver/-/archiver-7.0.1.tgz", @@ -1377,6 +1370,47 @@ "node": ">= 14" } }, + "node_modules/archiver-utils/node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "license": "ISC", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/archiver-utils/node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/archiver-utils/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, "node_modules/archiver-utils/node_modules/brace-expansion": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", @@ -1410,10 +1444,17 @@ "ieee754": "^1.2.1" } }, + "node_modules/archiver-utils/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "license": "MIT" + }, "node_modules/archiver-utils/node_modules/glob": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", "license": "ISC", "dependencies": { "foreground-child": "^3.1.0", @@ -1466,15 +1507,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/archiver-utils/node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "license": "ISC", - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, "node_modules/archiver-utils/node_modules/path-scurry": { "version": "1.11.1", "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", @@ -1516,6 +1548,55 @@ "safe-buffer": "~5.2.0" } }, + "node_modules/archiver-utils/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/archiver-utils/node_modules/strip-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", + "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/archiver-utils/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/archiver/node_modules/buffer": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", @@ -1576,43 +1657,6 @@ "streamx": "^2.15.0" } }, - "node_modules/are-we-there-yet": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", - "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", - "deprecated": "This package is no longer supported.", - "license": "ISC", - "dependencies": { - "delegates": "^1.0.0", - "readable-stream": "^3.6.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/are-we-there-yet/node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "license": "MIT", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/are-we-there-yet/node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "license": "MIT", - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, "node_modules/arg": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", @@ -1696,21 +1740,29 @@ "license": "MIT" }, "node_modules/axios": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.11.0.tgz", - "integrity": "sha512-1Lx3WLFQWm3ooKDYZD1eXmoGO9fxYQjrycfHFC8P0sCfQVXyROp0p9PFWBehewBOdCwHc+f/b8I0fMto5eSfwA==", + "version": "1.13.5", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.5.tgz", + "integrity": "sha512-cz4ur7Vb0xS4/KUN0tPWe44eqxrIu31me+fbang3ijiNscE129POzipJJA6zniq2C/Z6sJCjMimjS8Lc/GAs8Q==", "license": "MIT", "dependencies": { - "follow-redirects": "^1.15.6", - "form-data": "^4.0.4", + "follow-redirects": "^1.15.11", + "form-data": "^4.0.5", "proxy-from-env": "^1.1.0" } }, "node_modules/b4a": { - "version": "1.6.7", - "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.7.tgz", - "integrity": "sha512-OnAYlL5b7LEkALw87fUVafQw5rVR9RjwGd4KUwNQ6DrrNmaVaUCgLipfVlzrPQ4tWOR9P0IXGNOx50jYCCdSJg==", - "license": "Apache-2.0" + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.7.4.tgz", + "integrity": "sha512-u20zJLDaSWpxaZ+zaAkEIB2dZZ1o+DF4T/MRbmsvGp9nletHOyiai19OzX1fF8xUBYsO1bPXxODvcd0978pnug==", + "license": "Apache-2.0", + "peerDependencies": { + "react-native-b4a": "*" + }, + "peerDependenciesMeta": { + "react-native-b4a": { + "optional": true + } + } }, "node_modules/balanced-match": { "version": "1.0.2", @@ -1719,16 +1771,23 @@ "license": "MIT" }, "node_modules/bare-events": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.6.1.tgz", - "integrity": "sha512-AuTJkq9XmE6Vk0FJVNq5QxETrSA/vKHarWVBG5l/JbdCL1prJemiyJqUS0jrlXO0MftuPq4m3YVYhoNc5+aE/g==", + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.8.2.tgz", + "integrity": "sha512-riJjyv1/mHLIPX4RwiK+oW9/4c3TEUeORHKefKAKnZ5kyslbN+HXowtbaVEqt4IMUB7OXlfixcs6gsFeo/jhiQ==", "license": "Apache-2.0", - "optional": true + "peerDependencies": { + "bare-abort-controller": "*" + }, + "peerDependenciesMeta": { + "bare-abort-controller": { + "optional": true + } + } }, "node_modules/base-x": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/base-x/-/base-x-5.0.1.tgz", - "integrity": "sha512-M7uio8Zt++eg3jPj+rHMfCC+IuygQHHCOU+IYsVtik6FWjuYpVt/+MRKcgsAMHh8mMFAwnB+Bs+mTrFiXjMzKg==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/base-x/-/base-x-4.0.1.tgz", + "integrity": "sha512-uAZ8x6r6S3aUM9rbHGVOIsR15U/ZSc82b3ymnCPsT45Gk1DDvhDPdIgB5MrhirZWt+5K0EEPQH985kNqZgNPFw==", "license": "MIT" }, "node_modules/base64-js": { @@ -1767,9 +1826,9 @@ "license": "MIT" }, "node_modules/better-sqlite3": { - "version": "12.2.0", - "resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-12.2.0.tgz", - "integrity": "sha512-eGbYq2CT+tos1fBwLQ/tkBt9J5M3JEHjku4hbvQUePCckkvVf14xWj+1m7dGoK81M/fOjFT7yM9UMeKT/+vFLQ==", + "version": "12.6.2", + "resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-12.6.2.tgz", + "integrity": "sha512-8VYKM3MjCa9WcaSAI3hzwhmyHVlH8tiGFwf0RlTsZPWJ1I5MkzjiudCo4KC4DxOaL/53A5B1sI/IbldNFDbsKA==", "hasInstallScript": true, "license": "MIT", "dependencies": { @@ -1777,7 +1836,7 @@ "prebuild-install": "^7.1.1" }, "engines": { - "node": "20.x || 22.x || 23.x || 24.x" + "node": "20.x || 22.x || 23.x || 24.x || 25.x" } }, "node_modules/bignumber.js": { @@ -1855,13 +1914,10 @@ } }, "node_modules/bip66": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/bip66/-/bip66-1.1.5.tgz", - "integrity": "sha512-nemMHz95EmS38a26XbbdxIYj5csHd3RMP3H5bwQknX0WYHF01qhpufP42mLOwVICuH2JmhIhXiWs89MfUGL7Xw==", - "license": "MIT", - "dependencies": { - "safe-buffer": "^5.0.1" - } + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/bip66/-/bip66-2.0.0.tgz", + "integrity": "sha512-kBG+hSpgvZBrkIm9dt5T1Hd/7xGCPEX2npoxAWZfsK1FvjgaxySEh2WizjyIstWXriKo9K9uJ4u0OnsyLDUPXQ==", + "license": "MIT" }, "node_modules/bitcoin-core": { "version": "4.2.0", @@ -1898,40 +1954,6 @@ "node": ">=8.0.0" } }, - "node_modules/bitcoinjs-lib/node_modules/base-x": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/base-x/-/base-x-4.0.1.tgz", - "integrity": "sha512-uAZ8x6r6S3aUM9rbHGVOIsR15U/ZSc82b3ymnCPsT45Gk1DDvhDPdIgB5MrhirZWt+5K0EEPQH985kNqZgNPFw==", - "license": "MIT" - }, - "node_modules/bitcoinjs-lib/node_modules/bs58": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/bs58/-/bs58-5.0.0.tgz", - "integrity": "sha512-r+ihvQJvahgYT50JD05dyJNKlmmSlMoOGwn1lCcEzanPglg7TxYjioQUYehQ9mAR/+hOSd2jRc/Z2y5UxBymvQ==", - "license": "MIT", - "dependencies": { - "base-x": "^4.0.0" - } - }, - "node_modules/bitcoinjs-lib/node_modules/bs58check": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/bs58check/-/bs58check-3.0.1.tgz", - "integrity": "sha512-hjuuJvoWEybo7Hn/0xOrczQKKEKD63WguEjlhLExYs2wUBcebDC1jDNK17eEAD2lYfw82d5ASC1d7K3SWszjaQ==", - "license": "MIT", - "dependencies": { - "@noble/hashes": "^1.2.0", - "bs58": "^5.0.0" - } - }, - "node_modules/bitcoinjs-lib/node_modules/varuint-bitcoin": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/varuint-bitcoin/-/varuint-bitcoin-1.1.2.tgz", - "integrity": "sha512-4EVb+w4rx+YfVM32HQX42AbbT7/1f5zwAYhIujKXKk8NQK+JfRVl3pqT3hjNn/L+RstigmGGKVwHA/P0wgITZw==", - "license": "MIT", - "dependencies": { - "safe-buffer": "^5.1.1" - } - }, "node_modules/bitset": { "version": "5.2.3", "resolved": "https://registry.npmjs.org/bitset/-/bitset-5.2.3.tgz", @@ -1971,15 +1993,6 @@ "node": ">= 6" } }, - "node_modules/bl/node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "license": "MIT", - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, "node_modules/blech32": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/blech32/-/blech32-1.1.2.tgz", @@ -2001,29 +2014,29 @@ "peer": true }, "node_modules/bn.js": { - "version": "4.12.2", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.2.tgz", - "integrity": "sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw==", + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.2.tgz", + "integrity": "sha512-v2YAxEmKaBLahNwE1mjp4WON6huMNeuDvagFZW+ASCuA/ku0bXR9hSMw0XpiqMoA3+rmnyck/tPRSFQkoC9Cuw==", "license": "MIT" }, "node_modules/body-parser": { - "version": "1.20.3", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", - "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", + "version": "1.20.4", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.4.tgz", + "integrity": "sha512-ZTgYYLMOXY9qKU/57FAo8F+HA2dGX7bqGc71txDRC1rS4frdFI5R7NhluHxH6M0YItAP0sHB4uqAOcYKxO6uGA==", "license": "MIT", "dependencies": { - "bytes": "3.1.2", + "bytes": "~3.1.2", "content-type": "~1.0.5", "debug": "2.6.9", "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.13.0", - "raw-body": "2.5.2", + "destroy": "~1.2.0", + "http-errors": "~2.0.1", + "iconv-lite": "~0.4.24", + "on-finished": "~2.4.1", + "qs": "~6.14.0", + "raw-body": "~2.5.3", "type-is": "~1.6.18", - "unpipe": "1.0.0" + "unpipe": "~1.0.0" }, "engines": { "node": ">= 0.8", @@ -2046,19 +2059,19 @@ "license": "MIT" }, "node_modules/boltz-core": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/boltz-core/-/boltz-core-3.0.0.tgz", - "integrity": "sha512-L0jzUnTIb/vir9k6yVlCkV8I29ZeBK7LWq3rrDcp/KP7bB0VvKR5JTceua8g2KBCBM5HOMVDEuPW3c9/82/Nmg==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/boltz-core/-/boltz-core-3.1.2.tgz", + "integrity": "sha512-FxDcOuANAvRKI/1IHKySjfBXDcXCXR3ImM9ndjYGN5km8lXGJWwYEt85KtTBNFTPSdBcNnkOPQ1nXJK6R62gCg==", "license": "AGPL-3.0", "dependencies": { "@boltz/bitcoin-ops": "^2.0.0", - "@openzeppelin/contracts": "^5.2.0", + "@openzeppelin/contracts": "^5.4.0", "@vulpemventures/secp256k1-zkp": "^3.2.1", "bip32": "^4.0.0", "bip65": "^1.0.3", "bip66": "^2.0.0", "bitcoinjs-lib": "^6.1.7", - "bn.js": "^5.2.1", + "bn.js": "^5.2.2", "ecpair": "^3.0.0", "varuint-bitcoin": "^2.0.0" }, @@ -2069,17 +2082,14 @@ "liquidjs-lib": "^6.0.2-liquid.37" } }, - "node_modules/boltz-core/node_modules/bip66": { + "node_modules/boltz-core/node_modules/varuint-bitcoin": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/bip66/-/bip66-2.0.0.tgz", - "integrity": "sha512-kBG+hSpgvZBrkIm9dt5T1Hd/7xGCPEX2npoxAWZfsK1FvjgaxySEh2WizjyIstWXriKo9K9uJ4u0OnsyLDUPXQ==", - "license": "MIT" - }, - "node_modules/boltz-core/node_modules/bn.js": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.2.tgz", - "integrity": "sha512-v2YAxEmKaBLahNwE1mjp4WON6huMNeuDvagFZW+ASCuA/ku0bXR9hSMw0XpiqMoA3+rmnyck/tPRSFQkoC9Cuw==", - "license": "MIT" + "resolved": "https://registry.npmjs.org/varuint-bitcoin/-/varuint-bitcoin-2.0.0.tgz", + "integrity": "sha512-6QZbU/rHO2ZQYpWFDALCDSRsXbAs1VOEmXAxtbtjLtKuMJ/FQ8YbhfxlaiKv5nklci0M6lZtlZyxo9Q+qNnyog==", + "license": "MIT", + "dependencies": { + "uint8array-tools": "^0.0.8" + } }, "node_modules/brace-expansion": { "version": "1.1.12", @@ -2125,22 +2135,22 @@ } }, "node_modules/bs58": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/bs58/-/bs58-6.0.0.tgz", - "integrity": "sha512-PD0wEnEYg6ijszw/u8s+iI3H17cTymlrwkKhDhPZq+Sokl3AU4htyBFTjAeNAlCCmg0f53g6ih3jATyCKftTfw==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/bs58/-/bs58-5.0.0.tgz", + "integrity": "sha512-r+ihvQJvahgYT50JD05dyJNKlmmSlMoOGwn1lCcEzanPglg7TxYjioQUYehQ9mAR/+hOSd2jRc/Z2y5UxBymvQ==", "license": "MIT", "dependencies": { - "base-x": "^5.0.0" + "base-x": "^4.0.0" } }, "node_modules/bs58check": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/bs58check/-/bs58check-4.0.0.tgz", - "integrity": "sha512-FsGDOnFg9aVI9erdriULkd/JjEWONV/lQE5aYziB5PoBsXRind56lh8doIZIc9X4HoxT5x4bLjMWN1/NB8Zp5g==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/bs58check/-/bs58check-3.0.1.tgz", + "integrity": "sha512-hjuuJvoWEybo7Hn/0xOrczQKKEKD63WguEjlhLExYs2wUBcebDC1jDNK17eEAD2lYfw82d5ASC1d7K3SWszjaQ==", "license": "MIT", "dependencies": { "@noble/hashes": "^1.2.0", - "bs58": "^6.0.0" + "bs58": "^5.0.0" } }, "node_modules/buffer": { @@ -2189,21 +2199,6 @@ "license": "MIT", "optional": true }, - "node_modules/bufferutil": { - "version": "4.0.9", - "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.9.tgz", - "integrity": "sha512-WDtdLmJvAuNNPzByAYpRo2rF1Mmradw6gvWsQKf63476DDXmomT9zUiGypLcG4ibIM67vhAj8jJRdbmEws2Aqw==", - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "node-gyp-build": "^4.3.0" - }, - "engines": { - "node": ">=6.14.2" - } - }, "node_modules/bunyan": { "version": "1.8.15", "resolved": "https://registry.npmjs.org/bunyan/-/bunyan-1.8.15.tgz", @@ -2231,65 +2226,6 @@ "node": ">= 0.8" } }, - "node_modules/cacache": { - "version": "15.3.0", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.3.0.tgz", - "integrity": "sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ==", - "license": "ISC", - "optional": true, - "peer": true, - "dependencies": { - "@npmcli/fs": "^1.0.0", - "@npmcli/move-file": "^1.0.1", - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "glob": "^7.1.4", - "infer-owner": "^1.0.4", - "lru-cache": "^6.0.0", - "minipass": "^3.1.1", - "minipass-collect": "^1.0.2", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.2", - "mkdirp": "^1.0.3", - "p-map": "^4.0.0", - "promise-inflight": "^1.0.1", - "rimraf": "^3.0.2", - "ssri": "^8.0.1", - "tar": "^6.0.2", - "unique-filename": "^1.1.1" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/cacache/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "license": "ISC", - "optional": true, - "peer": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/cacache/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "license": "ISC", - "optional": true, - "peer": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/call-bind": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", @@ -2420,38 +2356,28 @@ } }, "node_modules/chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "license": "ISC", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", + "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", + "license": "BlueOak-1.0.0", "engines": { - "node": ">=10" + "node": ">=18" } }, "node_modules/cipher-base": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.6.tgz", - "integrity": "sha512-3Ek9H3X6pj5TgenXYtNWdaBon1tgYCaebd+XPg0keyjEbEfkD4KkmAxkQ/i1vYvxdcT5nscLBfq9VJRmCBcFSw==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.7.tgz", + "integrity": "sha512-Mz9QMT5fJe7bKI7MH31UilT5cEK5EHHRCccw/YRFsRY47AuNgaV6HY3rscp0/I4Q+tTW/5zoqpSeRRI54TkDWA==", "license": "MIT", "dependencies": { "inherits": "^2.0.4", - "safe-buffer": "^5.2.1" + "safe-buffer": "^5.2.1", + "to-buffer": "^1.2.2" }, "engines": { "node": ">= 0.10" } }, - "node_modules/clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">=6" - } - }, "node_modules/cliui": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", @@ -2484,15 +2410,6 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "license": "MIT" }, - "node_modules/color-support": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", - "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", - "license": "ISC", - "bin": { - "color-support": "bin.js" - } - }, "node_modules/combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -2576,11 +2493,14 @@ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "license": "MIT" }, - "node_modules/console-control-strings": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", - "license": "ISC" + "node_modules/consola": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/consola/-/consola-3.4.2.tgz", + "integrity": "sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==", + "license": "MIT", + "engines": { + "node": "^14.18.0 || >=16.10.0" + } }, "node_modules/content-disposition": { "version": "0.5.4", @@ -2604,18 +2524,18 @@ } }, "node_modules/cookie": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", - "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.7.tgz", + "integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==", "license": "MIT" }, "node_modules/copyfiles": { @@ -2682,9 +2602,9 @@ "license": "MIT" }, "node_modules/cors": { - "version": "2.8.5", - "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", - "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "version": "2.8.6", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.6.tgz", + "integrity": "sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw==", "license": "MIT", "dependencies": { "object-assign": "^4", @@ -2692,6 +2612,10 @@ }, "engines": { "node": ">= 0.10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/crc-32": { @@ -2862,15 +2786,15 @@ } }, "node_modules/dayjs": { - "version": "1.11.13", - "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz", - "integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==", + "version": "1.11.19", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.19.tgz", + "integrity": "sha512-t5EcLVS6QPBNqM2z8fakk/NKel+Xzshgt8FFKAn+qwlD1pzZWxh0nVCrvFK7ZDb6XucZeF9z8C7CBWTRIVApAw==", "license": "MIT" }, "node_modules/debug": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", - "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "license": "MIT", "dependencies": { "ms": "^2.1.3" @@ -2928,9 +2852,9 @@ } }, "node_modules/dedent": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.6.0.tgz", - "integrity": "sha512-F1Z+5UCFpmQUzJa11agbyPVMbpgT/qA3/SKyJ1jyBgm7dUcUEa8v9JwDkerSQXfakBwFljIxhOJqGkjUwZ9FSA==", + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.7.1.tgz", + "integrity": "sha512-9JmrhGZpOlEgOLdQgSm0zxFaYoQon408V1v49aqTWuXENVlnCuY9JBZcXZiCsZQWDjTm5Qf/nIvAy77mXDAjEg==", "license": "MIT", "peerDependencies": { "babel-plugin-macros": "^3.1.0" @@ -2988,12 +2912,6 @@ "node": ">=0.4.0" } }, - "node_modules/delegates": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", - "license": "MIT" - }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -3014,18 +2932,18 @@ } }, "node_modules/detect-libc": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.4.tgz", - "integrity": "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", "license": "Apache-2.0", "engines": { "node": ">=8" } }, "node_modules/diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.4.tgz", + "integrity": "sha512-X07nttJQkwkfKfvTPG/KSnE2OMdcUCao6+eXF3wmnIQRn2aPAHH3VxDbDOdegkd6JbPsXqShpvEOHfAT+nCNwQ==", "devOptional": true, "license": "BSD-3-Clause", "engines": { @@ -3170,6 +3088,23 @@ "secp256k1": "3.7.1" } }, + "node_modules/eccrypto/node_modules/bip66": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/bip66/-/bip66-1.1.5.tgz", + "integrity": "sha512-nemMHz95EmS38a26XbbdxIYj5csHd3RMP3H5bwQknX0WYHF01qhpufP42mLOwVICuH2JmhIhXiWs89MfUGL7Xw==", + "license": "MIT", + "optional": true, + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "node_modules/eccrypto/node_modules/bn.js": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.2.tgz", + "integrity": "sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw==", + "license": "MIT", + "optional": true + }, "node_modules/eccrypto/node_modules/nan": { "version": "2.14.0", "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", @@ -3207,40 +3142,42 @@ } }, "node_modules/ecpair": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ecpair/-/ecpair-3.0.0.tgz", - "integrity": "sha512-kf4JxjsRQoD4EBzpYjGAcR0t9i/4oAeRPtyCpKvSwyotgkc6oA4E4M0/e+kep7cXe+mgxAvoeh/jdgH9h5+Wxw==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ecpair/-/ecpair-3.0.1.tgz", + "integrity": "sha512-uz8wMFvtdr58TLrXnAesBsoMEyY8UudLOfApcyg40XfZjP+gt1xO4cuZSIkZ8hTMTQ8+ETgt7xSIV4eM7M6VNw==", "license": "MIT", "dependencies": { "uint8array-tools": "^0.0.8", - "valibot": "^0.37.0", + "valibot": "^1.2.0", "wif": "^5.0.0" }, "engines": { "node": ">=20.0.0" } }, - "node_modules/ecpair/node_modules/uint8array-tools": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/uint8array-tools/-/uint8array-tools-0.0.8.tgz", - "integrity": "sha512-xS6+s8e0Xbx++5/0L+yyexukU7pz//Yg6IHg3BKhXotg1JcYtgxVcUctQ0HxLByiJzpAkNFawz1Nz5Xadzo82g==", + "node_modules/ecpair/node_modules/base-x": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/base-x/-/base-x-5.0.1.tgz", + "integrity": "sha512-M7uio8Zt++eg3jPj+rHMfCC+IuygQHHCOU+IYsVtik6FWjuYpVt/+MRKcgsAMHh8mMFAwnB+Bs+mTrFiXjMzKg==", + "license": "MIT" + }, + "node_modules/ecpair/node_modules/bs58": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/bs58/-/bs58-6.0.0.tgz", + "integrity": "sha512-PD0wEnEYg6ijszw/u8s+iI3H17cTymlrwkKhDhPZq+Sokl3AU4htyBFTjAeNAlCCmg0f53g6ih3jATyCKftTfw==", "license": "MIT", - "engines": { - "node": ">=14.0.0" + "dependencies": { + "base-x": "^5.0.0" } }, - "node_modules/ecpair/node_modules/valibot": { - "version": "0.37.0", - "resolved": "https://registry.npmjs.org/valibot/-/valibot-0.37.0.tgz", - "integrity": "sha512-FQz52I8RXgFgOHym3XHYSREbNtkgSjF9prvMFH1nBsRyfL6SfCzoT1GuSDTlbsuPubM7/6Kbw0ZMQb8A+V+VsQ==", + "node_modules/ecpair/node_modules/bs58check": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/bs58check/-/bs58check-4.0.0.tgz", + "integrity": "sha512-FsGDOnFg9aVI9erdriULkd/JjEWONV/lQE5aYziB5PoBsXRind56lh8doIZIc9X4HoxT5x4bLjMWN1/NB8Zp5g==", "license": "MIT", - "peerDependencies": { - "typescript": ">=5" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "dependencies": { + "@noble/hashes": "^1.2.0", + "bs58": "^6.0.0" } }, "node_modules/ecpair/node_modules/wif": { @@ -3273,6 +3210,12 @@ "minimalistic-crypto-utils": "^1.0.1" } }, + "node_modules/elliptic/node_modules/bn.js": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.2.tgz", + "integrity": "sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw==", + "license": "MIT" + }, "node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -3288,31 +3231,6 @@ "node": ">= 0.8" } }, - "node_modules/encoding": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", - "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "iconv-lite": "^0.6.2" - } - }, - "node_modules/encoding/node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/end-of-stream": { "version": "1.4.5", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", @@ -3322,25 +3240,6 @@ "once": "^1.4.0" } }, - "node_modules/env-paths": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", - "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/err-code": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", - "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", - "license": "MIT", - "optional": true, - "peer": true - }, "node_modules/es-define-property": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", @@ -3434,6 +3333,15 @@ "node": ">=0.8.x" } }, + "node_modules/events-universal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/events-universal/-/events-universal-1.0.1.tgz", + "integrity": "sha512-LUd5euvbMLpwOF8m6ivPCbhQeSiYVNb8Vs0fQ8QjXo0JTkEHpz8pxdQf0gStltaPpw0Cca8b39KxvK9cfKRiAw==", + "license": "Apache-2.0", + "dependencies": { + "bare-events": "^2.7.0" + } + }, "node_modules/evp_bytestokey": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", @@ -3455,39 +3363,39 @@ } }, "node_modules/express": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", - "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", + "version": "4.22.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.22.1.tgz", + "integrity": "sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g==", "license": "MIT", "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.20.3", - "content-disposition": "0.5.4", + "body-parser": "~1.20.3", + "content-disposition": "~0.5.4", "content-type": "~1.0.4", - "cookie": "0.7.1", - "cookie-signature": "1.0.6", + "cookie": "~0.7.1", + "cookie-signature": "~1.0.6", "debug": "2.6.9", "depd": "2.0.0", "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", - "finalhandler": "1.3.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", + "finalhandler": "~1.3.1", + "fresh": "~0.5.2", + "http-errors": "~2.0.0", "merge-descriptors": "1.0.3", "methods": "~1.1.2", - "on-finished": "2.4.1", + "on-finished": "~2.4.1", "parseurl": "~1.3.3", - "path-to-regexp": "0.1.12", + "path-to-regexp": "~0.1.12", "proxy-addr": "~2.0.7", - "qs": "6.13.0", + "qs": "~6.14.0", "range-parser": "~1.2.1", "safe-buffer": "5.2.1", - "send": "0.19.0", - "serve-static": "1.16.2", + "send": "~0.19.0", + "serve-static": "~1.16.2", "setprototypeof": "1.2.0", - "statuses": "2.0.1", + "statuses": "~2.0.1", "type-is": "~1.6.18", "utils-merge": "1.0.1", "vary": "~1.1.2" @@ -3565,9 +3473,9 @@ "license": "MIT" }, "node_modules/fastq": { - "version": "1.19.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", - "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz", + "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==", "license": "ISC", "dependencies": { "reusify": "^1.0.4" @@ -3592,17 +3500,17 @@ } }, "node_modules/finalhandler": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", - "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.2.tgz", + "integrity": "sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg==", "license": "MIT", "dependencies": { "debug": "2.6.9", "encodeurl": "~2.0.0", "escape-html": "~1.0.3", - "on-finished": "2.4.1", + "on-finished": "~2.4.1", "parseurl": "~1.3.3", - "statuses": "2.0.1", + "statuses": "~2.0.2", "unpipe": "~1.0.0" }, "engines": { @@ -3675,18 +3583,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/foreground-child/node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "license": "ISC", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/forever-agent": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", @@ -3697,9 +3593,9 @@ } }, "node_modules/form-data": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz", - "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", + "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", "license": "MIT", "dependencies": { "asynckit": "^0.4.0", @@ -3736,30 +3632,6 @@ "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", "license": "MIT" }, - "node_modules/fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "license": "ISC", - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/fs-minipass/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -3790,27 +3662,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/gauge": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", - "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", - "deprecated": "This package is no longer supported.", - "license": "ISC", - "dependencies": { - "aproba": "^1.0.3 || ^2.0.0", - "color-support": "^1.1.2", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.1", - "object-assign": "^4.1.1", - "signal-exit": "^3.0.0", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "wide-align": "^1.1.2" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", @@ -3885,7 +3736,7 @@ "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", "license": "ISC", "dependencies": { "fs.realpath": "^1.0.0", @@ -3952,12 +3803,12 @@ "license": "ISC" }, "node_modules/grpc-tools": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/grpc-tools/-/grpc-tools-1.13.0.tgz", - "integrity": "sha512-7CbkJ1yWPfX0nHjbYG58BQThNhbICXBZynzCUxCb3LzX5X9B3hQbRY2STiRgIEiLILlK9fgl0z0QVGwPCdXf5g==", + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/grpc-tools/-/grpc-tools-1.13.1.tgz", + "integrity": "sha512-0sttMUxThNIkCTJq5qI0xXMz5zWqV2u3yG1kR3Sj9OokGIoyRBFjoInK9NyW7x5fH7knj48Roh1gq5xbl0VoDQ==", "hasInstallScript": true, "dependencies": { - "@mapbox/node-pre-gyp": "^1.0.5" + "@mapbox/node-pre-gyp": "^2.0.0" }, "bin": { "grpc_tools_node_protoc": "bin/protoc.js", @@ -4036,47 +3887,19 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/has-unicode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", - "license": "ISC" - }, "node_modules/hash-base": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", - "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.2.tgz", + "integrity": "sha512-Bb33KbowVTIj5s7Ked1OsqHUeCpz//tPwR+E2zJgJKo9Z5XolZ9b6bdUgjmYlwnWhoOQKoTd1TYToZGn5mAYOg==", "license": "MIT", "dependencies": { "inherits": "^2.0.4", - "readable-stream": "^3.6.0", - "safe-buffer": "^5.2.0" + "readable-stream": "^2.3.8", + "safe-buffer": "^5.2.1", + "to-buffer": "^1.2.1" }, "engines": { - "node": ">=4" - } - }, - "node_modules/hash-base/node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "license": "MIT", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/hash-base/node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "license": "MIT", - "dependencies": { - "safe-buffer": "~5.2.0" + "node": ">= 0.8" } }, "node_modules/hash.js": { @@ -4112,44 +3935,24 @@ "minimalistic-crypto-utils": "^1.0.1" } }, - "node_modules/http-cache-semantics": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", - "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==", - "license": "BSD-2-Clause", - "optional": true, - "peer": true - }, "node_modules/http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", "license": "MIT", "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" + "depd": "~2.0.0", + "inherits": "~2.0.4", + "setprototypeof": "~1.2.0", + "statuses": "~2.0.2", + "toidentifier": "~1.0.1" }, "engines": { "node": ">= 0.8" - } - }, - "node_modules/http-proxy-agent": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", - "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "@tootallnate/once": "1", - "agent-base": "6", - "debug": "4" }, - "engines": { - "node": ">= 6" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/http-signature": { @@ -4168,27 +3971,16 @@ } }, "node_modules/https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", "license": "MIT", "dependencies": { - "agent-base": "6", + "agent-base": "^7.1.2", "debug": "4" }, "engines": { - "node": ">= 6" - } - }, - "node_modules/humanize-ms": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", - "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "ms": "^2.0.0" + "node": ">= 14" } }, "node_modules/iconv-lite": { @@ -4239,36 +4031,6 @@ "dev": true, "license": "ISC" }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/infer-owner": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", - "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", - "license": "ISC", - "optional": true, - "peer": true - }, "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -4292,17 +4054,6 @@ "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", "license": "ISC" }, - "node_modules/ip-address": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.0.1.tgz", - "integrity": "sha512-NWv9YLW4PoW2B7xtzaS3NCot75m6nK7Icdv0o3lfMceJVRfSoQwqD4wEH5rLwoKJwUiZ/rfpiVBhnaF0FK4HoA==", - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">= 12" - } - }, "node_modules/ipaddr.js": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", @@ -4367,14 +4118,6 @@ "node": ">=0.10.0" } }, - "node_modules/is-lambda": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", - "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", - "license": "MIT", - "optional": true, - "peer": true - }, "node_modules/is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", @@ -4418,9 +4161,9 @@ "license": "MIT" }, "node_modules/isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", "license": "MIT" }, "node_modules/isexe": { @@ -4436,12 +4179,12 @@ "license": "MIT" }, "node_modules/jackspeak": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.1.1.tgz", - "integrity": "sha512-zptv57P3GpL+O0I7VdMJNBZCu+BPHVQUk55Ft8/QCJjTVxrnJHuVuX/0Bl2A6/+2oyR/ZMEuFKwmzqqZ/U5nPQ==", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.2.3.tgz", + "integrity": "sha512-ykkVRwrYvFm1nb2AJfKKYPr0emF6IiXDYUaFx4Zn9ZuIH7MrzEZ3sD5RlqGXNRpHtvUHJyOnCEFxOlNDtGo7wg==", "license": "BlueOak-1.0.0", "dependencies": { - "@isaacs/cliui": "^8.0.2" + "@isaacs/cliui": "^9.0.0" }, "engines": { "node": "20 || >=22" @@ -4484,12 +4227,12 @@ "license": "ISC" }, "node_modules/jsonwebtoken": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", - "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==", + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.3.tgz", + "integrity": "sha512-MT/xP0CrubFRNLNKvxJ2BYfy53Zkm++5bX9dtuPbqAeQpTVe0MQTFhao8+Cp//EmJp244xt6Drw/GVEGCUj40g==", "license": "MIT", "dependencies": { - "jws": "^3.2.2", + "jws": "^4.0.1", "lodash.includes": "^4.3.0", "lodash.isboolean": "^3.0.3", "lodash.isinteger": "^4.0.4", @@ -4506,9 +4249,9 @@ } }, "node_modules/jsonwebtoken/node_modules/semver": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", - "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -4533,9 +4276,9 @@ } }, "node_modules/jwa": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.2.tgz", - "integrity": "sha512-eeH5JO+21J78qMvTIDdBXidBd6nG2kZjg5Ohz/1fpa28Z4CcsWUzJ1ZZyFq/3z3N17aZy+ZuBoHljASbL1WfOw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.1.tgz", + "integrity": "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==", "license": "MIT", "dependencies": { "buffer-equal-constant-time": "^1.0.1", @@ -4544,12 +4287,12 @@ } }, "node_modules/jws": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", - "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.1.tgz", + "integrity": "sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==", "license": "MIT", "dependencies": { - "jwa": "^1.4.1", + "jwa": "^2.0.1", "safe-buffer": "^5.0.1" } }, @@ -4565,42 +4308,6 @@ "node": ">= 0.6.3" } }, - "node_modules/lazystream/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "license": "MIT" - }, - "node_modules/lazystream/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "license": "MIT", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/lazystream/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "license": "MIT" - }, - "node_modules/lazystream/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "license": "MIT", - "dependencies": { - "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", @@ -4657,6 +4364,16 @@ "safe-buffer": "^5.0.1" } }, + "node_modules/liquidjs-lib/node_modules/bip66": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/bip66/-/bip66-1.1.5.tgz", + "integrity": "sha512-nemMHz95EmS38a26XbbdxIYj5csHd3RMP3H5bwQknX0WYHF01qhpufP42mLOwVICuH2JmhIhXiWs89MfUGL7Xw==", + "license": "MIT", + "peer": true, + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, "node_modules/liquidjs-lib/node_modules/bs58": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", @@ -4694,20 +4411,10 @@ "node": ">=8.0.0" } }, - "node_modules/liquidjs-lib/node_modules/varuint-bitcoin": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/varuint-bitcoin/-/varuint-bitcoin-1.1.2.tgz", - "integrity": "sha512-4EVb+w4rx+YfVM32HQX42AbbT7/1f5zwAYhIujKXKk8NQK+JfRVl3pqT3hjNn/L+RstigmGGKVwHA/P0wgITZw==", - "license": "MIT", - "peer": true, - "dependencies": { - "safe-buffer": "^5.1.1" - } - }, "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "version": "4.17.23", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz", + "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==", "license": "MIT" }, "node_modules/lodash.camelcase": { @@ -4774,38 +4481,14 @@ } }, "node_modules/lru-cache": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.1.0.tgz", - "integrity": "sha512-QIXZUBJUx+2zHUdQujWejBkcD9+cs94tLn0+YL8UrCh+D5sCXZ4c7LaEH48pNwRY3MLDgqUFyhlCyjJPf1WP0A==", - "license": "ISC", + "version": "11.2.6", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.6.tgz", + "integrity": "sha512-ESL2CrkS/2wTPfuend7Zhkzo2u0daGJ/A2VucJOgQ/C48S/zB8MMeMHSGKYpXhIjbPxfuezITkaBH1wqv00DDQ==", + "license": "BlueOak-1.0.0", "engines": { "node": "20 || >=22" } }, - "node_modules/make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "license": "MIT", - "dependencies": { - "semver": "^6.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/make-dir/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, "node_modules/make-error": { "version": "1.3.6", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", @@ -4813,63 +4496,6 @@ "devOptional": true, "license": "ISC" }, - "node_modules/make-fetch-happen": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz", - "integrity": "sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg==", - "license": "ISC", - "optional": true, - "peer": true, - "dependencies": { - "agentkeepalive": "^4.1.3", - "cacache": "^15.2.0", - "http-cache-semantics": "^4.1.0", - "http-proxy-agent": "^4.0.1", - "https-proxy-agent": "^5.0.0", - "is-lambda": "^1.0.1", - "lru-cache": "^6.0.0", - "minipass": "^3.1.3", - "minipass-collect": "^1.0.2", - "minipass-fetch": "^1.3.2", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.2", - "promise-retry": "^2.0.1", - "socks-proxy-agent": "^6.0.0", - "ssri": "^8.0.0" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/make-fetch-happen/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "license": "ISC", - "optional": true, - "peer": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/make-fetch-happen/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "license": "ISC", - "optional": true, - "peer": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/math-intrinsics": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", @@ -5018,182 +4644,24 @@ } }, "node_modules/minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", "license": "ISC", "engines": { - "node": ">=8" - } - }, - "node_modules/minipass-collect": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", - "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", - "license": "ISC", - "optional": true, - "peer": true, - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/minipass-collect/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "license": "ISC", - "optional": true, - "peer": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minipass-fetch": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-1.4.1.tgz", - "integrity": "sha512-CGH1eblLq26Y15+Azk7ey4xh0J/XfJfrCox5LDJiKqI2Q2iwOLOKrlmIaODiSQS8d18jalF6y2K2ePUm0CmShw==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "minipass": "^3.1.0", - "minipass-sized": "^1.0.3", - "minizlib": "^2.0.0" - }, - "engines": { - "node": ">=8" - }, - "optionalDependencies": { - "encoding": "^0.1.12" - } - }, - "node_modules/minipass-fetch/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "license": "ISC", - "optional": true, - "peer": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minipass-flush": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", - "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", - "license": "ISC", - "optional": true, - "peer": true, - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/minipass-flush/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "license": "ISC", - "optional": true, - "peer": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minipass-pipeline": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", - "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", - "license": "ISC", - "optional": true, - "peer": true, - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minipass-pipeline/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "license": "ISC", - "optional": true, - "peer": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minipass-sized": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", - "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", - "license": "ISC", - "optional": true, - "peer": true, - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minipass-sized/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "license": "ISC", - "optional": true, - "peer": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" + "node": ">=16 || 14 >=14.17" } }, "node_modules/minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.1.0.tgz", + "integrity": "sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==", "license": "MIT", "dependencies": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" + "minipass": "^7.1.2" }, "engines": { - "node": ">= 8" - } - }, - "node_modules/minizlib/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" + "node": ">= 18" } }, "node_modules/mkdirp": { @@ -5249,7 +4717,7 @@ "version": "6.0.4", "resolved": "https://registry.npmjs.org/glob/-/glob-6.0.4.tgz", "integrity": "sha512-MKZeRNyYZAVVVG1oZeLaWie1uweH40m9AZwIwxyPbTSX4hHrVYSzLg0Ro5Z5R7XKkIX+Cc6oD1rqeDJnwsB8/A==", - "deprecated": "Glob versions prior to v9 are no longer supported", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", "license": "ISC", "optional": true, "dependencies": { @@ -5291,9 +4759,9 @@ } }, "node_modules/nan": { - "version": "2.23.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.23.0.tgz", - "integrity": "sha512-1UxuyYGdoQHcGg87Lkqm3FzefucTa0NAiOcuRsDmysep3c1LVCRK2krrUDafMWtjSG04htvAmvg96+SDknOmgQ==", + "version": "2.25.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.25.0.tgz", + "integrity": "sha512-0M90Ag7Xn5KMLLZ7zliPWP3rT90P6PN+IzVFS0VqmnPktBk3700xUVv8Ikm9EUaUE5SDWdp/BIxdENzVznpm1g==", "license": "MIT", "optional": true }, @@ -5323,9 +4791,9 @@ } }, "node_modules/node-abi": { - "version": "3.75.0", - "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.75.0.tgz", - "integrity": "sha512-OhYaY5sDsIka7H7AtijtI9jwGYLyl29eQn/W623DiN/MIv5sUqc4g7BIDThX+gb7di9f6xK02nkp8sdfFWZLTg==", + "version": "3.87.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.87.0.tgz", + "integrity": "sha512-+CGM1L1CgmtheLcBuleyYOn7NWPVu0s0EJH2C4puxgEZb9h8QpR9G2dBfZJOAUhi7VQxuBPMd0hiISWcTyiYyQ==", "license": "MIT", "dependencies": { "semver": "^7.3.5" @@ -5335,9 +4803,9 @@ } }, "node_modules/node-abi/node_modules/semver": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", - "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -5372,32 +4840,6 @@ } } }, - "node_modules/node-gyp": { - "version": "8.4.1", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-8.4.1.tgz", - "integrity": "sha512-olTJRgUtAb/hOXG0E93wZDs5YiJlgbXxTwQAFHyNlRsXQnYzUaF2aGgujZbw+hR8aF4ZG/rST57bWMWD16jr9w==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "env-paths": "^2.2.0", - "glob": "^7.1.4", - "graceful-fs": "^4.2.6", - "make-fetch-happen": "^9.1.0", - "nopt": "^5.0.0", - "npmlog": "^6.0.0", - "rimraf": "^3.0.2", - "semver": "^7.3.5", - "tar": "^6.1.2", - "which": "^2.0.2" - }, - "bin": { - "node-gyp": "bin/node-gyp.js" - }, - "engines": { - "node": ">= 10.12.0" - } - }, "node_modules/node-gyp-build": { "version": "4.8.4", "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.4.tgz", @@ -5409,103 +4851,6 @@ "node-gyp-build-test": "build-test.js" } }, - "node_modules/node-gyp/node_modules/are-we-there-yet": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz", - "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==", - "deprecated": "This package is no longer supported.", - "license": "ISC", - "optional": true, - "peer": true, - "dependencies": { - "delegates": "^1.0.0", - "readable-stream": "^3.6.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/node-gyp/node_modules/gauge": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz", - "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", - "deprecated": "This package is no longer supported.", - "license": "ISC", - "optional": true, - "peer": true, - "dependencies": { - "aproba": "^1.0.3 || ^2.0.0", - "color-support": "^1.1.3", - "console-control-strings": "^1.1.0", - "has-unicode": "^2.0.1", - "signal-exit": "^3.0.7", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "wide-align": "^1.1.5" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/node-gyp/node_modules/npmlog": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz", - "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==", - "deprecated": "This package is no longer supported.", - "license": "ISC", - "optional": true, - "peer": true, - "dependencies": { - "are-we-there-yet": "^3.0.0", - "console-control-strings": "^1.1.0", - "gauge": "^4.0.3", - "set-blocking": "^2.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/node-gyp/node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/node-gyp/node_modules/semver": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", - "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", - "license": "ISC", - "optional": true, - "peer": true, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/node-gyp/node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, "node_modules/nodemon": { "version": "2.0.22", "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.22.tgz", @@ -5555,19 +4900,43 @@ "readable-stream": "~1.0.31" } }, + "node_modules/noms/node_modules/isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==", + "license": "MIT" + }, + "node_modules/noms/node_modules/readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha512-ok1qVCJuRkNmvebYikljxJA/UEsKwLl2nI1OmaqAu4/UE+h0wKCHok4XkL/gvi39OacXvw59RJUOFUkDib2rHg==", + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "node_modules/noms/node_modules/string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==", + "license": "MIT" + }, "node_modules/nopt": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", - "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-8.1.0.tgz", + "integrity": "sha512-ieGu42u/Qsa4TFktmaKEwM6MQH0pOWnaB3htzh0JRtx84+Mebc0cbZYN5bC+6WTZ4+77xrL9Pn5m7CV6VIkV7A==", "license": "ISC", "dependencies": { - "abbrev": "1" + "abbrev": "^3.0.0" }, "bin": { "nopt": "bin/nopt.js" }, "engines": { - "node": ">=6" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/normalize-path": { @@ -5580,17 +4949,17 @@ } }, "node_modules/nostr-tools": { - "version": "2.16.2", - "resolved": "https://registry.npmjs.org/nostr-tools/-/nostr-tools-2.16.2.tgz", - "integrity": "sha512-ZxH9EbSt5ypURZj2TGNJxZd0Omb5ag5KZSu8IyJMCdLyg2KKz+2GA0sP/cSawCQEkyviIN4eRT4G2gB/t9lMRw==", + "version": "2.23.1", + "resolved": "https://registry.npmjs.org/nostr-tools/-/nostr-tools-2.23.1.tgz", + "integrity": "sha512-Q5SJ1omrseBFXtLwqDhufpFLA6vX3rS/IuBCc974qaYX6YKGwEPxa/ZsyxruUOr+b+5EpWL2hFmCB5AueYrfBw==", "license": "Unlicense", "dependencies": { - "@noble/ciphers": "^0.5.1", - "@noble/curves": "1.2.0", - "@noble/hashes": "1.3.1", - "@scure/base": "1.1.1", - "@scure/bip32": "1.3.1", - "@scure/bip39": "1.2.1", + "@noble/ciphers": "2.1.1", + "@noble/curves": "2.0.1", + "@noble/hashes": "2.0.1", + "@scure/base": "2.0.0", + "@scure/bip32": "2.0.1", + "@scure/bip39": "2.0.1", "nostr-wasm": "0.1.0" }, "peerDependencies": { @@ -5603,28 +4972,25 @@ } }, "node_modules/nostr-tools/node_modules/@noble/hashes": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.1.tgz", - "integrity": "sha512-EbqwksQwz9xDRGfDST86whPBgM65E0OH/pCgqW0GBVzO22bNE+NuIbeTb714+IfSjU3aRk47EUvXIb5bTsenKA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-2.0.1.tgz", + "integrity": "sha512-XlOlEbQcE9fmuXxrVTXCTlG2nlRXa9Rj3rr5Ue/+tX+nmkgbX720YHh0VR3hBF9xDvwnb8D2shVGOwNx+ulArw==", "license": "MIT", "engines": { - "node": ">= 16" + "node": ">= 20.19.0" }, "funding": { "url": "https://paulmillr.com/funding/" } }, "node_modules/nostr-tools/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" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@scure/base/-/base-2.0.0.tgz", + "integrity": "sha512-3E1kpuZginKkek01ovG8krQ0Z44E3DHPjc5S2rjJw9lZn3KSQOs8S7wqikF/AH7iRanHypj85uGyxk0XAyC37w==", + "license": "MIT", + "funding": { + "url": "https://paulmillr.com/funding/" + } }, "node_modules/nostr-wasm": { "version": "0.1.0", @@ -5632,19 +4998,6 @@ "integrity": "sha512-78BTryCLcLYv96ONU8Ws3Q1JzjlAt+43pWQhIl86xZmWeegYCNLPml7yQ+gG3vR6V5h4XGj+TxO+SS5dsThQIA==", "license": "MIT" }, - "node_modules/npmlog": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", - "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", - "deprecated": "This package is no longer supported.", - "license": "ISC", - "dependencies": { - "are-we-there-yet": "^2.0.0", - "console-control-strings": "^1.1.0", - "gauge": "^3.0.0", - "set-blocking": "^2.0.0" - } - }, "node_modules/oauth-sign": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", @@ -5696,23 +5049,6 @@ "wrappy": "1" } }, - "node_modules/p-map": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "aggregate-error": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/package-json-from-dist": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", @@ -5747,9 +5083,9 @@ } }, "node_modules/path-scurry": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.0.tgz", - "integrity": "sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.1.tgz", + "integrity": "sha512-oWyT4gICAu+kaA7QWk/jvCHWarMKNs6pXOGWKDTr7cw4IGcUbW+PeTfbaQiLGheFRpjo6O9J0PmyMfQPjH71oA==", "license": "BlueOak-1.0.0", "dependencies": { "lru-cache": "^11.0.0", @@ -5762,15 +5098,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/path-scurry/node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "license": "ISC", - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, "node_modules/path-to-regexp": { "version": "0.1.12", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", @@ -5808,14 +5135,14 @@ "license": "MIT" }, "node_modules/pg": { - "version": "8.16.3", - "resolved": "https://registry.npmjs.org/pg/-/pg-8.16.3.tgz", - "integrity": "sha512-enxc1h0jA/aq5oSDMvqyW3q89ra6XIIDZgCX9vkMrnz5DFTw/Ny3Li2lFQ+pt3L6MCgm/5o2o8HW9hiJji+xvw==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/pg/-/pg-8.18.0.tgz", + "integrity": "sha512-xqrUDL1b9MbkydY/s+VZ6v+xiMUmOUk7SS9d/1kpyQxoJ6U9AO1oIJyUWVZojbfe5Cc/oluutcgFG4L9RDP1iQ==", "license": "MIT", "dependencies": { - "pg-connection-string": "^2.9.1", - "pg-pool": "^3.10.1", - "pg-protocol": "^1.10.3", + "pg-connection-string": "^2.11.0", + "pg-pool": "^3.11.0", + "pg-protocol": "^1.11.0", "pg-types": "2.2.0", "pgpass": "1.0.5" }, @@ -5823,7 +5150,7 @@ "node": ">= 16.0.0" }, "optionalDependencies": { - "pg-cloudflare": "^1.2.7" + "pg-cloudflare": "^1.3.0" }, "peerDependencies": { "pg-native": ">=3.0.1" @@ -5835,16 +5162,16 @@ } }, "node_modules/pg-cloudflare": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.2.7.tgz", - "integrity": "sha512-YgCtzMH0ptvZJslLM1ffsY4EuGaU0cx4XSdXLRFae8bPP4dS5xL1tNB3k2o/N64cHJpwU7dxKli/nZ2lUa5fLg==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.3.0.tgz", + "integrity": "sha512-6lswVVSztmHiRtD6I8hw4qP/nDm1EJbKMRhf3HCYaqud7frGysPv7FYJ5noZQdhQtN2xJnimfMtvQq21pdbzyQ==", "license": "MIT", "optional": true }, "node_modules/pg-connection-string": { - "version": "2.9.1", - "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.9.1.tgz", - "integrity": "sha512-nkc6NpDcvPVpZXxrreI/FOtX3XemeLl8E0qFr6F2Lrm/I8WOnaWNhIPK2Z7OHpw7gh5XJThi6j6ppgNoaT1w4w==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.11.0.tgz", + "integrity": "sha512-kecgoJwhOpxYU21rZjULrmrBJ698U2RxXofKVzOn5UDj61BPj/qMb7diYUR1nLScCDbrztQFl1TaQZT0t1EtzQ==", "license": "MIT" }, "node_modules/pg-int8": { @@ -5857,18 +5184,18 @@ } }, "node_modules/pg-pool": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.10.1.tgz", - "integrity": "sha512-Tu8jMlcX+9d8+QVzKIvM/uJtp07PKr82IUOYEphaWcoBhIYkoHpLXN3qO59nAI11ripznDsEzEv8nUxBVWajGg==", + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.11.0.tgz", + "integrity": "sha512-MJYfvHwtGp870aeusDh+hg9apvOe2zmpZJpyt+BMtzUWlVqbhFmMK6bOBXLBUPd7iRtIF9fZplDc7KrPN3PN7w==", "license": "MIT", "peerDependencies": { "pg": ">=8.0" } }, "node_modules/pg-protocol": { - "version": "1.10.3", - "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.10.3.tgz", - "integrity": "sha512-6DIBgBQaTKDJyxnXaLiLR8wBpQQcGWuAESkRBX/t6OwA8YsqP+iVSiond2EDy6Y/dsGk8rh/jtax3js5NeV7JQ==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.11.0.tgz", + "integrity": "sha512-pfsxk2M9M3BuGgDOfuy37VNRRX3jmKgMjcvAcWqNDpZSf4cUmv8HSOl5ViRQFsfARFn0KuUQTgLxVMbNq5NW3g==", "license": "MIT" }, "node_modules/pg-types": { @@ -5927,9 +5254,9 @@ } }, "node_modules/postgres-bytea": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz", - "integrity": "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.1.tgz", + "integrity": "sha512-5+5HqXnsZPE65IJZSMkZtURARZelel2oXUEO8rH83VS/hxH5vv1uHquPg5wZs8yMAfdv971IU+kcPUczi7NVBQ==", "license": "MIT", "engines": { "node": ">=0.10.0" @@ -5997,29 +5324,6 @@ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", "license": "MIT" }, - "node_modules/promise-inflight": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", - "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==", - "license": "ISC", - "optional": true, - "peer": true - }, - "node_modules/promise-retry": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", - "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "err-code": "^2.0.2", - "retry": "^0.12.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/protobufjs": { "version": "7.5.4", "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.5.4.tgz", @@ -6110,12 +5414,12 @@ } }, "node_modules/qs": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", - "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "version": "6.14.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.2.tgz", + "integrity": "sha512-V/yCWTTF7VJ9hIh18Ugr2zhJMP01MY7c5kh4J870L7imm6/DIzBsNLTXzMwUA3yZ5b/KBqLx8Kp3uRvd7xSe3Q==", "license": "BSD-3-Clause", "dependencies": { - "side-channel": "^1.0.6" + "side-channel": "^1.1.0" }, "engines": { "node": ">=0.6" @@ -6164,15 +5468,15 @@ } }, "node_modules/raw-body": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", - "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.3.tgz", + "integrity": "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==", "license": "MIT", "dependencies": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" + "bytes": "~3.1.2", + "http-errors": "~2.0.1", + "iconv-lite": "~0.4.24", + "unpipe": "~1.0.0" }, "engines": { "node": ">= 0.8" @@ -6194,17 +5498,26 @@ } }, "node_modules/readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha512-ok1qVCJuRkNmvebYikljxJA/UEsKwLl2nI1OmaqAu4/UE+h0wKCHok4XkL/gvi39OacXvw59RJUOFUkDib2rHg==", + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", "license": "MIT", "dependencies": { "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" } }, + "node_modules/readable-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "license": "MIT" + }, "node_modules/readdir-glob": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/readdir-glob/-/readdir-glob-1.1.3.tgz", @@ -6301,9 +5614,9 @@ } }, "node_modules/request/node_modules/qs": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", - "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==", + "version": "6.5.5", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.5.tgz", + "integrity": "sha512-mzR4sElr1bfCaPJe7m8ilJ6ZXdDaGoObcYR0ZHSsktM/Lt21MVHj5De30GQH2eiZ1qGRTO7LCAzQsUeXTNexWQ==", "license": "BSD-3-Clause", "engines": { "node": ">=0.6" @@ -6328,17 +5641,6 @@ "node": ">=0.10.0" } }, - "node_modules/retry": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", - "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">= 4" - } - }, "node_modules/reusify": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", @@ -6366,13 +5668,16 @@ } }, "node_modules/ripemd160": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", - "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.3.tgz", + "integrity": "sha512-5Di9UC0+8h1L6ZD2d7awM7E/T4uA1fJRlx6zk/NvdCCVEoAnFqvHmCuNeIKoCeIixBX/q8uM+6ycDvF8woqosA==", "license": "MIT", "dependencies": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1" + "hash-base": "^3.1.2", + "inherits": "^2.0.4" + }, + "engines": { + "node": ">= 0.8" } }, "node_modules/run-parallel": { @@ -6455,6 +5760,12 @@ "node": ">=18.0.0" } }, + "node_modules/secp256k1/node_modules/bn.js": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.2.tgz", + "integrity": "sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw==", + "license": "MIT" + }, "node_modules/secp256k1/node_modules/elliptic": { "version": "6.6.1", "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.6.1.tgz", @@ -6480,24 +5791,24 @@ } }, "node_modules/send": { - "version": "0.19.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", - "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.2.tgz", + "integrity": "sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==", "license": "MIT", "dependencies": { "debug": "2.6.9", "depd": "2.0.0", "destroy": "1.2.0", - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", + "fresh": "~0.5.2", + "http-errors": "~2.0.1", "mime": "1.6.0", "ms": "2.1.3", - "on-finished": "2.4.1", + "on-finished": "~2.4.1", "range-parser": "~1.2.1", - "statuses": "2.0.1" + "statuses": "~2.0.2" }, "engines": { "node": ">= 0.8.0" @@ -6518,36 +5829,21 @@ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "license": "MIT" }, - "node_modules/send/node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, "node_modules/serve-static": { - "version": "1.16.2", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", - "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", + "version": "1.16.3", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.3.tgz", + "integrity": "sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA==", "license": "MIT", "dependencies": { "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "parseurl": "~1.3.3", - "send": "0.19.0" + "send": "~0.19.1" }, "engines": { "node": ">= 0.8.0" } }, - "node_modules/set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", - "license": "ISC" - }, "node_modules/set-function-length": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", @@ -6685,10 +5981,16 @@ } }, "node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "license": "ISC" + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } }, "node_modules/simple-concat": { "version": "1.0.1", @@ -6792,50 +6094,6 @@ "license": "MIT", "peer": true }, - "node_modules/smart-buffer": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", - "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">= 6.0.0", - "npm": ">= 3.0.0" - } - }, - "node_modules/socks": { - "version": "2.8.7", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.7.tgz", - "integrity": "sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "ip-address": "^10.0.1", - "smart-buffer": "^4.2.0" - }, - "engines": { - "node": ">= 10.0.0", - "npm": ">= 3.0.0" - } - }, - "node_modules/socks-proxy-agent": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-6.2.1.tgz", - "integrity": "sha512-a6KW9G+6B3nWZ1yB8G7pJwL3ggLy1uTzKAgCb7ttblwqdz9fMGJUuTy3uFzEP48FAs9FLILlmzDlE2JJhVQaXQ==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "agent-base": "^6.0.2", - "debug": "^4.3.3", - "socks": "^2.6.2" - }, - "engines": { - "node": ">= 10" - } - }, "node_modules/split2": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", @@ -6861,40 +6119,6 @@ "node": ">=14" } }, - "node_modules/sqlite3": { - "version": "5.1.7", - "resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-5.1.7.tgz", - "integrity": "sha512-GGIyOiFaG+TUra3JIfkI/zGP8yZYLPQ0pl1bH+ODjiX57sPhrLU5sQJn1y9bDKZUFYkX1crlrPfSYt0BKKdkog==", - "hasInstallScript": true, - "license": "BSD-3-Clause", - "optional": true, - "peer": true, - "dependencies": { - "bindings": "^1.5.0", - "node-addon-api": "^7.0.0", - "prebuild-install": "^7.1.1", - "tar": "^6.1.11" - }, - "optionalDependencies": { - "node-gyp": "8.x" - }, - "peerDependencies": { - "node-gyp": "8.x" - }, - "peerDependenciesMeta": { - "node-gyp": { - "optional": true - } - } - }, - "node_modules/sqlite3/node_modules/node-addon-api": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", - "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", - "license": "MIT", - "optional": true, - "peer": true - }, "node_modules/sshpk": { "version": "1.18.0", "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.18.0.tgz", @@ -6920,43 +6144,15 @@ "node": ">=0.10.0" } }, - "node_modules/ssri": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", - "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==", - "license": "ISC", - "optional": true, - "peer": true, - "dependencies": { - "minipass": "^3.1.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/ssri/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "license": "ISC", - "optional": true, - "peer": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/standard-error": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/standard-error/-/standard-error-1.1.0.tgz", "integrity": "sha512-4v7qzU7oLJfMI5EltUSHCaaOd65J6S4BqKRWgzMi4EYaE5fvNabPxmAPGdxpGXqrcWjhDGI/H09CIdEuUOUeXg==" }, "node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", "license": "MIT", "engines": { "node": ">= 0.8" @@ -6969,22 +6165,29 @@ "license": "MIT" }, "node_modules/streamx": { - "version": "2.22.1", - "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.22.1.tgz", - "integrity": "sha512-znKXEBxfatz2GBNK02kRnCXjV+AA4kjZIUxeWSr3UGirZMJfTE9uiwKHobnbgxWyL/JWro8tTq+vOqAK1/qbSA==", + "version": "2.23.0", + "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.23.0.tgz", + "integrity": "sha512-kn+e44esVfn2Fa/O0CPFcex27fjIL6MkVae0Mm6q+E6f0hWv578YCERbv+4m02cjxvDsPKLnmxral/rR6lBMAg==", "license": "MIT", "dependencies": { + "events-universal": "^1.0.0", "fast-fifo": "^1.3.2", "text-decoder": "^1.1.0" - }, - "optionalDependencies": { - "bare-events": "^2.2.0" } }, "node_modules/string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "license": "MIT" }, "node_modules/string-width": { @@ -7064,26 +6267,25 @@ } }, "node_modules/tar": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", - "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", - "license": "ISC", + "version": "7.5.7", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.7.tgz", + "integrity": "sha512-fov56fJiRuThVFXD6o6/Q354S7pnWMJIVlDBYijsTNx6jKSE4pvrDTs6lUnmGvNyfJwFQQwWy3owKz1ucIhveQ==", + "license": "BlueOak-1.0.0", "dependencies": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^5.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" + "@isaacs/fs-minipass": "^4.0.0", + "chownr": "^3.0.0", + "minipass": "^7.1.2", + "minizlib": "^3.1.0", + "yallist": "^5.0.0" }, "engines": { - "node": ">=10" + "node": ">=18" } }, "node_modules/tar-fs": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.3.tgz", - "integrity": "sha512-090nwYJDmlhwFwEW3QQl+vaNnxsO2yVsd45eTKRBzSzu+hlb1w2K9inVq5b0ngXuLVqQ4ApvsUHHnu/zQNkWAg==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.4.tgz", + "integrity": "sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ==", "license": "MIT", "dependencies": { "chownr": "^1.1.1", @@ -7128,19 +6330,10 @@ "node": ">= 6" } }, - "node_modules/tar-stream/node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "license": "MIT", - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, "node_modules/text-decoder": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.2.3.tgz", - "integrity": "sha512-3/o9z3X0X0fTupwsYvR03pJ/DjWuqqrfwBgTQzdWDiQSm9KitAyz/9WqsT2JQW7KV2m+bC2ol/zqpW37NHxLaA==", + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.2.6.tgz", + "integrity": "sha512-27FeW5GQFDfw0FpwMQhMagB7BztOOlmjcSRi97t2oplhKVTZtp0DZbSegSaXS5IIC6mxMvBG4AR1Sgc6BX3CQg==", "license": "Apache-2.0", "dependencies": { "b4a": "^1.6.4" @@ -7156,42 +6349,6 @@ "xtend": "~4.0.1" } }, - "node_modules/through2/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "license": "MIT" - }, - "node_modules/through2/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "license": "MIT", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/through2/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "license": "MIT" - }, - "node_modules/through2/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "license": "MIT", - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, "node_modules/tiny-secp256k1": { "version": "2.2.4", "resolved": "https://registry.npmjs.org/tiny-secp256k1/-/tiny-secp256k1-2.2.4.tgz", @@ -7214,9 +6371,9 @@ } }, "node_modules/to-buffer": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.2.1.tgz", - "integrity": "sha512-tB82LpAIWjhLYbqjx3X4zEeHN6M8CiuOEy2JY8SEQVdYRe3CCHOFaqrBW1doLDrfpWhplcW7BL+bO3/6S3pcDQ==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.2.2.tgz", + "integrity": "sha512-db0E3UJjcFhpDhAF4tLo03oli3pwl3dbnzXOUIlRKrp+ldk/VUxzpWYZENsw2SZiuBjHAk7DfB0VU7NKdpb6sw==", "license": "MIT", "dependencies": { "isarray": "^2.0.5", @@ -7441,22 +6598,23 @@ "license": "MIT" }, "node_modules/typeorm": { - "version": "0.3.26", - "resolved": "https://registry.npmjs.org/typeorm/-/typeorm-0.3.26.tgz", - "integrity": "sha512-o2RrBNn3lczx1qv4j+JliVMmtkPSqEGpG0UuZkt9tCfWkoXKu8MZnjvp2GjWPll1SehwemQw6xrbVRhmOglj8Q==", + "version": "0.3.28", + "resolved": "https://registry.npmjs.org/typeorm/-/typeorm-0.3.28.tgz", + "integrity": "sha512-6GH7wXhtfq2D33ZuRXYwIsl/qM5685WZcODZb7noOOcRMteM9KF2x2ap3H0EBjnSV0VO4gNAfJT5Ukp0PkOlvg==", "license": "MIT", "dependencies": { "@sqltools/formatter": "^1.2.5", - "ansis": "^3.17.0", + "ansis": "^4.2.0", "app-root-path": "^3.1.0", "buffer": "^6.0.3", - "dayjs": "^1.11.13", - "debug": "^4.4.0", - "dedent": "^1.6.0", - "dotenv": "^16.4.7", - "glob": "^10.4.5", - "sha.js": "^2.4.11", - "sql-highlight": "^6.0.0", + "dayjs": "^1.11.19", + "debug": "^4.4.3", + "dedent": "^1.7.0", + "dotenv": "^16.6.1", + "glob": "^10.5.0", + "reflect-metadata": "^0.2.2", + "sha.js": "^2.4.12", + "sql-highlight": "^6.1.0", "tslib": "^2.8.1", "uuid": "^11.1.0", "yargs": "^17.7.2" @@ -7473,19 +6631,18 @@ "url": "https://opencollective.com/typeorm" }, "peerDependencies": { - "@google-cloud/spanner": "^5.18.0 || ^6.0.0 || ^7.0.0", + "@google-cloud/spanner": "^5.18.0 || ^6.0.0 || ^7.0.0 || ^8.0.0", "@sap/hana-client": "^2.14.22", "better-sqlite3": "^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0 || ^12.0.0", "ioredis": "^5.0.4", "mongodb": "^5.8.0 || ^6.0.0", - "mssql": "^9.1.1 || ^10.0.1 || ^11.0.1", + "mssql": "^9.1.1 || ^10.0.0 || ^11.0.0 || ^12.0.0", "mysql2": "^2.2.5 || ^3.0.1", "oracledb": "^6.3.0", "pg": "^8.5.1", "pg-native": "^3.0.0", "pg-query-stream": "^4.0.0", "redis": "^3.1.1 || ^4.0.0 || ^5.0.14", - "reflect-metadata": "^0.1.14 || ^0.2.0", "sql.js": "^1.4.0", "sqlite3": "^5.0.3", "ts-node": "^10.7.0", @@ -7542,6 +6699,47 @@ } } }, + "node_modules/typeorm/node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "license": "ISC", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/typeorm/node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/typeorm/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, "node_modules/typeorm/node_modules/brace-expansion": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", @@ -7575,10 +6773,17 @@ "ieee754": "^1.2.1" } }, + "node_modules/typeorm/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "license": "MIT" + }, "node_modules/typeorm/node_modules/glob": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", "license": "ISC", "dependencies": { "foreground-child": "^3.1.0", @@ -7631,15 +6836,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/typeorm/node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "license": "ISC", - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, "node_modules/typeorm/node_modules/path-scurry": { "version": "1.11.1", "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", @@ -7656,6 +6852,38 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/typeorm/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typeorm/node_modules/strip-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", + "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, "node_modules/typeorm/node_modules/uuid": { "version": "11.1.0", "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.0.tgz", @@ -7669,6 +6897,23 @@ "uuid": "dist/esm/bin/uuid" } }, + "node_modules/typeorm/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/typescript": { "version": "5.5.4", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", @@ -7682,6 +6927,15 @@ "node": ">=14.17" } }, + "node_modules/uint8array-tools": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/uint8array-tools/-/uint8array-tools-0.0.8.tgz", + "integrity": "sha512-xS6+s8e0Xbx++5/0L+yyexukU7pz//Yg6IHg3BKhXotg1JcYtgxVcUctQ0HxLByiJzpAkNFawz1Nz5Xadzo82g==", + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/undefsafe": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", @@ -7689,28 +6943,6 @@ "dev": true, "license": "MIT" }, - "node_modules/unique-filename": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", - "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", - "license": "ISC", - "optional": true, - "peer": true, - "dependencies": { - "unique-slug": "^2.0.0" - } - }, - "node_modules/unique-slug": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", - "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", - "license": "ISC", - "optional": true, - "peer": true, - "dependencies": { - "imurmurhash": "^0.1.4" - } - }, "node_modules/unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", @@ -7747,21 +6979,6 @@ "pct-encode": "~1.0.0" } }, - "node_modules/utf-8-validate": { - "version": "5.0.10", - "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.10.tgz", - "integrity": "sha512-Z6czzLq4u8fPOyx7TU6X3dvUZVvoJmxSQ+IcrlmagKhilxlhZgxPK6C5Jqbkw1IDUmFTM+cz9QDnnLTwDz/2gQ==", - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "node-gyp-build": "^4.3.0" - }, - "engines": { - "node": ">=6.14.2" - } - }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -7793,22 +7010,27 @@ "devOptional": true, "license": "MIT" }, - "node_modules/varuint-bitcoin": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/varuint-bitcoin/-/varuint-bitcoin-2.0.0.tgz", - "integrity": "sha512-6QZbU/rHO2ZQYpWFDALCDSRsXbAs1VOEmXAxtbtjLtKuMJ/FQ8YbhfxlaiKv5nklci0M6lZtlZyxo9Q+qNnyog==", + "node_modules/valibot": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/valibot/-/valibot-1.2.0.tgz", + "integrity": "sha512-mm1rxUsmOxzrwnX5arGS+U4T25RdvpPjPN4yR0u9pUBov9+zGVtO84tif1eY4r6zWxVxu3KzIyknJy3rxfRZZg==", "license": "MIT", - "dependencies": { - "uint8array-tools": "^0.0.8" + "peerDependencies": { + "typescript": ">=5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/varuint-bitcoin/node_modules/uint8array-tools": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/uint8array-tools/-/uint8array-tools-0.0.8.tgz", - "integrity": "sha512-xS6+s8e0Xbx++5/0L+yyexukU7pz//Yg6IHg3BKhXotg1JcYtgxVcUctQ0HxLByiJzpAkNFawz1Nz5Xadzo82g==", + "node_modules/varuint-bitcoin": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/varuint-bitcoin/-/varuint-bitcoin-1.1.2.tgz", + "integrity": "sha512-4EVb+w4rx+YfVM32HQX42AbbT7/1f5zwAYhIujKXKk8NQK+JfRVl3pqT3hjNn/L+RstigmGGKVwHA/P0wgITZw==", "license": "MIT", - "engines": { - "node": ">=14.0.0" + "dependencies": { + "safe-buffer": "^5.1.1" } }, "node_modules/vary": { @@ -7872,9 +7094,9 @@ } }, "node_modules/which-typed-array": { - "version": "1.1.19", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.19.tgz", - "integrity": "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==", + "version": "1.1.20", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.20.tgz", + "integrity": "sha512-LYfpUkmqwl0h9A2HL09Mms427Q1RZWuOHsukfVcKRq9q95iQxdw0ix1JQrqbcDR9PH1QDwf5Qo8OZb5lksZ8Xg==", "license": "MIT", "dependencies": { "available-typed-arrays": "^1.0.7", @@ -7904,15 +7126,6 @@ "node": ">=20.11" } }, - "node_modules/wide-align": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", - "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", - "license": "ISC", - "dependencies": { - "string-width": "^1.0.2 || 2 || 3 || 4" - } - }, "node_modules/wif": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/wif/-/wif-2.0.6.tgz", @@ -8012,9 +7225,9 @@ } }, "node_modules/ws": { - "version": "8.18.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", - "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", + "version": "8.19.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.19.0.tgz", + "integrity": "sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==", "license": "MIT", "engines": { "node": ">=10.0.0" @@ -8051,10 +7264,13 @@ } }, "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "license": "ISC" + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", + "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } }, "node_modules/yargs": { "version": "17.7.2", @@ -8104,15 +7320,40 @@ "is-glob": "^4.0.3" } }, + "node_modules/zip-a-folder/node_modules/balanced-match": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.2.tgz", + "integrity": "sha512-x0K50QvKQ97fdEz2kPehIerj+YTeptKF9hyYkKf6egnwmMWAkADiO0QCzSp0R5xN8FTZgYaBfSaue46Ej62nMg==", + "license": "MIT", + "dependencies": { + "jackspeak": "^4.2.3" + }, + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/zip-a-folder/node_modules/brace-expansion": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.2.tgz", + "integrity": "sha512-Pdk8c9poy+YhOgVWw1JNN22/HcivgKWwpxKq04M/jTmHyCZn12WPJebZxdjSa5TmBqISrUSgNYU3eRORljfCCw==", + "license": "MIT", + "dependencies": { + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "20 || >=22" + } + }, "node_modules/zip-a-folder/node_modules/glob": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-11.0.3.tgz", - "integrity": "sha512-2Nim7dha1KVkaiF4q6Dj+ngPPMdfvLJEOpZk/jKiUAkqKebpGAWQXAq9z1xu9HKu5lWfqw/FASuccEjyznjPaA==", - "license": "ISC", + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-11.1.0.tgz", + "integrity": "sha512-vuNwKSaKiqm7g0THUBu2x7ckSs3XJLXE+2ssL7/MfTGPLLcrJQ/4Uq1CjPTtO5cCIiRxqvN6Twy1qOwhL0Xjcw==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "license": "BlueOak-1.0.0", "dependencies": { "foreground-child": "^3.3.1", "jackspeak": "^4.1.1", - "minimatch": "^10.0.3", + "minimatch": "^10.1.1", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^2.0.0" @@ -8128,12 +7369,12 @@ } }, "node_modules/zip-a-folder/node_modules/minimatch": { - "version": "10.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.3.tgz", - "integrity": "sha512-IPZ167aShDZZUMdRk66cyQAW3qr0WzbHkPdMYa8bzZhlHhO3jALbKdxcaak7W9FfT2rZNpQuUu4Od7ILEpXSaw==", - "license": "ISC", + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.0.tgz", + "integrity": "sha512-ugkC31VaVg9cF0DFVoADH12k6061zNZkZON+aX8AWsR9GhPcErkcMBceb6znR8wLERM2AkkOxy2nWRLpT9Jq5w==", + "license": "BlueOak-1.0.0", "dependencies": { - "@isaacs/brace-expansion": "^5.0.0" + "brace-expansion": "^5.0.2" }, "engines": { "node": "20 || >=22" @@ -8142,15 +7383,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/zip-a-folder/node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "license": "ISC", - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, "node_modules/zip-stream": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-6.0.1.tgz", diff --git a/package.json b/package.json index 7db3acdb..54f95e5c 100644 --- a/package.json +++ b/package.json @@ -77,6 +77,7 @@ "zip-a-folder": "^3.1.9" }, "devDependencies": { + "@types/better-sqlite3": "^7.6.13", "@types/chai": "^4.3.4", "@types/chai-string": "^1.4.5", "@types/cors": "^2.8.17", @@ -93,4 +94,4 @@ "typescript": "5.5.4" }, "overrides": {} -} \ No newline at end of file +} diff --git a/proto/autogenerated/client.md b/proto/autogenerated/client.md index d42fc9ac..569f4328 100644 --- a/proto/autogenerated/client.md +++ b/proto/autogenerated/client.md @@ -1431,6 +1431,9 @@ The nostr server will send back a message response, and inside the body there wi - __failure_reason__: _string_ *this field is optional - __operation_payment__: _[UserOperation](#UserOperation)_ *this field is optional - __quote__: _[InvoiceSwapQuote](#InvoiceSwapQuote)_ + - __refund_address__: _string_ *this field is optional + - __refund_at_unix__: _number_ *this field is optional + - __refund_tx_id__: _string_ *this field is optional ### InvoiceSwapQuote - __address__: _string_ diff --git a/proto/autogenerated/go/types.go b/proto/autogenerated/go/types.go index cff46783..32b3a605 100644 --- a/proto/autogenerated/go/types.go +++ b/proto/autogenerated/go/types.go @@ -391,6 +391,9 @@ type InvoiceSwapOperation struct { Failure_reason string `json:"failure_reason"` Operation_payment *UserOperation `json:"operation_payment"` Quote *InvoiceSwapQuote `json:"quote"` + Refund_address string `json:"refund_address"` + Refund_at_unix int64 `json:"refund_at_unix"` + Refund_tx_id string `json:"refund_tx_id"` } type InvoiceSwapQuote struct { Address string `json:"address"` diff --git a/proto/autogenerated/ts/types.ts b/proto/autogenerated/ts/types.ts index 90cd1724..9b24aabb 100644 --- a/proto/autogenerated/ts/types.ts +++ b/proto/autogenerated/ts/types.ts @@ -2270,15 +2270,21 @@ export type InvoiceSwapOperation = { failure_reason?: string operation_payment?: UserOperation quote: InvoiceSwapQuote + refund_address?: string + refund_at_unix?: number + refund_tx_id?: string } -export type InvoiceSwapOperationOptionalField = 'completed_at_unix' | 'failure_reason' | 'operation_payment' -export const InvoiceSwapOperationOptionalFields: InvoiceSwapOperationOptionalField[] = ['completed_at_unix', 'failure_reason', 'operation_payment'] +export type InvoiceSwapOperationOptionalField = 'completed_at_unix' | 'failure_reason' | 'operation_payment' | 'refund_address' | 'refund_at_unix' | 'refund_tx_id' +export const InvoiceSwapOperationOptionalFields: InvoiceSwapOperationOptionalField[] = ['completed_at_unix', 'failure_reason', 'operation_payment', 'refund_address', 'refund_at_unix', 'refund_tx_id'] export type InvoiceSwapOperationOptions = OptionsBaseMessage & { checkOptionalsAreSet?: InvoiceSwapOperationOptionalField[] completed_at_unix_CustomCheck?: (v?: number) => boolean failure_reason_CustomCheck?: (v?: string) => boolean operation_payment_Options?: UserOperationOptions quote_Options?: InvoiceSwapQuoteOptions + refund_address_CustomCheck?: (v?: string) => boolean + refund_at_unix_CustomCheck?: (v?: number) => boolean + refund_tx_id_CustomCheck?: (v?: string) => boolean } export const InvoiceSwapOperationValidate = (o?: InvoiceSwapOperation, opts: InvoiceSwapOperationOptions = {}, path: string = 'InvoiceSwapOperation::root.'): Error | null => { if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message') @@ -2300,6 +2306,15 @@ export const InvoiceSwapOperationValidate = (o?: InvoiceSwapOperation, opts: Inv if (quoteErr !== null) return quoteErr + if ((o.refund_address || opts.allOptionalsAreSet || opts.checkOptionalsAreSet?.includes('refund_address')) && typeof o.refund_address !== 'string') return new Error(`${path}.refund_address: is not a string`) + if (opts.refund_address_CustomCheck && !opts.refund_address_CustomCheck(o.refund_address)) return new Error(`${path}.refund_address: custom check failed`) + + if ((o.refund_at_unix || opts.allOptionalsAreSet || opts.checkOptionalsAreSet?.includes('refund_at_unix')) && typeof o.refund_at_unix !== 'number') return new Error(`${path}.refund_at_unix: is not a number`) + if (opts.refund_at_unix_CustomCheck && !opts.refund_at_unix_CustomCheck(o.refund_at_unix)) return new Error(`${path}.refund_at_unix: custom check failed`) + + if ((o.refund_tx_id || opts.allOptionalsAreSet || opts.checkOptionalsAreSet?.includes('refund_tx_id')) && typeof o.refund_tx_id !== 'string') return new Error(`${path}.refund_tx_id: is not a string`) + if (opts.refund_tx_id_CustomCheck && !opts.refund_tx_id_CustomCheck(o.refund_tx_id)) return new Error(`${path}.refund_tx_id: custom check failed`) + return null } diff --git a/proto/lnd/chainnotifier.client.ts b/proto/lnd/chainnotifier.client.ts index dba8dc1b..c5d35063 100644 --- a/proto/lnd/chainnotifier.client.ts +++ b/proto/lnd/chainnotifier.client.ts @@ -1,4 +1,4 @@ -// @generated by protobuf-ts 2.8.1 +// @generated by protobuf-ts 2.11.1 // @generated from protobuf file "chainnotifier.proto" (package "chainrpc", syntax proto3) // tslint:disable import type { RpcTransport } from "@protobuf-ts/runtime-rpc"; @@ -31,7 +31,7 @@ export interface IChainNotifierClient { * a notification is sent once the output script confirms in the given * transaction. * - * @generated from protobuf rpc: RegisterConfirmationsNtfn(chainrpc.ConfRequest) returns (stream chainrpc.ConfEvent); + * @generated from protobuf rpc: RegisterConfirmationsNtfn */ registerConfirmationsNtfn(input: ConfRequest, options?: RpcOptions): ServerStreamingCall; /** @@ -43,7 +43,7 @@ export interface IChainNotifierClient { * A client can specify whether the spend request should be for a particular * outpoint or for an output script by specifying a zero outpoint. * - * @generated from protobuf rpc: RegisterSpendNtfn(chainrpc.SpendRequest) returns (stream chainrpc.SpendEvent); + * @generated from protobuf rpc: RegisterSpendNtfn */ registerSpendNtfn(input: SpendRequest, options?: RpcOptions): ServerStreamingCall; /** @@ -58,7 +58,7 @@ export interface IChainNotifierClient { * point. This allows clients to be idempotent by ensuring that they do not * missing processing a single block within the chain. * - * @generated from protobuf rpc: RegisterBlockEpochNtfn(chainrpc.BlockEpoch) returns (stream chainrpc.BlockEpoch); + * @generated from protobuf rpc: RegisterBlockEpochNtfn */ registerBlockEpochNtfn(input: BlockEpoch, options?: RpcOptions): ServerStreamingCall; } @@ -86,7 +86,7 @@ export class ChainNotifierClient implements IChainNotifierClient, ServiceInfo { * a notification is sent once the output script confirms in the given * transaction. * - * @generated from protobuf rpc: RegisterConfirmationsNtfn(chainrpc.ConfRequest) returns (stream chainrpc.ConfEvent); + * @generated from protobuf rpc: RegisterConfirmationsNtfn */ registerConfirmationsNtfn(input: ConfRequest, options?: RpcOptions): ServerStreamingCall { const method = this.methods[0], opt = this._transport.mergeOptions(options); @@ -101,7 +101,7 @@ export class ChainNotifierClient implements IChainNotifierClient, ServiceInfo { * A client can specify whether the spend request should be for a particular * outpoint or for an output script by specifying a zero outpoint. * - * @generated from protobuf rpc: RegisterSpendNtfn(chainrpc.SpendRequest) returns (stream chainrpc.SpendEvent); + * @generated from protobuf rpc: RegisterSpendNtfn */ registerSpendNtfn(input: SpendRequest, options?: RpcOptions): ServerStreamingCall { const method = this.methods[1], opt = this._transport.mergeOptions(options); @@ -119,7 +119,7 @@ export class ChainNotifierClient implements IChainNotifierClient, ServiceInfo { * point. This allows clients to be idempotent by ensuring that they do not * missing processing a single block within the chain. * - * @generated from protobuf rpc: RegisterBlockEpochNtfn(chainrpc.BlockEpoch) returns (stream chainrpc.BlockEpoch); + * @generated from protobuf rpc: RegisterBlockEpochNtfn */ registerBlockEpochNtfn(input: BlockEpoch, options?: RpcOptions): ServerStreamingCall { const method = this.methods[2], opt = this._transport.mergeOptions(options); diff --git a/proto/lnd/chainnotifier.ts b/proto/lnd/chainnotifier.ts index 326fa968..b2f3a97a 100644 --- a/proto/lnd/chainnotifier.ts +++ b/proto/lnd/chainnotifier.ts @@ -1,4 +1,4 @@ -// @generated by protobuf-ts 2.8.1 +// @generated by protobuf-ts 2.11.1 // @generated from protobuf file "chainnotifier.proto" (package "chainrpc", syntax proto3) // tslint:disable import { ServiceType } from "@protobuf-ts/runtime-rpc"; @@ -10,7 +10,6 @@ import type { IBinaryReader } from "@protobuf-ts/runtime"; import { UnknownFieldHandler } from "@protobuf-ts/runtime"; import type { PartialMessage } from "@protobuf-ts/runtime"; import { reflectionMergePartial } from "@protobuf-ts/runtime"; -import { MESSAGE_TYPE } from "@protobuf-ts/runtime"; import { MessageType } from "@protobuf-ts/runtime"; /** * @generated from protobuf message chainrpc.ConfRequest @@ -22,7 +21,7 @@ export interface ConfRequest { * for. If set to a hash of all zeros, then the confirmation notification will * be requested for the script instead. * - * @generated from protobuf field: bytes txid = 1; + * @generated from protobuf field: bytes txid = 1 */ txid: Uint8Array; /** @@ -32,7 +31,7 @@ export interface ConfRequest { * hash of all zeros, then a confirmation notification will be requested for * this script instead. * - * @generated from protobuf field: bytes script = 2; + * @generated from protobuf field: bytes script = 2 */ script: Uint8Array; /** @@ -40,7 +39,7 @@ export interface ConfRequest { * The number of desired confirmations the transaction/output script should * reach before dispatching a confirmation notification. * - * @generated from protobuf field: uint32 num_confs = 3; + * @generated from protobuf field: uint32 num_confs = 3 */ numConfs: number; /** @@ -49,7 +48,7 @@ export interface ConfRequest { * could have been included in a block. This should in most cases be set to the * broadcast height of the transaction/output script. * - * @generated from protobuf field: uint32 height_hint = 4; + * @generated from protobuf field: uint32 height_hint = 4 */ heightHint: number; /** @@ -57,7 +56,7 @@ export interface ConfRequest { * If true, then the block that mines the specified txid/script will be * included in eventual the notification event. * - * @generated from protobuf field: bool include_block = 5; + * @generated from protobuf field: bool include_block = 5 */ includeBlock: boolean; } @@ -68,26 +67,26 @@ export interface ConfDetails { /** * The raw bytes of the confirmed transaction. * - * @generated from protobuf field: bytes raw_tx = 1; + * @generated from protobuf field: bytes raw_tx = 1 */ rawTx: Uint8Array; /** * The hash of the block in which the confirmed transaction was included in. * - * @generated from protobuf field: bytes block_hash = 2; + * @generated from protobuf field: bytes block_hash = 2 */ blockHash: Uint8Array; /** * The height of the block in which the confirmed transaction was included * in. * - * @generated from protobuf field: uint32 block_height = 3; + * @generated from protobuf field: uint32 block_height = 3 */ blockHeight: number; /** * The index of the confirmed transaction within the block. * - * @generated from protobuf field: uint32 tx_index = 4; + * @generated from protobuf field: uint32 tx_index = 4 */ txIndex: number; /** @@ -95,7 +94,7 @@ export interface ConfDetails { * The raw bytes of the block that mined the transaction. Only included if * include_block was set in the request. * - * @generated from protobuf field: bytes raw_block = 5; + * @generated from protobuf field: bytes raw_block = 5 */ rawBlock: Uint8Array; } @@ -120,7 +119,7 @@ export interface ConfEvent { * An event that includes the confirmation details of the request * (txid/ouput script). * - * @generated from protobuf field: chainrpc.ConfDetails conf = 1; + * @generated from protobuf field: chainrpc.ConfDetails conf = 1 */ conf: ConfDetails; } | { @@ -130,7 +129,7 @@ export interface ConfEvent { * An event send when the transaction of the request is reorged out of the * chain. * - * @generated from protobuf field: chainrpc.Reorg reorg = 2; + * @generated from protobuf field: chainrpc.Reorg reorg = 2 */ reorg: Reorg; } | { @@ -144,13 +143,13 @@ export interface Outpoint { /** * The hash of the transaction. * - * @generated from protobuf field: bytes hash = 1; + * @generated from protobuf field: bytes hash = 1 */ hash: Uint8Array; /** * The index of the output within the transaction. * - * @generated from protobuf field: uint32 index = 2; + * @generated from protobuf field: uint32 index = 2 */ index: number; } @@ -168,7 +167,7 @@ export interface SpendRequest { * So an outpoint must _always_ be specified when registering a spend * notification for a Taproot output. * - * @generated from protobuf field: chainrpc.Outpoint outpoint = 1; + * @generated from protobuf field: chainrpc.Outpoint outpoint = 1 */ outpoint?: Outpoint; /** @@ -177,7 +176,7 @@ export interface SpendRequest { * to match block filters. If the outpoint is set to a zero outpoint, then a * spend notification will be requested for this script instead. * - * @generated from protobuf field: bytes script = 2; + * @generated from protobuf field: bytes script = 2 */ script: Uint8Array; /** @@ -186,7 +185,7 @@ export interface SpendRequest { * have been spent. This should in most cases be set to the broadcast height of * the outpoint/output script. * - * @generated from protobuf field: uint32 height_hint = 3; + * @generated from protobuf field: uint32 height_hint = 3 */ heightHint: number; } @@ -197,31 +196,31 @@ export interface SpendDetails { /** * The outpoint was that spent. * - * @generated from protobuf field: chainrpc.Outpoint spending_outpoint = 1; + * @generated from protobuf field: chainrpc.Outpoint spending_outpoint = 1 */ spendingOutpoint?: Outpoint; /** * The raw bytes of the spending transaction. * - * @generated from protobuf field: bytes raw_spending_tx = 2; + * @generated from protobuf field: bytes raw_spending_tx = 2 */ rawSpendingTx: Uint8Array; /** * The hash of the spending transaction. * - * @generated from protobuf field: bytes spending_tx_hash = 3; + * @generated from protobuf field: bytes spending_tx_hash = 3 */ spendingTxHash: Uint8Array; /** * The input of the spending transaction that fulfilled the spend request. * - * @generated from protobuf field: uint32 spending_input_index = 4; + * @generated from protobuf field: uint32 spending_input_index = 4 */ spendingInputIndex: number; /** * The height at which the spending transaction was included in a block. * - * @generated from protobuf field: uint32 spending_height = 5; + * @generated from protobuf field: uint32 spending_height = 5 */ spendingHeight: number; } @@ -239,7 +238,7 @@ export interface SpendEvent { * An event that includes the details of the spending transaction of the * request (outpoint/output script). * - * @generated from protobuf field: chainrpc.SpendDetails spend = 1; + * @generated from protobuf field: chainrpc.SpendDetails spend = 1 */ spend: SpendDetails; } | { @@ -249,7 +248,7 @@ export interface SpendEvent { * An event sent when the spending transaction of the request was * reorged out of the chain. * - * @generated from protobuf field: chainrpc.Reorg reorg = 2; + * @generated from protobuf field: chainrpc.Reorg reorg = 2 */ reorg: Reorg; } | { @@ -263,13 +262,13 @@ export interface BlockEpoch { /** * The hash of the block. * - * @generated from protobuf field: bytes hash = 1; + * @generated from protobuf field: bytes hash = 1 */ hash: Uint8Array; /** * The height of the block. * - * @generated from protobuf field: uint32 height = 2; + * @generated from protobuf field: uint32 height = 2 */ height: number; } @@ -285,8 +284,12 @@ class ConfRequest$Type extends MessageType { ]); } create(value?: PartialMessage): ConfRequest { - const message = { txid: new Uint8Array(0), script: new Uint8Array(0), numConfs: 0, heightHint: 0, includeBlock: false }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.txid = new Uint8Array(0); + message.script = new Uint8Array(0); + message.numConfs = 0; + message.heightHint = 0; + message.includeBlock = false; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -360,8 +363,12 @@ class ConfDetails$Type extends MessageType { ]); } create(value?: PartialMessage): ConfDetails { - const message = { rawTx: new Uint8Array(0), blockHash: new Uint8Array(0), blockHeight: 0, txIndex: 0, rawBlock: new Uint8Array(0) }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.rawTx = new Uint8Array(0); + message.blockHash = new Uint8Array(0); + message.blockHeight = 0; + message.txIndex = 0; + message.rawBlock = new Uint8Array(0); if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -429,14 +436,26 @@ class Reorg$Type extends MessageType { super("chainrpc.Reorg", []); } create(value?: PartialMessage): Reorg { - const message = {}; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); if (value !== undefined) reflectionMergePartial(this, message, value); return message; } internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: Reorg): Reorg { - return target ?? this.create(); + let message = target ?? this.create(), end = reader.pos + length; + while (reader.pos < end) { + let [fieldNo, wireType] = reader.tag(); + switch (fieldNo) { + default: + let u = options.readUnknownField; + if (u === "throw") + throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`); + let d = reader.skip(wireType); + if (u !== false) + (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d); + } + } + return message; } internalBinaryWrite(message: Reorg, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter { let u = options.writeUnknownFields; @@ -458,8 +477,8 @@ class ConfEvent$Type extends MessageType { ]); } create(value?: PartialMessage): ConfEvent { - const message = { event: { oneofKind: undefined } }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.event = { oneofKind: undefined }; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -518,8 +537,9 @@ class Outpoint$Type extends MessageType { ]); } create(value?: PartialMessage): Outpoint { - const message = { hash: new Uint8Array(0), index: 0 }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.hash = new Uint8Array(0); + message.index = 0; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -573,8 +593,9 @@ class SpendRequest$Type extends MessageType { ]); } create(value?: PartialMessage): SpendRequest { - const message = { script: new Uint8Array(0), heightHint: 0 }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.script = new Uint8Array(0); + message.heightHint = 0; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -636,8 +657,11 @@ class SpendDetails$Type extends MessageType { ]); } create(value?: PartialMessage): SpendDetails { - const message = { rawSpendingTx: new Uint8Array(0), spendingTxHash: new Uint8Array(0), spendingInputIndex: 0, spendingHeight: 0 }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.rawSpendingTx = new Uint8Array(0); + message.spendingTxHash = new Uint8Array(0); + message.spendingInputIndex = 0; + message.spendingHeight = 0; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -708,8 +732,8 @@ class SpendEvent$Type extends MessageType { ]); } create(value?: PartialMessage): SpendEvent { - const message = { event: { oneofKind: undefined } }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.event = { oneofKind: undefined }; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -768,8 +792,9 @@ class BlockEpoch$Type extends MessageType { ]); } create(value?: PartialMessage): BlockEpoch { - const message = { hash: new Uint8Array(0), height: 0 }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.hash = new Uint8Array(0); + message.height = 0; if (value !== undefined) reflectionMergePartial(this, message, value); return message; diff --git a/proto/lnd/invoices.client.ts b/proto/lnd/invoices.client.ts index b529cca1..842cd4b7 100644 --- a/proto/lnd/invoices.client.ts +++ b/proto/lnd/invoices.client.ts @@ -1,9 +1,12 @@ -// @generated by protobuf-ts 2.8.1 +// @generated by protobuf-ts 2.11.1 // @generated from protobuf file "invoices.proto" (package "invoicesrpc", syntax proto3) // tslint:disable import type { RpcTransport } from "@protobuf-ts/runtime-rpc"; import type { ServiceInfo } from "@protobuf-ts/runtime-rpc"; import { Invoices } from "./invoices.js"; +import type { HtlcModifyRequest } from "./invoices.js"; +import type { HtlcModifyResponse } from "./invoices.js"; +import type { DuplexStreamingCall } from "@protobuf-ts/runtime-rpc"; import type { LookupInvoiceMsg } from "./invoices.js"; import type { SettleInvoiceResp } from "./invoices.js"; import type { SettleInvoiceMsg } from "./invoices.js"; @@ -17,6 +20,23 @@ import type { Invoice } from "./lightning.js"; import type { SubscribeSingleInvoiceRequest } from "./invoices.js"; import type { ServerStreamingCall } from "@protobuf-ts/runtime-rpc"; import type { RpcOptions } from "@protobuf-ts/runtime-rpc"; +// +// Comments in this file will be directly parsed into the API +// Documentation as descriptions of the associated method, message, or field. +// These descriptions should go right above the definition of the object, and +// can be in either block or // comment format. +// +// An RPC method can be matched to an lncli command by placing a line in the +// beginning of the description in exactly the following format: +// lncli: `methodname` +// +// Failure to specify the exact name of the command will cause documentation +// generation to fail. +// +// More information on how exactly the gRPC documentation is generated from +// this proto file can be found here: +// https://github.com/lightninglabs/lightning-api + /** * Invoices is a service that can be used to create, accept, settle and cancel * invoices. @@ -30,43 +50,70 @@ export interface IInvoicesClient { * to notify the client of state transitions of the specified invoice. * Initially the current invoice state is always sent out. * - * @generated from protobuf rpc: SubscribeSingleInvoice(invoicesrpc.SubscribeSingleInvoiceRequest) returns (stream lnrpc.Invoice); + * @generated from protobuf rpc: SubscribeSingleInvoice */ subscribeSingleInvoice(input: SubscribeSingleInvoiceRequest, options?: RpcOptions): ServerStreamingCall; /** - * + * lncli: `cancelinvoice` * CancelInvoice cancels a currently open invoice. If the invoice is already * canceled, this call will succeed. If the invoice is already settled, it will * fail. * - * @generated from protobuf rpc: CancelInvoice(invoicesrpc.CancelInvoiceMsg) returns (invoicesrpc.CancelInvoiceResp); + * @generated from protobuf rpc: CancelInvoice */ cancelInvoice(input: CancelInvoiceMsg, options?: RpcOptions): UnaryCall; /** - * + * lncli: `addholdinvoice` * AddHoldInvoice creates a hold invoice. It ties the invoice to the hash * supplied in the request. * - * @generated from protobuf rpc: AddHoldInvoice(invoicesrpc.AddHoldInvoiceRequest) returns (invoicesrpc.AddHoldInvoiceResp); + * @generated from protobuf rpc: AddHoldInvoice */ addHoldInvoice(input: AddHoldInvoiceRequest, options?: RpcOptions): UnaryCall; /** - * + * lncli: `settleinvoice` * SettleInvoice settles an accepted invoice. If the invoice is already * settled, this call will succeed. * - * @generated from protobuf rpc: SettleInvoice(invoicesrpc.SettleInvoiceMsg) returns (invoicesrpc.SettleInvoiceResp); + * @generated from protobuf rpc: SettleInvoice */ settleInvoice(input: SettleInvoiceMsg, options?: RpcOptions): UnaryCall; /** * - * LookupInvoiceV2 attempts to look up at invoice. An invoice can be refrenced + * LookupInvoiceV2 attempts to look up at invoice. An invoice can be referenced * using either its payment hash, payment address, or set ID. * - * @generated from protobuf rpc: LookupInvoiceV2(invoicesrpc.LookupInvoiceMsg) returns (lnrpc.Invoice); + * @generated from protobuf rpc: LookupInvoiceV2 */ lookupInvoiceV2(input: LookupInvoiceMsg, options?: RpcOptions): UnaryCall; + /** + * + * HtlcModifier is a bidirectional streaming RPC that allows a client to + * intercept and modify the HTLCs that attempt to settle the given invoice. The + * server will send HTLCs of invoices to the client and the client can modify + * some aspects of the HTLC in order to pass the invoice acceptance tests. + * + * @generated from protobuf rpc: HtlcModifier + */ + htlcModifier(options?: RpcOptions): DuplexStreamingCall; } +// +// Comments in this file will be directly parsed into the API +// Documentation as descriptions of the associated method, message, or field. +// These descriptions should go right above the definition of the object, and +// can be in either block or // comment format. +// +// An RPC method can be matched to an lncli command by placing a line in the +// beginning of the description in exactly the following format: +// lncli: `methodname` +// +// Failure to specify the exact name of the command will cause documentation +// generation to fail. +// +// More information on how exactly the gRPC documentation is generated from +// this proto file can be found here: +// https://github.com/lightninglabs/lightning-api + /** * Invoices is a service that can be used to create, accept, settle and cancel * invoices. @@ -85,41 +132,41 @@ export class InvoicesClient implements IInvoicesClient, ServiceInfo { * to notify the client of state transitions of the specified invoice. * Initially the current invoice state is always sent out. * - * @generated from protobuf rpc: SubscribeSingleInvoice(invoicesrpc.SubscribeSingleInvoiceRequest) returns (stream lnrpc.Invoice); + * @generated from protobuf rpc: SubscribeSingleInvoice */ subscribeSingleInvoice(input: SubscribeSingleInvoiceRequest, options?: RpcOptions): ServerStreamingCall { const method = this.methods[0], opt = this._transport.mergeOptions(options); return stackIntercept("serverStreaming", this._transport, method, opt, input); } /** - * + * lncli: `cancelinvoice` * CancelInvoice cancels a currently open invoice. If the invoice is already * canceled, this call will succeed. If the invoice is already settled, it will * fail. * - * @generated from protobuf rpc: CancelInvoice(invoicesrpc.CancelInvoiceMsg) returns (invoicesrpc.CancelInvoiceResp); + * @generated from protobuf rpc: CancelInvoice */ cancelInvoice(input: CancelInvoiceMsg, options?: RpcOptions): UnaryCall { const method = this.methods[1], opt = this._transport.mergeOptions(options); return stackIntercept("unary", this._transport, method, opt, input); } /** - * + * lncli: `addholdinvoice` * AddHoldInvoice creates a hold invoice. It ties the invoice to the hash * supplied in the request. * - * @generated from protobuf rpc: AddHoldInvoice(invoicesrpc.AddHoldInvoiceRequest) returns (invoicesrpc.AddHoldInvoiceResp); + * @generated from protobuf rpc: AddHoldInvoice */ addHoldInvoice(input: AddHoldInvoiceRequest, options?: RpcOptions): UnaryCall { const method = this.methods[2], opt = this._transport.mergeOptions(options); return stackIntercept("unary", this._transport, method, opt, input); } /** - * + * lncli: `settleinvoice` * SettleInvoice settles an accepted invoice. If the invoice is already * settled, this call will succeed. * - * @generated from protobuf rpc: SettleInvoice(invoicesrpc.SettleInvoiceMsg) returns (invoicesrpc.SettleInvoiceResp); + * @generated from protobuf rpc: SettleInvoice */ settleInvoice(input: SettleInvoiceMsg, options?: RpcOptions): UnaryCall { const method = this.methods[3], opt = this._transport.mergeOptions(options); @@ -127,13 +174,26 @@ export class InvoicesClient implements IInvoicesClient, ServiceInfo { } /** * - * LookupInvoiceV2 attempts to look up at invoice. An invoice can be refrenced + * LookupInvoiceV2 attempts to look up at invoice. An invoice can be referenced * using either its payment hash, payment address, or set ID. * - * @generated from protobuf rpc: LookupInvoiceV2(invoicesrpc.LookupInvoiceMsg) returns (lnrpc.Invoice); + * @generated from protobuf rpc: LookupInvoiceV2 */ lookupInvoiceV2(input: LookupInvoiceMsg, options?: RpcOptions): UnaryCall { const method = this.methods[4], opt = this._transport.mergeOptions(options); return stackIntercept("unary", this._transport, method, opt, input); } + /** + * + * HtlcModifier is a bidirectional streaming RPC that allows a client to + * intercept and modify the HTLCs that attempt to settle the given invoice. The + * server will send HTLCs of invoices to the client and the client can modify + * some aspects of the HTLC in order to pass the invoice acceptance tests. + * + * @generated from protobuf rpc: HtlcModifier + */ + htlcModifier(options?: RpcOptions): DuplexStreamingCall { + const method = this.methods[5], opt = this._transport.mergeOptions(options); + return stackIntercept("duplex", this._transport, method, opt); + } } diff --git a/proto/lnd/invoices.ts b/proto/lnd/invoices.ts index 4155cf06..64395755 100644 --- a/proto/lnd/invoices.ts +++ b/proto/lnd/invoices.ts @@ -1,7 +1,6 @@ -// @generated by protobuf-ts 2.8.1 +// @generated by protobuf-ts 2.11.1 // @generated from protobuf file "invoices.proto" (package "invoicesrpc", syntax proto3) // tslint:disable -import { Invoice } from "./lightning.js"; import { ServiceType } from "@protobuf-ts/runtime-rpc"; import type { BinaryWriteOptions } from "@protobuf-ts/runtime"; import type { IBinaryWriter } from "@protobuf-ts/runtime"; @@ -11,8 +10,8 @@ import type { IBinaryReader } from "@protobuf-ts/runtime"; import { UnknownFieldHandler } from "@protobuf-ts/runtime"; import type { PartialMessage } from "@protobuf-ts/runtime"; import { reflectionMergePartial } from "@protobuf-ts/runtime"; -import { MESSAGE_TYPE } from "@protobuf-ts/runtime"; import { MessageType } from "@protobuf-ts/runtime"; +import { Invoice } from "./lightning.js"; import { RouteHint } from "./lightning.js"; /** * @generated from protobuf message invoicesrpc.CancelInvoiceMsg @@ -22,7 +21,7 @@ export interface CancelInvoiceMsg { * Hash corresponding to the (hold) invoice to cancel. When using * REST, this field must be encoded as base64. * - * @generated from protobuf field: bytes payment_hash = 1; + * @generated from protobuf field: bytes payment_hash = 1 */ paymentHash: Uint8Array; } @@ -42,13 +41,13 @@ export interface AddHoldInvoiceRequest { * field of the encoded payment request if the description_hash field is not * being used. * - * @generated from protobuf field: string memo = 1; + * @generated from protobuf field: string memo = 1 */ memo: string; /** * The hash of the preimage * - * @generated from protobuf field: bytes hash = 2; + * @generated from protobuf field: bytes hash = 2 */ hash: Uint8Array; /** @@ -57,7 +56,7 @@ export interface AddHoldInvoiceRequest { * * The fields value and value_msat are mutually exclusive. * - * @generated from protobuf field: int64 value = 3; + * @generated from protobuf field: int64 value = 3 */ value: bigint; /** @@ -66,7 +65,7 @@ export interface AddHoldInvoiceRequest { * * The fields value and value_msat are mutually exclusive. * - * @generated from protobuf field: int64 value_msat = 10; + * @generated from protobuf field: int64 value_msat = 10 */ valueMsat: bigint; /** @@ -75,25 +74,25 @@ export interface AddHoldInvoiceRequest { * payment (memo) is too long to naturally fit within the description field * of an encoded payment request. * - * @generated from protobuf field: bytes description_hash = 4; + * @generated from protobuf field: bytes description_hash = 4 */ descriptionHash: Uint8Array; /** - * Payment request expiry time in seconds. Default is 3600 (1 hour). + * Payment request expiry time in seconds. Default is 86400 (24 hours). * - * @generated from protobuf field: int64 expiry = 5; + * @generated from protobuf field: int64 expiry = 5 */ expiry: bigint; /** * Fallback on-chain address. * - * @generated from protobuf field: string fallback_addr = 6; + * @generated from protobuf field: string fallback_addr = 6 */ fallbackAddr: string; /** * Delta to use for the time-lock of the CLTV extended to the final hop. * - * @generated from protobuf field: uint64 cltv_expiry = 7; + * @generated from protobuf field: uint64 cltv_expiry = 7 */ cltvExpiry: bigint; /** @@ -101,13 +100,13 @@ export interface AddHoldInvoiceRequest { * Route hints that can each be individually used to assist in reaching the * invoice's destination. * - * @generated from protobuf field: repeated lnrpc.RouteHint route_hints = 8; + * @generated from protobuf field: repeated lnrpc.RouteHint route_hints = 8 */ routeHints: RouteHint[]; /** * Whether this invoice should include routing hints for private channels. * - * @generated from protobuf field: bool private = 9; + * @generated from protobuf field: bool private = 9 */ private: boolean; } @@ -121,7 +120,7 @@ export interface AddHoldInvoiceResp { * details of the invoice, the sender has all the data necessary to send a * payment to the recipient. * - * @generated from protobuf field: string payment_request = 1; + * @generated from protobuf field: string payment_request = 1 */ paymentRequest: string; /** @@ -131,16 +130,17 @@ export interface AddHoldInvoiceResp { * SubscribeInvoices call can use this to instantly get notified of all added * invoices with an add_index greater than this one. * - * @generated from protobuf field: uint64 add_index = 2; + * @generated from protobuf field: uint64 add_index = 2 */ addIndex: bigint; /** * - * The payment address of the generated invoice. This value should be used - * in all payments for this invoice as we require it for end to end + * The payment address of the generated invoice. This is also called + * the payment secret in specifications (e.g. BOLT 11). This value should + * be used in all payments for this invoice as we require it for end to end * security. * - * @generated from protobuf field: bytes payment_addr = 3; + * @generated from protobuf field: bytes payment_addr = 3 */ paymentAddr: Uint8Array; } @@ -152,7 +152,7 @@ export interface SettleInvoiceMsg { * Externally discovered pre-image that should be used to settle the hold * invoice. * - * @generated from protobuf field: bytes preimage = 1; + * @generated from protobuf field: bytes preimage = 1 */ preimage: Uint8Array; } @@ -169,7 +169,7 @@ export interface SubscribeSingleInvoiceRequest { * Hash corresponding to the (hold) invoice to subscribe to. When using * REST, this field must be encoded as base64url. * - * @generated from protobuf field: bytes r_hash = 2; + * @generated from protobuf field: bytes r_hash = 2 */ rHash: Uint8Array; } @@ -185,29 +185,122 @@ export interface LookupInvoiceMsg { /** * When using REST, this field must be encoded as base64. * - * @generated from protobuf field: bytes payment_hash = 1; + * @generated from protobuf field: bytes payment_hash = 1 */ paymentHash: Uint8Array; } | { oneofKind: "paymentAddr"; /** - * @generated from protobuf field: bytes payment_addr = 2; + * @generated from protobuf field: bytes payment_addr = 2 */ paymentAddr: Uint8Array; } | { oneofKind: "setId"; /** - * @generated from protobuf field: bytes set_id = 3; + * @generated from protobuf field: bytes set_id = 3 */ setId: Uint8Array; } | { oneofKind: undefined; }; /** - * @generated from protobuf field: invoicesrpc.LookupModifier lookup_modifier = 4; + * @generated from protobuf field: invoicesrpc.LookupModifier lookup_modifier = 4 */ lookupModifier: LookupModifier; } +/** + * CircuitKey is a unique identifier for an HTLC. + * + * @generated from protobuf message invoicesrpc.CircuitKey + */ +export interface CircuitKey { + /** + * The id of the channel that the is part of this circuit. + * + * @generated from protobuf field: uint64 chan_id = 1 + */ + chanId: bigint; + /** + * The index of the incoming htlc in the incoming channel. + * + * @generated from protobuf field: uint64 htlc_id = 2 + */ + htlcId: bigint; +} +/** + * @generated from protobuf message invoicesrpc.HtlcModifyRequest + */ +export interface HtlcModifyRequest { + /** + * The invoice the intercepted HTLC is attempting to settle. The HTLCs in + * the invoice are only HTLCs that have already been accepted or settled, + * not including the current intercepted HTLC. + * + * @generated from protobuf field: lnrpc.Invoice invoice = 1 + */ + invoice?: Invoice; + /** + * The unique identifier of the HTLC of this intercepted HTLC. + * + * @generated from protobuf field: invoicesrpc.CircuitKey exit_htlc_circuit_key = 2 + */ + exitHtlcCircuitKey?: CircuitKey; + /** + * The amount in milli-satoshi that the exit HTLC is attempting to pay. + * + * @generated from protobuf field: uint64 exit_htlc_amt = 3 + */ + exitHtlcAmt: bigint; + /** + * The absolute expiry height of the exit HTLC. + * + * @generated from protobuf field: uint32 exit_htlc_expiry = 4 + */ + exitHtlcExpiry: number; + /** + * The current block height. + * + * @generated from protobuf field: uint32 current_height = 5 + */ + currentHeight: number; + /** + * The wire message custom records of the exit HTLC. + * + * @generated from protobuf field: map exit_htlc_wire_custom_records = 6 + */ + exitHtlcWireCustomRecords: { + [key: string]: Uint8Array; + }; +} +/** + * @generated from protobuf message invoicesrpc.HtlcModifyResponse + */ +export interface HtlcModifyResponse { + /** + * The circuit key of the HTLC that the client wants to modify. + * + * @generated from protobuf field: invoicesrpc.CircuitKey circuit_key = 1 + */ + circuitKey?: CircuitKey; + /** + * The modified amount in milli-satoshi that the exit HTLC is paying. This + * value can be different from the actual on-chain HTLC amount, in case the + * HTLC carries other valuable items, as can be the case with custom channel + * types. + * + * @generated from protobuf field: optional uint64 amt_paid = 2 + */ + amtPaid?: bigint; + /** + * This flag indicates whether the HTLCs associated with the invoices should + * be cancelled. The interceptor client may set this field if some + * unexpected behavior is encountered. Setting this will ignore the amt_paid + * field. + * + * @generated from protobuf field: bool cancel_set = 3 + */ + cancelSet: boolean; +} /** * @generated from protobuf enum invoicesrpc.LookupModifier */ @@ -245,8 +338,8 @@ class CancelInvoiceMsg$Type extends MessageType { ]); } create(value?: PartialMessage): CancelInvoiceMsg { - const message = { paymentHash: new Uint8Array(0) }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.paymentHash = new Uint8Array(0); if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -290,14 +383,26 @@ class CancelInvoiceResp$Type extends MessageType { super("invoicesrpc.CancelInvoiceResp", []); } create(value?: PartialMessage): CancelInvoiceResp { - const message = {}; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); if (value !== undefined) reflectionMergePartial(this, message, value); return message; } internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: CancelInvoiceResp): CancelInvoiceResp { - return target ?? this.create(); + let message = target ?? this.create(), end = reader.pos + length; + while (reader.pos < end) { + let [fieldNo, wireType] = reader.tag(); + switch (fieldNo) { + default: + let u = options.readUnknownField; + if (u === "throw") + throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`); + let d = reader.skip(wireType); + if (u !== false) + (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d); + } + } + return message; } internalBinaryWrite(message: CancelInvoiceResp, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter { let u = options.writeUnknownFields; @@ -322,13 +427,22 @@ class AddHoldInvoiceRequest$Type extends MessageType { { no: 5, name: "expiry", kind: "scalar", T: 3 /*ScalarType.INT64*/, L: 0 /*LongType.BIGINT*/ }, { no: 6, name: "fallback_addr", kind: "scalar", T: 9 /*ScalarType.STRING*/ }, { no: 7, name: "cltv_expiry", kind: "scalar", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ }, - { no: 8, name: "route_hints", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => RouteHint }, + { no: 8, name: "route_hints", kind: "message", repeat: 2 /*RepeatType.UNPACKED*/, T: () => RouteHint }, { no: 9, name: "private", kind: "scalar", T: 8 /*ScalarType.BOOL*/ } ]); } create(value?: PartialMessage): AddHoldInvoiceRequest { - const message = { memo: "", hash: new Uint8Array(0), value: 0n, valueMsat: 0n, descriptionHash: new Uint8Array(0), expiry: 0n, fallbackAddr: "", cltvExpiry: 0n, routeHints: [], private: false }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.memo = ""; + message.hash = new Uint8Array(0); + message.value = 0n; + message.valueMsat = 0n; + message.descriptionHash = new Uint8Array(0); + message.expiry = 0n; + message.fallbackAddr = ""; + message.cltvExpiry = 0n; + message.routeHints = []; + message.private = false; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -389,9 +503,6 @@ class AddHoldInvoiceRequest$Type extends MessageType { /* int64 value = 3; */ if (message.value !== 0n) writer.tag(3, WireType.Varint).int64(message.value); - /* int64 value_msat = 10; */ - if (message.valueMsat !== 0n) - writer.tag(10, WireType.Varint).int64(message.valueMsat); /* bytes description_hash = 4; */ if (message.descriptionHash.length) writer.tag(4, WireType.LengthDelimited).bytes(message.descriptionHash); @@ -410,6 +521,9 @@ class AddHoldInvoiceRequest$Type extends MessageType { /* bool private = 9; */ if (message.private !== false) writer.tag(9, WireType.Varint).bool(message.private); + /* int64 value_msat = 10; */ + if (message.valueMsat !== 0n) + writer.tag(10, WireType.Varint).int64(message.valueMsat); let u = options.writeUnknownFields; if (u !== false) (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer); @@ -430,8 +544,10 @@ class AddHoldInvoiceResp$Type extends MessageType { ]); } create(value?: PartialMessage): AddHoldInvoiceResp { - const message = { paymentRequest: "", addIndex: 0n, paymentAddr: new Uint8Array(0) }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.paymentRequest = ""; + message.addIndex = 0n; + message.paymentAddr = new Uint8Array(0); if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -489,8 +605,8 @@ class SettleInvoiceMsg$Type extends MessageType { ]); } create(value?: PartialMessage): SettleInvoiceMsg { - const message = { preimage: new Uint8Array(0) }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.preimage = new Uint8Array(0); if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -534,14 +650,26 @@ class SettleInvoiceResp$Type extends MessageType { super("invoicesrpc.SettleInvoiceResp", []); } create(value?: PartialMessage): SettleInvoiceResp { - const message = {}; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); if (value !== undefined) reflectionMergePartial(this, message, value); return message; } internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: SettleInvoiceResp): SettleInvoiceResp { - return target ?? this.create(); + let message = target ?? this.create(), end = reader.pos + length; + while (reader.pos < end) { + let [fieldNo, wireType] = reader.tag(); + switch (fieldNo) { + default: + let u = options.readUnknownField; + if (u === "throw") + throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`); + let d = reader.skip(wireType); + if (u !== false) + (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d); + } + } + return message; } internalBinaryWrite(message: SettleInvoiceResp, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter { let u = options.writeUnknownFields; @@ -562,8 +690,8 @@ class SubscribeSingleInvoiceRequest$Type extends MessageType): SubscribeSingleInvoiceRequest { - const message = { rHash: new Uint8Array(0) }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.rHash = new Uint8Array(0); if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -612,8 +740,9 @@ class LookupInvoiceMsg$Type extends MessageType { ]); } create(value?: PartialMessage): LookupInvoiceMsg { - const message = { invoiceRef: { oneofKind: undefined }, lookupModifier: 0 }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.invoiceRef = { oneofKind: undefined }; + message.lookupModifier = 0; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -678,6 +807,223 @@ class LookupInvoiceMsg$Type extends MessageType { * @generated MessageType for protobuf message invoicesrpc.LookupInvoiceMsg */ export const LookupInvoiceMsg = new LookupInvoiceMsg$Type(); +// @generated message type with reflection information, may provide speed optimized methods +class CircuitKey$Type extends MessageType { + constructor() { + super("invoicesrpc.CircuitKey", [ + { no: 1, name: "chan_id", kind: "scalar", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ }, + { no: 2, name: "htlc_id", kind: "scalar", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ } + ]); + } + create(value?: PartialMessage): CircuitKey { + const message = globalThis.Object.create((this.messagePrototype!)); + message.chanId = 0n; + message.htlcId = 0n; + if (value !== undefined) + reflectionMergePartial(this, message, value); + return message; + } + internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: CircuitKey): CircuitKey { + let message = target ?? this.create(), end = reader.pos + length; + while (reader.pos < end) { + let [fieldNo, wireType] = reader.tag(); + switch (fieldNo) { + case /* uint64 chan_id */ 1: + message.chanId = reader.uint64().toBigInt(); + break; + case /* uint64 htlc_id */ 2: + message.htlcId = reader.uint64().toBigInt(); + break; + default: + let u = options.readUnknownField; + if (u === "throw") + throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`); + let d = reader.skip(wireType); + if (u !== false) + (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d); + } + } + return message; + } + internalBinaryWrite(message: CircuitKey, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter { + /* uint64 chan_id = 1; */ + if (message.chanId !== 0n) + writer.tag(1, WireType.Varint).uint64(message.chanId); + /* uint64 htlc_id = 2; */ + if (message.htlcId !== 0n) + writer.tag(2, WireType.Varint).uint64(message.htlcId); + let u = options.writeUnknownFields; + if (u !== false) + (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer); + return writer; + } +} +/** + * @generated MessageType for protobuf message invoicesrpc.CircuitKey + */ +export const CircuitKey = new CircuitKey$Type(); +// @generated message type with reflection information, may provide speed optimized methods +class HtlcModifyRequest$Type extends MessageType { + constructor() { + super("invoicesrpc.HtlcModifyRequest", [ + { no: 1, name: "invoice", kind: "message", T: () => Invoice }, + { no: 2, name: "exit_htlc_circuit_key", kind: "message", T: () => CircuitKey }, + { no: 3, name: "exit_htlc_amt", kind: "scalar", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ }, + { no: 4, name: "exit_htlc_expiry", kind: "scalar", T: 13 /*ScalarType.UINT32*/ }, + { no: 5, name: "current_height", kind: "scalar", T: 13 /*ScalarType.UINT32*/ }, + { no: 6, name: "exit_htlc_wire_custom_records", kind: "map", K: 4 /*ScalarType.UINT64*/, V: { kind: "scalar", T: 12 /*ScalarType.BYTES*/ } } + ]); + } + create(value?: PartialMessage): HtlcModifyRequest { + const message = globalThis.Object.create((this.messagePrototype!)); + message.exitHtlcAmt = 0n; + message.exitHtlcExpiry = 0; + message.currentHeight = 0; + message.exitHtlcWireCustomRecords = {}; + if (value !== undefined) + reflectionMergePartial(this, message, value); + return message; + } + internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: HtlcModifyRequest): HtlcModifyRequest { + let message = target ?? this.create(), end = reader.pos + length; + while (reader.pos < end) { + let [fieldNo, wireType] = reader.tag(); + switch (fieldNo) { + case /* lnrpc.Invoice invoice */ 1: + message.invoice = Invoice.internalBinaryRead(reader, reader.uint32(), options, message.invoice); + break; + case /* invoicesrpc.CircuitKey exit_htlc_circuit_key */ 2: + message.exitHtlcCircuitKey = CircuitKey.internalBinaryRead(reader, reader.uint32(), options, message.exitHtlcCircuitKey); + break; + case /* uint64 exit_htlc_amt */ 3: + message.exitHtlcAmt = reader.uint64().toBigInt(); + break; + case /* uint32 exit_htlc_expiry */ 4: + message.exitHtlcExpiry = reader.uint32(); + break; + case /* uint32 current_height */ 5: + message.currentHeight = reader.uint32(); + break; + case /* map exit_htlc_wire_custom_records */ 6: + this.binaryReadMap6(message.exitHtlcWireCustomRecords, reader, options); + break; + default: + let u = options.readUnknownField; + if (u === "throw") + throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`); + let d = reader.skip(wireType); + if (u !== false) + (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d); + } + } + return message; + } + private binaryReadMap6(map: HtlcModifyRequest["exitHtlcWireCustomRecords"], reader: IBinaryReader, options: BinaryReadOptions): void { + let len = reader.uint32(), end = reader.pos + len, key: keyof HtlcModifyRequest["exitHtlcWireCustomRecords"] | undefined, val: HtlcModifyRequest["exitHtlcWireCustomRecords"][any] | undefined; + while (reader.pos < end) { + let [fieldNo, wireType] = reader.tag(); + switch (fieldNo) { + case 1: + key = reader.uint64().toString(); + break; + case 2: + val = reader.bytes(); + break; + default: throw new globalThis.Error("unknown map entry field for invoicesrpc.HtlcModifyRequest.exit_htlc_wire_custom_records"); + } + } + map[key ?? "0"] = val ?? new Uint8Array(0); + } + internalBinaryWrite(message: HtlcModifyRequest, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter { + /* lnrpc.Invoice invoice = 1; */ + if (message.invoice) + Invoice.internalBinaryWrite(message.invoice, writer.tag(1, WireType.LengthDelimited).fork(), options).join(); + /* invoicesrpc.CircuitKey exit_htlc_circuit_key = 2; */ + if (message.exitHtlcCircuitKey) + CircuitKey.internalBinaryWrite(message.exitHtlcCircuitKey, writer.tag(2, WireType.LengthDelimited).fork(), options).join(); + /* uint64 exit_htlc_amt = 3; */ + if (message.exitHtlcAmt !== 0n) + writer.tag(3, WireType.Varint).uint64(message.exitHtlcAmt); + /* uint32 exit_htlc_expiry = 4; */ + if (message.exitHtlcExpiry !== 0) + writer.tag(4, WireType.Varint).uint32(message.exitHtlcExpiry); + /* uint32 current_height = 5; */ + if (message.currentHeight !== 0) + writer.tag(5, WireType.Varint).uint32(message.currentHeight); + /* map exit_htlc_wire_custom_records = 6; */ + for (let k of globalThis.Object.keys(message.exitHtlcWireCustomRecords)) + writer.tag(6, WireType.LengthDelimited).fork().tag(1, WireType.Varint).uint64(k).tag(2, WireType.LengthDelimited).bytes(message.exitHtlcWireCustomRecords[k]).join(); + let u = options.writeUnknownFields; + if (u !== false) + (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer); + return writer; + } +} +/** + * @generated MessageType for protobuf message invoicesrpc.HtlcModifyRequest + */ +export const HtlcModifyRequest = new HtlcModifyRequest$Type(); +// @generated message type with reflection information, may provide speed optimized methods +class HtlcModifyResponse$Type extends MessageType { + constructor() { + super("invoicesrpc.HtlcModifyResponse", [ + { no: 1, name: "circuit_key", kind: "message", T: () => CircuitKey }, + { no: 2, name: "amt_paid", kind: "scalar", opt: true, T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ }, + { no: 3, name: "cancel_set", kind: "scalar", T: 8 /*ScalarType.BOOL*/ } + ]); + } + create(value?: PartialMessage): HtlcModifyResponse { + const message = globalThis.Object.create((this.messagePrototype!)); + message.cancelSet = false; + if (value !== undefined) + reflectionMergePartial(this, message, value); + return message; + } + internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: HtlcModifyResponse): HtlcModifyResponse { + let message = target ?? this.create(), end = reader.pos + length; + while (reader.pos < end) { + let [fieldNo, wireType] = reader.tag(); + switch (fieldNo) { + case /* invoicesrpc.CircuitKey circuit_key */ 1: + message.circuitKey = CircuitKey.internalBinaryRead(reader, reader.uint32(), options, message.circuitKey); + break; + case /* optional uint64 amt_paid */ 2: + message.amtPaid = reader.uint64().toBigInt(); + break; + case /* bool cancel_set */ 3: + message.cancelSet = reader.bool(); + break; + default: + let u = options.readUnknownField; + if (u === "throw") + throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`); + let d = reader.skip(wireType); + if (u !== false) + (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d); + } + } + return message; + } + internalBinaryWrite(message: HtlcModifyResponse, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter { + /* invoicesrpc.CircuitKey circuit_key = 1; */ + if (message.circuitKey) + CircuitKey.internalBinaryWrite(message.circuitKey, writer.tag(1, WireType.LengthDelimited).fork(), options).join(); + /* optional uint64 amt_paid = 2; */ + if (message.amtPaid !== undefined) + writer.tag(2, WireType.Varint).uint64(message.amtPaid); + /* bool cancel_set = 3; */ + if (message.cancelSet !== false) + writer.tag(3, WireType.Varint).bool(message.cancelSet); + let u = options.writeUnknownFields; + if (u !== false) + (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer); + return writer; + } +} +/** + * @generated MessageType for protobuf message invoicesrpc.HtlcModifyResponse + */ +export const HtlcModifyResponse = new HtlcModifyResponse$Type(); /** * @generated ServiceType for protobuf service invoicesrpc.Invoices */ @@ -686,5 +1032,6 @@ export const Invoices = new ServiceType("invoicesrpc.Invoices", [ { name: "CancelInvoice", options: {}, I: CancelInvoiceMsg, O: CancelInvoiceResp }, { name: "AddHoldInvoice", options: {}, I: AddHoldInvoiceRequest, O: AddHoldInvoiceResp }, { name: "SettleInvoice", options: {}, I: SettleInvoiceMsg, O: SettleInvoiceResp }, - { name: "LookupInvoiceV2", options: {}, I: LookupInvoiceMsg, O: Invoice } + { name: "LookupInvoiceV2", options: {}, I: LookupInvoiceMsg, O: Invoice }, + { name: "HtlcModifier", serverStreaming: true, clientStreaming: true, options: {}, I: HtlcModifyResponse, O: HtlcModifyRequest } ]); diff --git a/proto/lnd/lightning.client.ts b/proto/lnd/lightning.client.ts index 746e7568..60b2e051 100644 --- a/proto/lnd/lightning.client.ts +++ b/proto/lnd/lightning.client.ts @@ -1,4 +1,4 @@ -// @generated by protobuf-ts 2.8.1 +// @generated by protobuf-ts 2.11.1 // @generated from protobuf file "lightning.proto" (package "lnrpc", syntax proto3) // tslint:disable import type { RpcTransport } from "@protobuf-ts/runtime-rpc"; @@ -10,7 +10,7 @@ import type { ListAliasesResponse } from "./lightning.js"; import type { ListAliasesRequest } from "./lightning.js"; import type { CustomMessage } from "./lightning.js"; import type { SubscribeCustomMessagesRequest } from "./lightning.js"; -import type { SendCustomMessageResponse } from "./lightning.js"; +import type { SendCustomMessageResponse } from "./lightning"; import type { SendCustomMessageRequest } from "./lightning.js"; import type { RPCMiddlewareRequest } from "./lightning.js"; import type { RPCMiddlewareResponse } from "./lightning.js"; @@ -46,7 +46,7 @@ import type { StopResponse } from "./lightning.js"; import type { StopRequest } from "./lightning.js"; import type { NetworkInfo } from "./lightning.js"; import type { NetworkInfoRequest } from "./lightning.js"; -import type { QueryRoutesResponse } from "./lightning.js"; +import type { QueryRoutesResponse } from "./lightning"; import type { QueryRoutesRequest } from "./lightning.js"; import type { NodeInfo } from "./lightning.js"; import type { NodeInfoRequest } from "./lightning.js"; @@ -56,18 +56,18 @@ import type { NodeMetricsResponse } from "./lightning.js"; import type { NodeMetricsRequest } from "./lightning.js"; import type { ChannelGraph } from "./lightning.js"; import type { ChannelGraphRequest } from "./lightning.js"; -import type { DeleteAllPaymentsResponse } from "./lightning.js"; +import type { DeleteAllPaymentsResponse } from "./lightning"; import type { DeleteAllPaymentsRequest } from "./lightning.js"; import type { DeletePaymentResponse } from "./lightning.js"; -import type { DeletePaymentRequest } from "./lightning.js"; +import type { DeletePaymentRequest } from "./lightning"; import type { ListPaymentsResponse } from "./lightning.js"; import type { ListPaymentsRequest } from "./lightning.js"; -import type { PayReq } from "./lightning.js"; -import type { PayReqString } from "./lightning.js"; +import type { PayReq } from "./lightning"; +import type { PayReqString } from "./lightning"; import type { InvoiceSubscription } from "./lightning.js"; -import type { PaymentHash } from "./lightning.js"; +import type { PaymentHash } from "./lightning"; import type { ListInvoiceResponse } from "./lightning.js"; -import type { ListInvoiceRequest } from "./lightning.js"; +import type { ListInvoiceRequest } from "./lightning"; import type { AddInvoiceResponse } from "./lightning.js"; import type { Invoice } from "./lightning.js"; import type { SendToRouteRequest } from "./lightning.js"; @@ -127,7 +127,7 @@ import type { EstimateFeeResponse } from "./lightning.js"; import type { EstimateFeeRequest } from "./lightning.js"; import type { TransactionDetails } from "./lightning.js"; import type { GetTransactionsRequest } from "./lightning.js"; -import type { ChannelBalanceResponse } from "./lightning.js"; +import type { ChannelBalanceResponse } from "./lightning"; import type { ChannelBalanceRequest } from "./lightning.js"; import { stackIntercept } from "@protobuf-ts/runtime-rpc"; import type { WalletBalanceResponse } from "./lightning.js"; @@ -163,7 +163,7 @@ export interface ILightningClient { * confirmed unspent outputs and all unconfirmed unspent outputs under control * of the wallet. * - * @generated from protobuf rpc: WalletBalance(lnrpc.WalletBalanceRequest) returns (lnrpc.WalletBalanceResponse); + * @generated from protobuf rpc: WalletBalance */ walletBalance(input: WalletBalanceRequest, options?: RpcOptions): UnaryCall; /** @@ -172,7 +172,7 @@ export interface ILightningClient { * categorized in local/remote, pending local/remote and unsettled local/remote * balances. * - * @generated from protobuf rpc: ChannelBalance(lnrpc.ChannelBalanceRequest) returns (lnrpc.ChannelBalanceResponse); + * @generated from protobuf rpc: ChannelBalance */ channelBalance(input: ChannelBalanceRequest, options?: RpcOptions): UnaryCall; /** @@ -180,7 +180,7 @@ export interface ILightningClient { * GetTransactions returns a list describing all the known transactions * relevant to the wallet. * - * @generated from protobuf rpc: GetTransactions(lnrpc.GetTransactionsRequest) returns (lnrpc.TransactionDetails); + * @generated from protobuf rpc: GetTransactions */ getTransactions(input: GetTransactionsRequest, options?: RpcOptions): UnaryCall; /** @@ -193,7 +193,7 @@ export interface ILightningClient { * map type doesn't appear in the REST API documentation because of a bug in * the grpc-gateway library. * - * @generated from protobuf rpc: EstimateFee(lnrpc.EstimateFeeRequest) returns (lnrpc.EstimateFeeResponse); + * @generated from protobuf rpc: EstimateFee */ estimateFee(input: EstimateFeeRequest, options?: RpcOptions): UnaryCall; /** @@ -204,7 +204,7 @@ export interface ILightningClient { * consult its fee model to determine a fee for the default confirmation * target. * - * @generated from protobuf rpc: SendCoins(lnrpc.SendCoinsRequest) returns (lnrpc.SendCoinsResponse); + * @generated from protobuf rpc: SendCoins */ sendCoins(input: SendCoinsRequest, options?: RpcOptions): UnaryCall; /** @@ -214,7 +214,7 @@ export interface ILightningClient { * ListUnspent returns a list of all utxos spendable by the wallet with a * number of confirmations between the specified minimum and maximum. * - * @generated from protobuf rpc: ListUnspent(lnrpc.ListUnspentRequest) returns (lnrpc.ListUnspentResponse); + * @generated from protobuf rpc: ListUnspent */ listUnspent(input: ListUnspentRequest, options?: RpcOptions): UnaryCall; /** @@ -223,7 +223,7 @@ export interface ILightningClient { * the client in which any newly discovered transactions relevant to the * wallet are sent over. * - * @generated from protobuf rpc: SubscribeTransactions(lnrpc.GetTransactionsRequest) returns (stream lnrpc.Transaction); + * @generated from protobuf rpc: SubscribeTransactions */ subscribeTransactions(input: GetTransactionsRequest, options?: RpcOptions): ServerStreamingCall; /** @@ -233,14 +233,14 @@ export interface ILightningClient { * the internal wallet will consult its fee model to determine a fee for the * default confirmation target. * - * @generated from protobuf rpc: SendMany(lnrpc.SendManyRequest) returns (lnrpc.SendManyResponse); + * @generated from protobuf rpc: SendMany */ sendMany(input: SendManyRequest, options?: RpcOptions): UnaryCall; /** * lncli: `newaddress` * NewAddress creates a new address under control of the local wallet. * - * @generated from protobuf rpc: NewAddress(lnrpc.NewAddressRequest) returns (lnrpc.NewAddressResponse); + * @generated from protobuf rpc: NewAddress */ newAddress(input: NewAddressRequest, options?: RpcOptions): UnaryCall; /** @@ -249,7 +249,7 @@ export interface ILightningClient { * signature string is `zbase32` encoded and pubkey recoverable, meaning that * only the message digest and signature are needed for verification. * - * @generated from protobuf rpc: SignMessage(lnrpc.SignMessageRequest) returns (lnrpc.SignMessageResponse); + * @generated from protobuf rpc: SignMessage */ signMessage(input: SignMessageRequest, options?: RpcOptions): UnaryCall; /** @@ -261,7 +261,7 @@ export interface ILightningClient { * channel database. In addition to returning the validity of the signature, * VerifyMessage also returns the recovered pubkey from the signature. * - * @generated from protobuf rpc: VerifyMessage(lnrpc.VerifyMessageRequest) returns (lnrpc.VerifyMessageResponse); + * @generated from protobuf rpc: VerifyMessage */ verifyMessage(input: VerifyMessageRequest, options?: RpcOptions): UnaryCall; /** @@ -270,7 +270,7 @@ export interface ILightningClient { * the networking level, and is used for communication between nodes. This is * distinct from establishing a channel with a peer. * - * @generated from protobuf rpc: ConnectPeer(lnrpc.ConnectPeerRequest) returns (lnrpc.ConnectPeerResponse); + * @generated from protobuf rpc: ConnectPeer */ connectPeer(input: ConnectPeerRequest, options?: RpcOptions): UnaryCall; /** @@ -279,14 +279,14 @@ export interface ILightningClient { * given pubKey. In the case that we currently have a pending or active channel * with the target peer, then this action will be not be allowed. * - * @generated from protobuf rpc: DisconnectPeer(lnrpc.DisconnectPeerRequest) returns (lnrpc.DisconnectPeerResponse); + * @generated from protobuf rpc: DisconnectPeer */ disconnectPeer(input: DisconnectPeerRequest, options?: RpcOptions): UnaryCall; /** * lncli: `listpeers` * ListPeers returns a verbose listing of all currently active peers. * - * @generated from protobuf rpc: ListPeers(lnrpc.ListPeersRequest) returns (lnrpc.ListPeersResponse); + * @generated from protobuf rpc: ListPeers */ listPeers(input: ListPeersRequest, options?: RpcOptions): UnaryCall; /** @@ -295,7 +295,7 @@ export interface ILightningClient { * the client in which any events relevant to the state of peers are sent * over. Events include peers going online and offline. * - * @generated from protobuf rpc: SubscribePeerEvents(lnrpc.PeerEventSubscription) returns (stream lnrpc.PeerEvent); + * @generated from protobuf rpc: SubscribePeerEvents */ subscribePeerEvents(input: PeerEventSubscription, options?: RpcOptions): ServerStreamingCall; /** @@ -304,7 +304,7 @@ export interface ILightningClient { * it's identity pubkey, alias, the chains it is connected to, and information * concerning the number of open+pending channels. * - * @generated from protobuf rpc: GetInfo(lnrpc.GetInfoRequest) returns (lnrpc.GetInfoResponse); + * @generated from protobuf rpc: GetInfo */ getInfo(input: GetInfoRequest, options?: RpcOptions): UnaryCall; /** @@ -313,7 +313,7 @@ export interface ILightningClient { * and its subsystems. This includes the full configuration and the latest log * entries from the log file. * - * @generated from protobuf rpc: GetDebugInfo(lnrpc.GetDebugInfoRequest) returns (lnrpc.GetDebugInfoResponse); + * @generated from protobuf rpc: GetDebugInfo */ getDebugInfo(input: GetDebugInfoRequest, options?: RpcOptions): UnaryCall; /** @@ -322,7 +322,7 @@ export interface ILightningClient { * whether it's in a recovery mode, whether the recovery is finished, and the * progress made so far. * - * @generated from protobuf rpc: GetRecoveryInfo(lnrpc.GetRecoveryInfoRequest) returns (lnrpc.GetRecoveryInfoResponse); + * @generated from protobuf rpc: GetRecoveryInfo */ getRecoveryInfo(input: GetRecoveryInfoRequest, options?: RpcOptions): UnaryCall; // TODO(roasbeef): merge with below with bool? @@ -334,7 +334,7 @@ export interface ILightningClient { * workflow and is waiting for confirmations for the funding txn, or is in the * process of closure, either initiated cooperatively or non-cooperatively. * - * @generated from protobuf rpc: PendingChannels(lnrpc.PendingChannelsRequest) returns (lnrpc.PendingChannelsResponse); + * @generated from protobuf rpc: PendingChannels */ pendingChannels(input: PendingChannelsRequest, options?: RpcOptions): UnaryCall; /** @@ -342,7 +342,7 @@ export interface ILightningClient { * ListChannels returns a description of all the open channels that this node * is a participant in. * - * @generated from protobuf rpc: ListChannels(lnrpc.ListChannelsRequest) returns (lnrpc.ListChannelsResponse); + * @generated from protobuf rpc: ListChannels */ listChannels(input: ListChannelsRequest, options?: RpcOptions): UnaryCall; /** @@ -352,7 +352,7 @@ export interface ILightningClient { * sent over. Events include new active channels, inactive channels, and closed * channels. * - * @generated from protobuf rpc: SubscribeChannelEvents(lnrpc.ChannelEventSubscription) returns (stream lnrpc.ChannelEventUpdate); + * @generated from protobuf rpc: SubscribeChannelEvents */ subscribeChannelEvents(input: ChannelEventSubscription, options?: RpcOptions): ServerStreamingCall; /** @@ -360,7 +360,7 @@ export interface ILightningClient { * ClosedChannels returns a description of all the closed channels that * this node was a participant in. * - * @generated from protobuf rpc: ClosedChannels(lnrpc.ClosedChannelsRequest) returns (lnrpc.ClosedChannelsResponse); + * @generated from protobuf rpc: ClosedChannels */ closedChannels(input: ClosedChannelsRequest, options?: RpcOptions): UnaryCall; /** @@ -370,7 +370,7 @@ export interface ILightningClient { * other sync calls, all byte slices are intended to be populated as hex * encoded strings. * - * @generated from protobuf rpc: OpenChannelSync(lnrpc.OpenChannelRequest) returns (lnrpc.ChannelPoint); + * @generated from protobuf rpc: OpenChannelSync */ openChannelSync(input: OpenChannelRequest, options?: RpcOptions): UnaryCall; /** @@ -384,7 +384,7 @@ export interface ILightningClient { * arguments specified in the OpenChannelRequest, this pending channel ID can * then be used to manually progress the channel funding flow. * - * @generated from protobuf rpc: OpenChannel(lnrpc.OpenChannelRequest) returns (stream lnrpc.OpenStatusUpdate); + * @generated from protobuf rpc: OpenChannel */ openChannel(input: OpenChannelRequest, options?: RpcOptions): ServerStreamingCall; /** @@ -395,7 +395,7 @@ export interface ILightningClient { * This is the safer variant of using PSBTs to manually fund a batch of * channels through the OpenChannel RPC. * - * @generated from protobuf rpc: BatchOpenChannel(lnrpc.BatchOpenChannelRequest) returns (lnrpc.BatchOpenChannelResponse); + * @generated from protobuf rpc: BatchOpenChannel */ batchOpenChannel(input: BatchOpenChannelRequest, options?: RpcOptions): UnaryCall; /** @@ -409,7 +409,7 @@ export interface ILightningClient { * Alternatively, this can be used to interactively drive PSBT signing for * funding for partially complete funding transactions. * - * @generated from protobuf rpc: FundingStateStep(lnrpc.FundingTransitionMsg) returns (lnrpc.FundingStateStepResp); + * @generated from protobuf rpc: FundingStateStep */ fundingStateStep(input: FundingTransitionMsg, options?: RpcOptions): UnaryCall; /** @@ -420,7 +420,7 @@ export interface ILightningClient { * node operators to specify their own criteria for accepting inbound channels * through a single persistent connection. * - * @generated from protobuf rpc: ChannelAcceptor(stream lnrpc.ChannelAcceptResponse) returns (stream lnrpc.ChannelAcceptRequest); + * @generated from protobuf rpc: ChannelAcceptor */ channelAcceptor(options?: RpcOptions): DuplexStreamingCall; /** @@ -433,7 +433,7 @@ export interface ILightningClient { * closure transaction is confirmed, or a manual fee rate. If neither are * specified, then a default lax, block confirmation target is used. * - * @generated from protobuf rpc: CloseChannel(lnrpc.CloseChannelRequest) returns (stream lnrpc.CloseStatusUpdate); + * @generated from protobuf rpc: CloseChannel */ closeChannel(input: CloseChannelRequest, options?: RpcOptions): ServerStreamingCall; /** @@ -445,7 +445,7 @@ export interface ILightningClient { * never broadcast. Only available for non-externally funded channels in dev * build. * - * @generated from protobuf rpc: AbandonChannel(lnrpc.AbandonChannelRequest) returns (lnrpc.AbandonChannelResponse); + * @generated from protobuf rpc: AbandonChannel */ abandonChannel(input: AbandonChannelRequest, options?: RpcOptions): UnaryCall; /** @@ -457,17 +457,18 @@ export interface ILightningClient { * Network with a single persistent connection. * * @deprecated - * @generated from protobuf rpc: SendPayment(stream lnrpc.SendRequest) returns (stream lnrpc.SendResponse); + * @generated from protobuf rpc: SendPayment */ sendPayment(options?: RpcOptions): DuplexStreamingCall; /** * - * SendPaymentSync is the synchronous non-streaming version of SendPayment. - * This RPC is intended to be consumed by clients of the REST proxy. - * Additionally, this RPC expects the destination's public key and the payment - * hash (if any) to be encoded as hex strings. + * Deprecated, use routerrpc.SendPaymentV2. SendPaymentSync is the synchronous + * non-streaming version of SendPayment. This RPC is intended to be consumed by + * clients of the REST proxy. Additionally, this RPC expects the destination's + * public key and the payment hash (if any) to be encoded as hex strings. * - * @generated from protobuf rpc: SendPaymentSync(lnrpc.SendRequest) returns (lnrpc.SendResponse); + * @deprecated + * @generated from protobuf rpc: SendPaymentSync */ sendPaymentSync(input: SendRequest, options?: RpcOptions): UnaryCall; /** @@ -479,15 +480,17 @@ export interface ILightningClient { * swaps. * * @deprecated - * @generated from protobuf rpc: SendToRoute(stream lnrpc.SendToRouteRequest) returns (stream lnrpc.SendResponse); + * @generated from protobuf rpc: SendToRoute */ sendToRoute(options?: RpcOptions): DuplexStreamingCall; /** * - * SendToRouteSync is a synchronous version of SendToRoute. It Will block - * until the payment either fails or succeeds. + * Deprecated, use routerrpc.SendToRouteV2. SendToRouteSync is a synchronous + * version of SendToRoute. It Will block until the payment either fails or + * succeeds. * - * @generated from protobuf rpc: SendToRouteSync(lnrpc.SendToRouteRequest) returns (lnrpc.SendResponse); + * @deprecated + * @generated from protobuf rpc: SendToRouteSync */ sendToRouteSync(input: SendToRouteRequest, options?: RpcOptions): UnaryCall; /** @@ -496,7 +499,7 @@ export interface ILightningClient { * duplicated invoices are rejected, therefore all invoices *must* have a * unique payment preimage. * - * @generated from protobuf rpc: AddInvoice(lnrpc.Invoice) returns (lnrpc.AddInvoiceResponse); + * @generated from protobuf rpc: AddInvoice */ addInvoice(input: Invoice, options?: RpcOptions): UnaryCall; /** @@ -509,7 +512,7 @@ export interface ILightningClient { * next request. By default, the first 100 invoices created will be returned. * Backwards pagination is also supported through the Reversed flag. * - * @generated from protobuf rpc: ListInvoices(lnrpc.ListInvoiceRequest) returns (lnrpc.ListInvoiceResponse); + * @generated from protobuf rpc: ListInvoices */ listInvoices(input: ListInvoiceRequest, options?: RpcOptions): UnaryCall; /** @@ -518,7 +521,7 @@ export interface ILightningClient { * The passed payment hash *must* be exactly 32 bytes, if not, an error is * returned. * - * @generated from protobuf rpc: LookupInvoice(lnrpc.PaymentHash) returns (lnrpc.Invoice); + * @generated from protobuf rpc: LookupInvoice */ lookupInvoice(input: PaymentHash, options?: RpcOptions): UnaryCall; /** @@ -533,7 +536,7 @@ export interface ILightningClient { * of these fields can be set. If no fields are set, then we'll only send out * the latest add/settle events. * - * @generated from protobuf rpc: SubscribeInvoices(lnrpc.InvoiceSubscription) returns (stream lnrpc.Invoice); + * @generated from protobuf rpc: SubscribeInvoices */ subscribeInvoices(input: InvoiceSubscription, options?: RpcOptions): ServerStreamingCall; /** @@ -542,14 +545,14 @@ export interface ILightningClient { * it, returning a full description of the conditions encoded within the * payment request. * - * @generated from protobuf rpc: DecodePayReq(lnrpc.PayReqString) returns (lnrpc.PayReq); + * @generated from protobuf rpc: DecodePayReq */ decodePayReq(input: PayReqString, options?: RpcOptions): UnaryCall; /** * lncli: `listpayments` * ListPayments returns a list of all outgoing payments. * - * @generated from protobuf rpc: ListPayments(lnrpc.ListPaymentsRequest) returns (lnrpc.ListPaymentsResponse); + * @generated from protobuf rpc: ListPayments */ listPayments(input: ListPaymentsRequest, options?: RpcOptions): UnaryCall; /** @@ -557,7 +560,7 @@ export interface ILightningClient { * DeletePayment deletes an outgoing payment from DB. Note that it will not * attempt to delete an In-Flight payment, since that would be unsafe. * - * @generated from protobuf rpc: DeletePayment(lnrpc.DeletePaymentRequest) returns (lnrpc.DeletePaymentResponse); + * @generated from protobuf rpc: DeletePayment */ deletePayment(input: DeletePaymentRequest, options?: RpcOptions): UnaryCall; /** @@ -565,7 +568,7 @@ export interface ILightningClient { * DeleteAllPayments deletes all outgoing payments from DB. Note that it will * not attempt to delete In-Flight payments, since that would be unsafe. * - * @generated from protobuf rpc: DeleteAllPayments(lnrpc.DeleteAllPaymentsRequest) returns (lnrpc.DeleteAllPaymentsResponse); + * @generated from protobuf rpc: DeleteAllPayments */ deleteAllPayments(input: DeleteAllPaymentsRequest, options?: RpcOptions): UnaryCall; /** @@ -577,7 +580,7 @@ export interface ILightningClient { * the node directional specific routing policy which includes: the time lock * delta, fee information, etc. * - * @generated from protobuf rpc: DescribeGraph(lnrpc.ChannelGraphRequest) returns (lnrpc.ChannelGraph); + * @generated from protobuf rpc: DescribeGraph */ describeGraph(input: ChannelGraphRequest, options?: RpcOptions): UnaryCall; /** @@ -585,7 +588,7 @@ export interface ILightningClient { * GetNodeMetrics returns node metrics calculated from the graph. Currently * the only supported metric is betweenness centrality of individual nodes. * - * @generated from protobuf rpc: GetNodeMetrics(lnrpc.NodeMetricsRequest) returns (lnrpc.NodeMetricsResponse); + * @generated from protobuf rpc: GetNodeMetrics */ getNodeMetrics(input: NodeMetricsRequest, options?: RpcOptions): UnaryCall; /** @@ -595,7 +598,7 @@ export interface ILightningClient { * uniquely identifies the location of transaction's funding output within the * blockchain. * - * @generated from protobuf rpc: GetChanInfo(lnrpc.ChanInfoRequest) returns (lnrpc.ChannelEdge); + * @generated from protobuf rpc: GetChanInfo */ getChanInfo(input: ChanInfoRequest, options?: RpcOptions): UnaryCall; /** @@ -603,7 +606,7 @@ export interface ILightningClient { * GetNodeInfo returns the latest advertised, aggregated, and authenticated * channel information for the specified node identified by its public key. * - * @generated from protobuf rpc: GetNodeInfo(lnrpc.NodeInfoRequest) returns (lnrpc.NodeInfo); + * @generated from protobuf rpc: GetNodeInfo */ getNodeInfo(input: NodeInfoRequest, options?: RpcOptions): UnaryCall; /** @@ -619,7 +622,7 @@ export interface ILightningClient { * to the URL. Unfortunately this map type doesn't appear in the REST API * documentation because of a bug in the grpc-gateway library. * - * @generated from protobuf rpc: QueryRoutes(lnrpc.QueryRoutesRequest) returns (lnrpc.QueryRoutesResponse); + * @generated from protobuf rpc: QueryRoutes */ queryRoutes(input: QueryRoutesRequest, options?: RpcOptions): UnaryCall; /** @@ -627,7 +630,7 @@ export interface ILightningClient { * GetNetworkInfo returns some basic stats about the known channel graph from * the point of view of the node. * - * @generated from protobuf rpc: GetNetworkInfo(lnrpc.NetworkInfoRequest) returns (lnrpc.NetworkInfo); + * @generated from protobuf rpc: GetNetworkInfo */ getNetworkInfo(input: NetworkInfoRequest, options?: RpcOptions): UnaryCall; /** @@ -635,7 +638,7 @@ export interface ILightningClient { * StopDaemon will send a shutdown request to the interrupt handler, triggering * a graceful shutdown of the daemon. * - * @generated from protobuf rpc: StopDaemon(lnrpc.StopRequest) returns (lnrpc.StopResponse); + * @generated from protobuf rpc: StopDaemon */ stopDaemon(input: StopRequest, options?: RpcOptions): UnaryCall; /** @@ -647,7 +650,7 @@ export interface ILightningClient { * channels being advertised, updates in the routing policy for a directional * channel edge, and when channels are closed on-chain. * - * @generated from protobuf rpc: SubscribeChannelGraph(lnrpc.GraphTopologySubscription) returns (stream lnrpc.GraphTopologyUpdate); + * @generated from protobuf rpc: SubscribeChannelGraph */ subscribeChannelGraph(input: GraphTopologySubscription, options?: RpcOptions): ServerStreamingCall; /** @@ -657,7 +660,7 @@ export interface ILightningClient { * level, or in a granular fashion to specify the logging for a target * sub-system. * - * @generated from protobuf rpc: DebugLevel(lnrpc.DebugLevelRequest) returns (lnrpc.DebugLevelResponse); + * @generated from protobuf rpc: DebugLevel */ debugLevel(input: DebugLevelRequest, options?: RpcOptions): UnaryCall; /** @@ -665,7 +668,7 @@ export interface ILightningClient { * FeeReport allows the caller to obtain a report detailing the current fee * schedule enforced by the node globally for each channel. * - * @generated from protobuf rpc: FeeReport(lnrpc.FeeReportRequest) returns (lnrpc.FeeReportResponse); + * @generated from protobuf rpc: FeeReport */ feeReport(input: FeeReportRequest, options?: RpcOptions): UnaryCall; /** @@ -673,7 +676,7 @@ export interface ILightningClient { * UpdateChannelPolicy allows the caller to update the fee schedule and * channel policies for all channels globally, or a particular channel. * - * @generated from protobuf rpc: UpdateChannelPolicy(lnrpc.PolicyUpdateRequest) returns (lnrpc.PolicyUpdateResponse); + * @generated from protobuf rpc: UpdateChannelPolicy */ updateChannelPolicy(input: PolicyUpdateRequest, options?: RpcOptions): UnaryCall; /** @@ -690,7 +693,7 @@ export interface ILightningClient { * the index offset of the last entry. The index offset can be provided to the * request to allow the caller to skip a series of records. * - * @generated from protobuf rpc: ForwardingHistory(lnrpc.ForwardingHistoryRequest) returns (lnrpc.ForwardingHistoryResponse); + * @generated from protobuf rpc: ForwardingHistory */ forwardingHistory(input: ForwardingHistoryRequest, options?: RpcOptions): UnaryCall; /** @@ -702,7 +705,7 @@ export interface ILightningClient { * method once lnd is running, or via the InitWallet and UnlockWallet methods * from the WalletUnlocker service. * - * @generated from protobuf rpc: ExportChannelBackup(lnrpc.ExportChannelBackupRequest) returns (lnrpc.ChannelBackup); + * @generated from protobuf rpc: ExportChannelBackup */ exportChannelBackup(input: ExportChannelBackupRequest, options?: RpcOptions): UnaryCall; /** @@ -713,7 +716,7 @@ export interface ILightningClient { * as well, which contains a single encrypted blob containing the backups of * each channel. * - * @generated from protobuf rpc: ExportAllChannelBackups(lnrpc.ChanBackupExportRequest) returns (lnrpc.ChanBackupSnapshot); + * @generated from protobuf rpc: ExportAllChannelBackups */ exportAllChannelBackups(input: ChanBackupExportRequest, options?: RpcOptions): UnaryCall; /** @@ -722,7 +725,7 @@ export interface ILightningClient { * snapshot. This method will accept either a packed Single or a packed Multi. * Specifying both will result in an error. * - * @generated from protobuf rpc: VerifyChanBackup(lnrpc.ChanBackupSnapshot) returns (lnrpc.VerifyChanBackupResponse); + * @generated from protobuf rpc: VerifyChanBackup */ verifyChanBackup(input: ChanBackupSnapshot, options?: RpcOptions): UnaryCall; /** @@ -732,7 +735,7 @@ export interface ILightningClient { * remaining within the channel. If we are able to unpack the backup, then the * new channel will be shown under listchannels, as well as pending channels. * - * @generated from protobuf rpc: RestoreChannelBackups(lnrpc.RestoreChanBackupRequest) returns (lnrpc.RestoreBackupResponse); + * @generated from protobuf rpc: RestoreChannelBackups */ restoreChannelBackups(input: RestoreChanBackupRequest, options?: RpcOptions): UnaryCall; /** @@ -745,7 +748,7 @@ export interface ILightningClient { * ups, but the updated set of encrypted multi-chan backups with the closed * channel(s) removed. * - * @generated from protobuf rpc: SubscribeChannelBackups(lnrpc.ChannelBackupSubscription) returns (stream lnrpc.ChanBackupSnapshot); + * @generated from protobuf rpc: SubscribeChannelBackups */ subscribeChannelBackups(input: ChannelBackupSubscription, options?: RpcOptions): ServerStreamingCall; /** @@ -754,14 +757,14 @@ export interface ILightningClient { * write permissions. No first-party caveats are added since this can be done * offline. * - * @generated from protobuf rpc: BakeMacaroon(lnrpc.BakeMacaroonRequest) returns (lnrpc.BakeMacaroonResponse); + * @generated from protobuf rpc: BakeMacaroon */ bakeMacaroon(input: BakeMacaroonRequest, options?: RpcOptions): UnaryCall; /** * lncli: `listmacaroonids` * ListMacaroonIDs returns all root key IDs that are in use. * - * @generated from protobuf rpc: ListMacaroonIDs(lnrpc.ListMacaroonIDsRequest) returns (lnrpc.ListMacaroonIDsResponse); + * @generated from protobuf rpc: ListMacaroonIDs */ listMacaroonIDs(input: ListMacaroonIDsRequest, options?: RpcOptions): UnaryCall; /** @@ -769,7 +772,7 @@ export interface ILightningClient { * DeleteMacaroonID deletes the specified macaroon ID and invalidates all * macaroons derived from that ID. * - * @generated from protobuf rpc: DeleteMacaroonID(lnrpc.DeleteMacaroonIDRequest) returns (lnrpc.DeleteMacaroonIDResponse); + * @generated from protobuf rpc: DeleteMacaroonID */ deleteMacaroonID(input: DeleteMacaroonIDRequest, options?: RpcOptions): UnaryCall; /** @@ -777,7 +780,7 @@ export interface ILightningClient { * ListPermissions lists all RPC method URIs and their required macaroon * permissions to access them. * - * @generated from protobuf rpc: ListPermissions(lnrpc.ListPermissionsRequest) returns (lnrpc.ListPermissionsResponse); + * @generated from protobuf rpc: ListPermissions */ listPermissions(input: ListPermissionsRequest, options?: RpcOptions): UnaryCall; /** @@ -786,7 +789,7 @@ export interface ILightningClient { * imposed on the macaroon and that the macaroon is authorized to follow the * provided permissions. * - * @generated from protobuf rpc: CheckMacaroonPermissions(lnrpc.CheckMacPermRequest) returns (lnrpc.CheckMacPermResponse); + * @generated from protobuf rpc: CheckMacaroonPermissions */ checkMacaroonPermissions(input: CheckMacPermRequest, options?: RpcOptions): UnaryCall; /** @@ -804,14 +807,14 @@ export interface ILightningClient { * allowed to modify any responses. As a security measure, _no_ middleware can * modify responses for requests made with _unencumbered_ macaroons! * - * @generated from protobuf rpc: RegisterRPCMiddleware(stream lnrpc.RPCMiddlewareResponse) returns (stream lnrpc.RPCMiddlewareRequest); + * @generated from protobuf rpc: RegisterRPCMiddleware */ registerRPCMiddleware(options?: RpcOptions): DuplexStreamingCall; /** * lncli: `sendcustom` * SendCustomMessage sends a custom peer message. * - * @generated from protobuf rpc: SendCustomMessage(lnrpc.SendCustomMessageRequest) returns (lnrpc.SendCustomMessageResponse); + * @generated from protobuf rpc: SendCustomMessage */ sendCustomMessage(input: SendCustomMessageRequest, options?: RpcOptions): UnaryCall; /** @@ -823,7 +826,7 @@ export interface ILightningClient { * needs to be compiled with the `dev` build tag, and the message type to * override should be specified in lnd's experimental protocol configuration. * - * @generated from protobuf rpc: SubscribeCustomMessages(lnrpc.SubscribeCustomMessagesRequest) returns (stream lnrpc.CustomMessage); + * @generated from protobuf rpc: SubscribeCustomMessages */ subscribeCustomMessages(input: SubscribeCustomMessagesRequest, options?: RpcOptions): ServerStreamingCall; /** @@ -832,7 +835,7 @@ export interface ILightningClient { * their confirmed SCID (if it exists) and/or the base SCID (in the case of * zero conf). * - * @generated from protobuf rpc: ListAliases(lnrpc.ListAliasesRequest) returns (lnrpc.ListAliasesResponse); + * @generated from protobuf rpc: ListAliases */ listAliases(input: ListAliasesRequest, options?: RpcOptions): UnaryCall; /** @@ -841,7 +844,7 @@ export interface ILightningClient { * If the htlc has no final resolution yet, a NotFound grpc status code is * returned. * - * @generated from protobuf rpc: LookupHtlcResolution(lnrpc.LookupHtlcResolutionRequest) returns (lnrpc.LookupHtlcResolutionResponse); + * @generated from protobuf rpc: LookupHtlcResolution */ lookupHtlcResolution(input: LookupHtlcResolutionRequest, options?: RpcOptions): UnaryCall; } @@ -879,7 +882,7 @@ export class LightningClient implements ILightningClient, ServiceInfo { * confirmed unspent outputs and all unconfirmed unspent outputs under control * of the wallet. * - * @generated from protobuf rpc: WalletBalance(lnrpc.WalletBalanceRequest) returns (lnrpc.WalletBalanceResponse); + * @generated from protobuf rpc: WalletBalance */ walletBalance(input: WalletBalanceRequest, options?: RpcOptions): UnaryCall { const method = this.methods[0], opt = this._transport.mergeOptions(options); @@ -891,7 +894,7 @@ export class LightningClient implements ILightningClient, ServiceInfo { * categorized in local/remote, pending local/remote and unsettled local/remote * balances. * - * @generated from protobuf rpc: ChannelBalance(lnrpc.ChannelBalanceRequest) returns (lnrpc.ChannelBalanceResponse); + * @generated from protobuf rpc: ChannelBalance */ channelBalance(input: ChannelBalanceRequest, options?: RpcOptions): UnaryCall { const method = this.methods[1], opt = this._transport.mergeOptions(options); @@ -902,7 +905,7 @@ export class LightningClient implements ILightningClient, ServiceInfo { * GetTransactions returns a list describing all the known transactions * relevant to the wallet. * - * @generated from protobuf rpc: GetTransactions(lnrpc.GetTransactionsRequest) returns (lnrpc.TransactionDetails); + * @generated from protobuf rpc: GetTransactions */ getTransactions(input: GetTransactionsRequest, options?: RpcOptions): UnaryCall { const method = this.methods[2], opt = this._transport.mergeOptions(options); @@ -918,7 +921,7 @@ export class LightningClient implements ILightningClient, ServiceInfo { * map type doesn't appear in the REST API documentation because of a bug in * the grpc-gateway library. * - * @generated from protobuf rpc: EstimateFee(lnrpc.EstimateFeeRequest) returns (lnrpc.EstimateFeeResponse); + * @generated from protobuf rpc: EstimateFee */ estimateFee(input: EstimateFeeRequest, options?: RpcOptions): UnaryCall { const method = this.methods[3], opt = this._transport.mergeOptions(options); @@ -932,7 +935,7 @@ export class LightningClient implements ILightningClient, ServiceInfo { * consult its fee model to determine a fee for the default confirmation * target. * - * @generated from protobuf rpc: SendCoins(lnrpc.SendCoinsRequest) returns (lnrpc.SendCoinsResponse); + * @generated from protobuf rpc: SendCoins */ sendCoins(input: SendCoinsRequest, options?: RpcOptions): UnaryCall { const method = this.methods[4], opt = this._transport.mergeOptions(options); @@ -945,7 +948,7 @@ export class LightningClient implements ILightningClient, ServiceInfo { * ListUnspent returns a list of all utxos spendable by the wallet with a * number of confirmations between the specified minimum and maximum. * - * @generated from protobuf rpc: ListUnspent(lnrpc.ListUnspentRequest) returns (lnrpc.ListUnspentResponse); + * @generated from protobuf rpc: ListUnspent */ listUnspent(input: ListUnspentRequest, options?: RpcOptions): UnaryCall { const method = this.methods[5], opt = this._transport.mergeOptions(options); @@ -957,7 +960,7 @@ export class LightningClient implements ILightningClient, ServiceInfo { * the client in which any newly discovered transactions relevant to the * wallet are sent over. * - * @generated from protobuf rpc: SubscribeTransactions(lnrpc.GetTransactionsRequest) returns (stream lnrpc.Transaction); + * @generated from protobuf rpc: SubscribeTransactions */ subscribeTransactions(input: GetTransactionsRequest, options?: RpcOptions): ServerStreamingCall { const method = this.methods[6], opt = this._transport.mergeOptions(options); @@ -970,7 +973,7 @@ export class LightningClient implements ILightningClient, ServiceInfo { * the internal wallet will consult its fee model to determine a fee for the * default confirmation target. * - * @generated from protobuf rpc: SendMany(lnrpc.SendManyRequest) returns (lnrpc.SendManyResponse); + * @generated from protobuf rpc: SendMany */ sendMany(input: SendManyRequest, options?: RpcOptions): UnaryCall { const method = this.methods[7], opt = this._transport.mergeOptions(options); @@ -980,7 +983,7 @@ export class LightningClient implements ILightningClient, ServiceInfo { * lncli: `newaddress` * NewAddress creates a new address under control of the local wallet. * - * @generated from protobuf rpc: NewAddress(lnrpc.NewAddressRequest) returns (lnrpc.NewAddressResponse); + * @generated from protobuf rpc: NewAddress */ newAddress(input: NewAddressRequest, options?: RpcOptions): UnaryCall { const method = this.methods[8], opt = this._transport.mergeOptions(options); @@ -992,7 +995,7 @@ export class LightningClient implements ILightningClient, ServiceInfo { * signature string is `zbase32` encoded and pubkey recoverable, meaning that * only the message digest and signature are needed for verification. * - * @generated from protobuf rpc: SignMessage(lnrpc.SignMessageRequest) returns (lnrpc.SignMessageResponse); + * @generated from protobuf rpc: SignMessage */ signMessage(input: SignMessageRequest, options?: RpcOptions): UnaryCall { const method = this.methods[9], opt = this._transport.mergeOptions(options); @@ -1007,7 +1010,7 @@ export class LightningClient implements ILightningClient, ServiceInfo { * channel database. In addition to returning the validity of the signature, * VerifyMessage also returns the recovered pubkey from the signature. * - * @generated from protobuf rpc: VerifyMessage(lnrpc.VerifyMessageRequest) returns (lnrpc.VerifyMessageResponse); + * @generated from protobuf rpc: VerifyMessage */ verifyMessage(input: VerifyMessageRequest, options?: RpcOptions): UnaryCall { const method = this.methods[10], opt = this._transport.mergeOptions(options); @@ -1019,7 +1022,7 @@ export class LightningClient implements ILightningClient, ServiceInfo { * the networking level, and is used for communication between nodes. This is * distinct from establishing a channel with a peer. * - * @generated from protobuf rpc: ConnectPeer(lnrpc.ConnectPeerRequest) returns (lnrpc.ConnectPeerResponse); + * @generated from protobuf rpc: ConnectPeer */ connectPeer(input: ConnectPeerRequest, options?: RpcOptions): UnaryCall { const method = this.methods[11], opt = this._transport.mergeOptions(options); @@ -1031,7 +1034,7 @@ export class LightningClient implements ILightningClient, ServiceInfo { * given pubKey. In the case that we currently have a pending or active channel * with the target peer, then this action will be not be allowed. * - * @generated from protobuf rpc: DisconnectPeer(lnrpc.DisconnectPeerRequest) returns (lnrpc.DisconnectPeerResponse); + * @generated from protobuf rpc: DisconnectPeer */ disconnectPeer(input: DisconnectPeerRequest, options?: RpcOptions): UnaryCall { const method = this.methods[12], opt = this._transport.mergeOptions(options); @@ -1041,7 +1044,7 @@ export class LightningClient implements ILightningClient, ServiceInfo { * lncli: `listpeers` * ListPeers returns a verbose listing of all currently active peers. * - * @generated from protobuf rpc: ListPeers(lnrpc.ListPeersRequest) returns (lnrpc.ListPeersResponse); + * @generated from protobuf rpc: ListPeers */ listPeers(input: ListPeersRequest, options?: RpcOptions): UnaryCall { const method = this.methods[13], opt = this._transport.mergeOptions(options); @@ -1053,7 +1056,7 @@ export class LightningClient implements ILightningClient, ServiceInfo { * the client in which any events relevant to the state of peers are sent * over. Events include peers going online and offline. * - * @generated from protobuf rpc: SubscribePeerEvents(lnrpc.PeerEventSubscription) returns (stream lnrpc.PeerEvent); + * @generated from protobuf rpc: SubscribePeerEvents */ subscribePeerEvents(input: PeerEventSubscription, options?: RpcOptions): ServerStreamingCall { const method = this.methods[14], opt = this._transport.mergeOptions(options); @@ -1065,7 +1068,7 @@ export class LightningClient implements ILightningClient, ServiceInfo { * it's identity pubkey, alias, the chains it is connected to, and information * concerning the number of open+pending channels. * - * @generated from protobuf rpc: GetInfo(lnrpc.GetInfoRequest) returns (lnrpc.GetInfoResponse); + * @generated from protobuf rpc: GetInfo */ getInfo(input: GetInfoRequest, options?: RpcOptions): UnaryCall { const method = this.methods[15], opt = this._transport.mergeOptions(options); @@ -1077,7 +1080,7 @@ export class LightningClient implements ILightningClient, ServiceInfo { * and its subsystems. This includes the full configuration and the latest log * entries from the log file. * - * @generated from protobuf rpc: GetDebugInfo(lnrpc.GetDebugInfoRequest) returns (lnrpc.GetDebugInfoResponse); + * @generated from protobuf rpc: GetDebugInfo */ getDebugInfo(input: GetDebugInfoRequest, options?: RpcOptions): UnaryCall { const method = this.methods[16], opt = this._transport.mergeOptions(options); @@ -1089,7 +1092,7 @@ export class LightningClient implements ILightningClient, ServiceInfo { * whether it's in a recovery mode, whether the recovery is finished, and the * progress made so far. * - * @generated from protobuf rpc: GetRecoveryInfo(lnrpc.GetRecoveryInfoRequest) returns (lnrpc.GetRecoveryInfoResponse); + * @generated from protobuf rpc: GetRecoveryInfo */ getRecoveryInfo(input: GetRecoveryInfoRequest, options?: RpcOptions): UnaryCall { const method = this.methods[17], opt = this._transport.mergeOptions(options); @@ -1104,7 +1107,7 @@ export class LightningClient implements ILightningClient, ServiceInfo { * workflow and is waiting for confirmations for the funding txn, or is in the * process of closure, either initiated cooperatively or non-cooperatively. * - * @generated from protobuf rpc: PendingChannels(lnrpc.PendingChannelsRequest) returns (lnrpc.PendingChannelsResponse); + * @generated from protobuf rpc: PendingChannels */ pendingChannels(input: PendingChannelsRequest, options?: RpcOptions): UnaryCall { const method = this.methods[18], opt = this._transport.mergeOptions(options); @@ -1115,7 +1118,7 @@ export class LightningClient implements ILightningClient, ServiceInfo { * ListChannels returns a description of all the open channels that this node * is a participant in. * - * @generated from protobuf rpc: ListChannels(lnrpc.ListChannelsRequest) returns (lnrpc.ListChannelsResponse); + * @generated from protobuf rpc: ListChannels */ listChannels(input: ListChannelsRequest, options?: RpcOptions): UnaryCall { const method = this.methods[19], opt = this._transport.mergeOptions(options); @@ -1128,7 +1131,7 @@ export class LightningClient implements ILightningClient, ServiceInfo { * sent over. Events include new active channels, inactive channels, and closed * channels. * - * @generated from protobuf rpc: SubscribeChannelEvents(lnrpc.ChannelEventSubscription) returns (stream lnrpc.ChannelEventUpdate); + * @generated from protobuf rpc: SubscribeChannelEvents */ subscribeChannelEvents(input: ChannelEventSubscription, options?: RpcOptions): ServerStreamingCall { const method = this.methods[20], opt = this._transport.mergeOptions(options); @@ -1139,7 +1142,7 @@ export class LightningClient implements ILightningClient, ServiceInfo { * ClosedChannels returns a description of all the closed channels that * this node was a participant in. * - * @generated from protobuf rpc: ClosedChannels(lnrpc.ClosedChannelsRequest) returns (lnrpc.ClosedChannelsResponse); + * @generated from protobuf rpc: ClosedChannels */ closedChannels(input: ClosedChannelsRequest, options?: RpcOptions): UnaryCall { const method = this.methods[21], opt = this._transport.mergeOptions(options); @@ -1152,7 +1155,7 @@ export class LightningClient implements ILightningClient, ServiceInfo { * other sync calls, all byte slices are intended to be populated as hex * encoded strings. * - * @generated from protobuf rpc: OpenChannelSync(lnrpc.OpenChannelRequest) returns (lnrpc.ChannelPoint); + * @generated from protobuf rpc: OpenChannelSync */ openChannelSync(input: OpenChannelRequest, options?: RpcOptions): UnaryCall { const method = this.methods[22], opt = this._transport.mergeOptions(options); @@ -1169,7 +1172,7 @@ export class LightningClient implements ILightningClient, ServiceInfo { * arguments specified in the OpenChannelRequest, this pending channel ID can * then be used to manually progress the channel funding flow. * - * @generated from protobuf rpc: OpenChannel(lnrpc.OpenChannelRequest) returns (stream lnrpc.OpenStatusUpdate); + * @generated from protobuf rpc: OpenChannel */ openChannel(input: OpenChannelRequest, options?: RpcOptions): ServerStreamingCall { const method = this.methods[23], opt = this._transport.mergeOptions(options); @@ -1183,7 +1186,7 @@ export class LightningClient implements ILightningClient, ServiceInfo { * This is the safer variant of using PSBTs to manually fund a batch of * channels through the OpenChannel RPC. * - * @generated from protobuf rpc: BatchOpenChannel(lnrpc.BatchOpenChannelRequest) returns (lnrpc.BatchOpenChannelResponse); + * @generated from protobuf rpc: BatchOpenChannel */ batchOpenChannel(input: BatchOpenChannelRequest, options?: RpcOptions): UnaryCall { const method = this.methods[24], opt = this._transport.mergeOptions(options); @@ -1200,7 +1203,7 @@ export class LightningClient implements ILightningClient, ServiceInfo { * Alternatively, this can be used to interactively drive PSBT signing for * funding for partially complete funding transactions. * - * @generated from protobuf rpc: FundingStateStep(lnrpc.FundingTransitionMsg) returns (lnrpc.FundingStateStepResp); + * @generated from protobuf rpc: FundingStateStep */ fundingStateStep(input: FundingTransitionMsg, options?: RpcOptions): UnaryCall { const method = this.methods[25], opt = this._transport.mergeOptions(options); @@ -1214,7 +1217,7 @@ export class LightningClient implements ILightningClient, ServiceInfo { * node operators to specify their own criteria for accepting inbound channels * through a single persistent connection. * - * @generated from protobuf rpc: ChannelAcceptor(stream lnrpc.ChannelAcceptResponse) returns (stream lnrpc.ChannelAcceptRequest); + * @generated from protobuf rpc: ChannelAcceptor */ channelAcceptor(options?: RpcOptions): DuplexStreamingCall { const method = this.methods[26], opt = this._transport.mergeOptions(options); @@ -1230,7 +1233,7 @@ export class LightningClient implements ILightningClient, ServiceInfo { * closure transaction is confirmed, or a manual fee rate. If neither are * specified, then a default lax, block confirmation target is used. * - * @generated from protobuf rpc: CloseChannel(lnrpc.CloseChannelRequest) returns (stream lnrpc.CloseStatusUpdate); + * @generated from protobuf rpc: CloseChannel */ closeChannel(input: CloseChannelRequest, options?: RpcOptions): ServerStreamingCall { const method = this.methods[27], opt = this._transport.mergeOptions(options); @@ -1245,7 +1248,7 @@ export class LightningClient implements ILightningClient, ServiceInfo { * never broadcast. Only available for non-externally funded channels in dev * build. * - * @generated from protobuf rpc: AbandonChannel(lnrpc.AbandonChannelRequest) returns (lnrpc.AbandonChannelResponse); + * @generated from protobuf rpc: AbandonChannel */ abandonChannel(input: AbandonChannelRequest, options?: RpcOptions): UnaryCall { const method = this.methods[28], opt = this._transport.mergeOptions(options); @@ -1260,7 +1263,7 @@ export class LightningClient implements ILightningClient, ServiceInfo { * Network with a single persistent connection. * * @deprecated - * @generated from protobuf rpc: SendPayment(stream lnrpc.SendRequest) returns (stream lnrpc.SendResponse); + * @generated from protobuf rpc: SendPayment */ sendPayment(options?: RpcOptions): DuplexStreamingCall { const method = this.methods[29], opt = this._transport.mergeOptions(options); @@ -1268,12 +1271,13 @@ export class LightningClient implements ILightningClient, ServiceInfo { } /** * - * SendPaymentSync is the synchronous non-streaming version of SendPayment. - * This RPC is intended to be consumed by clients of the REST proxy. - * Additionally, this RPC expects the destination's public key and the payment - * hash (if any) to be encoded as hex strings. + * Deprecated, use routerrpc.SendPaymentV2. SendPaymentSync is the synchronous + * non-streaming version of SendPayment. This RPC is intended to be consumed by + * clients of the REST proxy. Additionally, this RPC expects the destination's + * public key and the payment hash (if any) to be encoded as hex strings. * - * @generated from protobuf rpc: SendPaymentSync(lnrpc.SendRequest) returns (lnrpc.SendResponse); + * @deprecated + * @generated from protobuf rpc: SendPaymentSync */ sendPaymentSync(input: SendRequest, options?: RpcOptions): UnaryCall { const method = this.methods[30], opt = this._transport.mergeOptions(options); @@ -1288,7 +1292,7 @@ export class LightningClient implements ILightningClient, ServiceInfo { * swaps. * * @deprecated - * @generated from protobuf rpc: SendToRoute(stream lnrpc.SendToRouteRequest) returns (stream lnrpc.SendResponse); + * @generated from protobuf rpc: SendToRoute */ sendToRoute(options?: RpcOptions): DuplexStreamingCall { const method = this.methods[31], opt = this._transport.mergeOptions(options); @@ -1296,10 +1300,12 @@ export class LightningClient implements ILightningClient, ServiceInfo { } /** * - * SendToRouteSync is a synchronous version of SendToRoute. It Will block - * until the payment either fails or succeeds. + * Deprecated, use routerrpc.SendToRouteV2. SendToRouteSync is a synchronous + * version of SendToRoute. It Will block until the payment either fails or + * succeeds. * - * @generated from protobuf rpc: SendToRouteSync(lnrpc.SendToRouteRequest) returns (lnrpc.SendResponse); + * @deprecated + * @generated from protobuf rpc: SendToRouteSync */ sendToRouteSync(input: SendToRouteRequest, options?: RpcOptions): UnaryCall { const method = this.methods[32], opt = this._transport.mergeOptions(options); @@ -1311,7 +1317,7 @@ export class LightningClient implements ILightningClient, ServiceInfo { * duplicated invoices are rejected, therefore all invoices *must* have a * unique payment preimage. * - * @generated from protobuf rpc: AddInvoice(lnrpc.Invoice) returns (lnrpc.AddInvoiceResponse); + * @generated from protobuf rpc: AddInvoice */ addInvoice(input: Invoice, options?: RpcOptions): UnaryCall { const method = this.methods[33], opt = this._transport.mergeOptions(options); @@ -1327,7 +1333,7 @@ export class LightningClient implements ILightningClient, ServiceInfo { * next request. By default, the first 100 invoices created will be returned. * Backwards pagination is also supported through the Reversed flag. * - * @generated from protobuf rpc: ListInvoices(lnrpc.ListInvoiceRequest) returns (lnrpc.ListInvoiceResponse); + * @generated from protobuf rpc: ListInvoices */ listInvoices(input: ListInvoiceRequest, options?: RpcOptions): UnaryCall { const method = this.methods[34], opt = this._transport.mergeOptions(options); @@ -1339,7 +1345,7 @@ export class LightningClient implements ILightningClient, ServiceInfo { * The passed payment hash *must* be exactly 32 bytes, if not, an error is * returned. * - * @generated from protobuf rpc: LookupInvoice(lnrpc.PaymentHash) returns (lnrpc.Invoice); + * @generated from protobuf rpc: LookupInvoice */ lookupInvoice(input: PaymentHash, options?: RpcOptions): UnaryCall { const method = this.methods[35], opt = this._transport.mergeOptions(options); @@ -1357,7 +1363,7 @@ export class LightningClient implements ILightningClient, ServiceInfo { * of these fields can be set. If no fields are set, then we'll only send out * the latest add/settle events. * - * @generated from protobuf rpc: SubscribeInvoices(lnrpc.InvoiceSubscription) returns (stream lnrpc.Invoice); + * @generated from protobuf rpc: SubscribeInvoices */ subscribeInvoices(input: InvoiceSubscription, options?: RpcOptions): ServerStreamingCall { const method = this.methods[36], opt = this._transport.mergeOptions(options); @@ -1369,7 +1375,7 @@ export class LightningClient implements ILightningClient, ServiceInfo { * it, returning a full description of the conditions encoded within the * payment request. * - * @generated from protobuf rpc: DecodePayReq(lnrpc.PayReqString) returns (lnrpc.PayReq); + * @generated from protobuf rpc: DecodePayReq */ decodePayReq(input: PayReqString, options?: RpcOptions): UnaryCall { const method = this.methods[37], opt = this._transport.mergeOptions(options); @@ -1379,7 +1385,7 @@ export class LightningClient implements ILightningClient, ServiceInfo { * lncli: `listpayments` * ListPayments returns a list of all outgoing payments. * - * @generated from protobuf rpc: ListPayments(lnrpc.ListPaymentsRequest) returns (lnrpc.ListPaymentsResponse); + * @generated from protobuf rpc: ListPayments */ listPayments(input: ListPaymentsRequest, options?: RpcOptions): UnaryCall { const method = this.methods[38], opt = this._transport.mergeOptions(options); @@ -1390,7 +1396,7 @@ export class LightningClient implements ILightningClient, ServiceInfo { * DeletePayment deletes an outgoing payment from DB. Note that it will not * attempt to delete an In-Flight payment, since that would be unsafe. * - * @generated from protobuf rpc: DeletePayment(lnrpc.DeletePaymentRequest) returns (lnrpc.DeletePaymentResponse); + * @generated from protobuf rpc: DeletePayment */ deletePayment(input: DeletePaymentRequest, options?: RpcOptions): UnaryCall { const method = this.methods[39], opt = this._transport.mergeOptions(options); @@ -1401,7 +1407,7 @@ export class LightningClient implements ILightningClient, ServiceInfo { * DeleteAllPayments deletes all outgoing payments from DB. Note that it will * not attempt to delete In-Flight payments, since that would be unsafe. * - * @generated from protobuf rpc: DeleteAllPayments(lnrpc.DeleteAllPaymentsRequest) returns (lnrpc.DeleteAllPaymentsResponse); + * @generated from protobuf rpc: DeleteAllPayments */ deleteAllPayments(input: DeleteAllPaymentsRequest, options?: RpcOptions): UnaryCall { const method = this.methods[40], opt = this._transport.mergeOptions(options); @@ -1416,7 +1422,7 @@ export class LightningClient implements ILightningClient, ServiceInfo { * the node directional specific routing policy which includes: the time lock * delta, fee information, etc. * - * @generated from protobuf rpc: DescribeGraph(lnrpc.ChannelGraphRequest) returns (lnrpc.ChannelGraph); + * @generated from protobuf rpc: DescribeGraph */ describeGraph(input: ChannelGraphRequest, options?: RpcOptions): UnaryCall { const method = this.methods[41], opt = this._transport.mergeOptions(options); @@ -1427,7 +1433,7 @@ export class LightningClient implements ILightningClient, ServiceInfo { * GetNodeMetrics returns node metrics calculated from the graph. Currently * the only supported metric is betweenness centrality of individual nodes. * - * @generated from protobuf rpc: GetNodeMetrics(lnrpc.NodeMetricsRequest) returns (lnrpc.NodeMetricsResponse); + * @generated from protobuf rpc: GetNodeMetrics */ getNodeMetrics(input: NodeMetricsRequest, options?: RpcOptions): UnaryCall { const method = this.methods[42], opt = this._transport.mergeOptions(options); @@ -1440,7 +1446,7 @@ export class LightningClient implements ILightningClient, ServiceInfo { * uniquely identifies the location of transaction's funding output within the * blockchain. * - * @generated from protobuf rpc: GetChanInfo(lnrpc.ChanInfoRequest) returns (lnrpc.ChannelEdge); + * @generated from protobuf rpc: GetChanInfo */ getChanInfo(input: ChanInfoRequest, options?: RpcOptions): UnaryCall { const method = this.methods[43], opt = this._transport.mergeOptions(options); @@ -1451,7 +1457,7 @@ export class LightningClient implements ILightningClient, ServiceInfo { * GetNodeInfo returns the latest advertised, aggregated, and authenticated * channel information for the specified node identified by its public key. * - * @generated from protobuf rpc: GetNodeInfo(lnrpc.NodeInfoRequest) returns (lnrpc.NodeInfo); + * @generated from protobuf rpc: GetNodeInfo */ getNodeInfo(input: NodeInfoRequest, options?: RpcOptions): UnaryCall { const method = this.methods[44], opt = this._transport.mergeOptions(options); @@ -1470,7 +1476,7 @@ export class LightningClient implements ILightningClient, ServiceInfo { * to the URL. Unfortunately this map type doesn't appear in the REST API * documentation because of a bug in the grpc-gateway library. * - * @generated from protobuf rpc: QueryRoutes(lnrpc.QueryRoutesRequest) returns (lnrpc.QueryRoutesResponse); + * @generated from protobuf rpc: QueryRoutes */ queryRoutes(input: QueryRoutesRequest, options?: RpcOptions): UnaryCall { const method = this.methods[45], opt = this._transport.mergeOptions(options); @@ -1481,7 +1487,7 @@ export class LightningClient implements ILightningClient, ServiceInfo { * GetNetworkInfo returns some basic stats about the known channel graph from * the point of view of the node. * - * @generated from protobuf rpc: GetNetworkInfo(lnrpc.NetworkInfoRequest) returns (lnrpc.NetworkInfo); + * @generated from protobuf rpc: GetNetworkInfo */ getNetworkInfo(input: NetworkInfoRequest, options?: RpcOptions): UnaryCall { const method = this.methods[46], opt = this._transport.mergeOptions(options); @@ -1492,7 +1498,7 @@ export class LightningClient implements ILightningClient, ServiceInfo { * StopDaemon will send a shutdown request to the interrupt handler, triggering * a graceful shutdown of the daemon. * - * @generated from protobuf rpc: StopDaemon(lnrpc.StopRequest) returns (lnrpc.StopResponse); + * @generated from protobuf rpc: StopDaemon */ stopDaemon(input: StopRequest, options?: RpcOptions): UnaryCall { const method = this.methods[47], opt = this._transport.mergeOptions(options); @@ -1507,7 +1513,7 @@ export class LightningClient implements ILightningClient, ServiceInfo { * channels being advertised, updates in the routing policy for a directional * channel edge, and when channels are closed on-chain. * - * @generated from protobuf rpc: SubscribeChannelGraph(lnrpc.GraphTopologySubscription) returns (stream lnrpc.GraphTopologyUpdate); + * @generated from protobuf rpc: SubscribeChannelGraph */ subscribeChannelGraph(input: GraphTopologySubscription, options?: RpcOptions): ServerStreamingCall { const method = this.methods[48], opt = this._transport.mergeOptions(options); @@ -1520,7 +1526,7 @@ export class LightningClient implements ILightningClient, ServiceInfo { * level, or in a granular fashion to specify the logging for a target * sub-system. * - * @generated from protobuf rpc: DebugLevel(lnrpc.DebugLevelRequest) returns (lnrpc.DebugLevelResponse); + * @generated from protobuf rpc: DebugLevel */ debugLevel(input: DebugLevelRequest, options?: RpcOptions): UnaryCall { const method = this.methods[49], opt = this._transport.mergeOptions(options); @@ -1531,7 +1537,7 @@ export class LightningClient implements ILightningClient, ServiceInfo { * FeeReport allows the caller to obtain a report detailing the current fee * schedule enforced by the node globally for each channel. * - * @generated from protobuf rpc: FeeReport(lnrpc.FeeReportRequest) returns (lnrpc.FeeReportResponse); + * @generated from protobuf rpc: FeeReport */ feeReport(input: FeeReportRequest, options?: RpcOptions): UnaryCall { const method = this.methods[50], opt = this._transport.mergeOptions(options); @@ -1542,7 +1548,7 @@ export class LightningClient implements ILightningClient, ServiceInfo { * UpdateChannelPolicy allows the caller to update the fee schedule and * channel policies for all channels globally, or a particular channel. * - * @generated from protobuf rpc: UpdateChannelPolicy(lnrpc.PolicyUpdateRequest) returns (lnrpc.PolicyUpdateResponse); + * @generated from protobuf rpc: UpdateChannelPolicy */ updateChannelPolicy(input: PolicyUpdateRequest, options?: RpcOptions): UnaryCall { const method = this.methods[51], opt = this._transport.mergeOptions(options); @@ -1562,7 +1568,7 @@ export class LightningClient implements ILightningClient, ServiceInfo { * the index offset of the last entry. The index offset can be provided to the * request to allow the caller to skip a series of records. * - * @generated from protobuf rpc: ForwardingHistory(lnrpc.ForwardingHistoryRequest) returns (lnrpc.ForwardingHistoryResponse); + * @generated from protobuf rpc: ForwardingHistory */ forwardingHistory(input: ForwardingHistoryRequest, options?: RpcOptions): UnaryCall { const method = this.methods[52], opt = this._transport.mergeOptions(options); @@ -1577,7 +1583,7 @@ export class LightningClient implements ILightningClient, ServiceInfo { * method once lnd is running, or via the InitWallet and UnlockWallet methods * from the WalletUnlocker service. * - * @generated from protobuf rpc: ExportChannelBackup(lnrpc.ExportChannelBackupRequest) returns (lnrpc.ChannelBackup); + * @generated from protobuf rpc: ExportChannelBackup */ exportChannelBackup(input: ExportChannelBackupRequest, options?: RpcOptions): UnaryCall { const method = this.methods[53], opt = this._transport.mergeOptions(options); @@ -1591,7 +1597,7 @@ export class LightningClient implements ILightningClient, ServiceInfo { * as well, which contains a single encrypted blob containing the backups of * each channel. * - * @generated from protobuf rpc: ExportAllChannelBackups(lnrpc.ChanBackupExportRequest) returns (lnrpc.ChanBackupSnapshot); + * @generated from protobuf rpc: ExportAllChannelBackups */ exportAllChannelBackups(input: ChanBackupExportRequest, options?: RpcOptions): UnaryCall { const method = this.methods[54], opt = this._transport.mergeOptions(options); @@ -1603,7 +1609,7 @@ export class LightningClient implements ILightningClient, ServiceInfo { * snapshot. This method will accept either a packed Single or a packed Multi. * Specifying both will result in an error. * - * @generated from protobuf rpc: VerifyChanBackup(lnrpc.ChanBackupSnapshot) returns (lnrpc.VerifyChanBackupResponse); + * @generated from protobuf rpc: VerifyChanBackup */ verifyChanBackup(input: ChanBackupSnapshot, options?: RpcOptions): UnaryCall { const method = this.methods[55], opt = this._transport.mergeOptions(options); @@ -1616,7 +1622,7 @@ export class LightningClient implements ILightningClient, ServiceInfo { * remaining within the channel. If we are able to unpack the backup, then the * new channel will be shown under listchannels, as well as pending channels. * - * @generated from protobuf rpc: RestoreChannelBackups(lnrpc.RestoreChanBackupRequest) returns (lnrpc.RestoreBackupResponse); + * @generated from protobuf rpc: RestoreChannelBackups */ restoreChannelBackups(input: RestoreChanBackupRequest, options?: RpcOptions): UnaryCall { const method = this.methods[56], opt = this._transport.mergeOptions(options); @@ -1632,7 +1638,7 @@ export class LightningClient implements ILightningClient, ServiceInfo { * ups, but the updated set of encrypted multi-chan backups with the closed * channel(s) removed. * - * @generated from protobuf rpc: SubscribeChannelBackups(lnrpc.ChannelBackupSubscription) returns (stream lnrpc.ChanBackupSnapshot); + * @generated from protobuf rpc: SubscribeChannelBackups */ subscribeChannelBackups(input: ChannelBackupSubscription, options?: RpcOptions): ServerStreamingCall { const method = this.methods[57], opt = this._transport.mergeOptions(options); @@ -1644,7 +1650,7 @@ export class LightningClient implements ILightningClient, ServiceInfo { * write permissions. No first-party caveats are added since this can be done * offline. * - * @generated from protobuf rpc: BakeMacaroon(lnrpc.BakeMacaroonRequest) returns (lnrpc.BakeMacaroonResponse); + * @generated from protobuf rpc: BakeMacaroon */ bakeMacaroon(input: BakeMacaroonRequest, options?: RpcOptions): UnaryCall { const method = this.methods[58], opt = this._transport.mergeOptions(options); @@ -1654,7 +1660,7 @@ export class LightningClient implements ILightningClient, ServiceInfo { * lncli: `listmacaroonids` * ListMacaroonIDs returns all root key IDs that are in use. * - * @generated from protobuf rpc: ListMacaroonIDs(lnrpc.ListMacaroonIDsRequest) returns (lnrpc.ListMacaroonIDsResponse); + * @generated from protobuf rpc: ListMacaroonIDs */ listMacaroonIDs(input: ListMacaroonIDsRequest, options?: RpcOptions): UnaryCall { const method = this.methods[59], opt = this._transport.mergeOptions(options); @@ -1665,7 +1671,7 @@ export class LightningClient implements ILightningClient, ServiceInfo { * DeleteMacaroonID deletes the specified macaroon ID and invalidates all * macaroons derived from that ID. * - * @generated from protobuf rpc: DeleteMacaroonID(lnrpc.DeleteMacaroonIDRequest) returns (lnrpc.DeleteMacaroonIDResponse); + * @generated from protobuf rpc: DeleteMacaroonID */ deleteMacaroonID(input: DeleteMacaroonIDRequest, options?: RpcOptions): UnaryCall { const method = this.methods[60], opt = this._transport.mergeOptions(options); @@ -1676,7 +1682,7 @@ export class LightningClient implements ILightningClient, ServiceInfo { * ListPermissions lists all RPC method URIs and their required macaroon * permissions to access them. * - * @generated from protobuf rpc: ListPermissions(lnrpc.ListPermissionsRequest) returns (lnrpc.ListPermissionsResponse); + * @generated from protobuf rpc: ListPermissions */ listPermissions(input: ListPermissionsRequest, options?: RpcOptions): UnaryCall { const method = this.methods[61], opt = this._transport.mergeOptions(options); @@ -1688,7 +1694,7 @@ export class LightningClient implements ILightningClient, ServiceInfo { * imposed on the macaroon and that the macaroon is authorized to follow the * provided permissions. * - * @generated from protobuf rpc: CheckMacaroonPermissions(lnrpc.CheckMacPermRequest) returns (lnrpc.CheckMacPermResponse); + * @generated from protobuf rpc: CheckMacaroonPermissions */ checkMacaroonPermissions(input: CheckMacPermRequest, options?: RpcOptions): UnaryCall { const method = this.methods[62], opt = this._transport.mergeOptions(options); @@ -1709,7 +1715,7 @@ export class LightningClient implements ILightningClient, ServiceInfo { * allowed to modify any responses. As a security measure, _no_ middleware can * modify responses for requests made with _unencumbered_ macaroons! * - * @generated from protobuf rpc: RegisterRPCMiddleware(stream lnrpc.RPCMiddlewareResponse) returns (stream lnrpc.RPCMiddlewareRequest); + * @generated from protobuf rpc: RegisterRPCMiddleware */ registerRPCMiddleware(options?: RpcOptions): DuplexStreamingCall { const method = this.methods[63], opt = this._transport.mergeOptions(options); @@ -1719,7 +1725,7 @@ export class LightningClient implements ILightningClient, ServiceInfo { * lncli: `sendcustom` * SendCustomMessage sends a custom peer message. * - * @generated from protobuf rpc: SendCustomMessage(lnrpc.SendCustomMessageRequest) returns (lnrpc.SendCustomMessageResponse); + * @generated from protobuf rpc: SendCustomMessage */ sendCustomMessage(input: SendCustomMessageRequest, options?: RpcOptions): UnaryCall { const method = this.methods[64], opt = this._transport.mergeOptions(options); @@ -1734,7 +1740,7 @@ export class LightningClient implements ILightningClient, ServiceInfo { * needs to be compiled with the `dev` build tag, and the message type to * override should be specified in lnd's experimental protocol configuration. * - * @generated from protobuf rpc: SubscribeCustomMessages(lnrpc.SubscribeCustomMessagesRequest) returns (stream lnrpc.CustomMessage); + * @generated from protobuf rpc: SubscribeCustomMessages */ subscribeCustomMessages(input: SubscribeCustomMessagesRequest, options?: RpcOptions): ServerStreamingCall { const method = this.methods[65], opt = this._transport.mergeOptions(options); @@ -1746,7 +1752,7 @@ export class LightningClient implements ILightningClient, ServiceInfo { * their confirmed SCID (if it exists) and/or the base SCID (in the case of * zero conf). * - * @generated from protobuf rpc: ListAliases(lnrpc.ListAliasesRequest) returns (lnrpc.ListAliasesResponse); + * @generated from protobuf rpc: ListAliases */ listAliases(input: ListAliasesRequest, options?: RpcOptions): UnaryCall { const method = this.methods[66], opt = this._transport.mergeOptions(options); @@ -1758,7 +1764,7 @@ export class LightningClient implements ILightningClient, ServiceInfo { * If the htlc has no final resolution yet, a NotFound grpc status code is * returned. * - * @generated from protobuf rpc: LookupHtlcResolution(lnrpc.LookupHtlcResolutionRequest) returns (lnrpc.LookupHtlcResolutionResponse); + * @generated from protobuf rpc: LookupHtlcResolution */ lookupHtlcResolution(input: LookupHtlcResolutionRequest, options?: RpcOptions): UnaryCall { const method = this.methods[67], opt = this._transport.mergeOptions(options); diff --git a/proto/lnd/lightning.ts b/proto/lnd/lightning.ts index 3b6d4149..07341608 100644 --- a/proto/lnd/lightning.ts +++ b/proto/lnd/lightning.ts @@ -1,4 +1,4 @@ -// @generated by protobuf-ts 2.8.1 +// @generated by protobuf-ts 2.11.1 // @generated from protobuf file "lightning.proto" (package "lnrpc", syntax proto3) // tslint:disable import { ServiceType } from "@protobuf-ts/runtime-rpc"; @@ -10,18 +10,17 @@ import type { IBinaryReader } from "@protobuf-ts/runtime"; import { UnknownFieldHandler } from "@protobuf-ts/runtime"; import type { PartialMessage } from "@protobuf-ts/runtime"; import { reflectionMergePartial } from "@protobuf-ts/runtime"; -import { MESSAGE_TYPE } from "@protobuf-ts/runtime"; import { MessageType } from "@protobuf-ts/runtime"; /** * @generated from protobuf message lnrpc.LookupHtlcResolutionRequest */ export interface LookupHtlcResolutionRequest { /** - * @generated from protobuf field: uint64 chan_id = 1; + * @generated from protobuf field: uint64 chan_id = 1 */ chanId: bigint; /** - * @generated from protobuf field: uint64 htlc_index = 2; + * @generated from protobuf field: uint64 htlc_index = 2 */ htlcIndex: bigint; } @@ -32,13 +31,13 @@ export interface LookupHtlcResolutionResponse { /** * Settled is true is the htlc was settled. If false, the htlc was failed. * - * @generated from protobuf field: bool settled = 1; + * @generated from protobuf field: bool settled = 1 */ settled: boolean; /** * Offchain indicates whether the htlc was resolved off-chain or on-chain. * - * @generated from protobuf field: bool offchain = 2; + * @generated from protobuf field: bool offchain = 2 */ offchain: boolean; } @@ -54,19 +53,19 @@ export interface CustomMessage { /** * Peer from which the message originates * - * @generated from protobuf field: bytes peer = 1; + * @generated from protobuf field: bytes peer = 1 */ peer: Uint8Array; /** * Message type. This value will be in the custom range (>= 32768). * - * @generated from protobuf field: uint32 type = 2; + * @generated from protobuf field: uint32 type = 2 */ type: number; /** * Raw message data * - * @generated from protobuf field: bytes data = 3; + * @generated from protobuf field: bytes data = 3 */ data: Uint8Array; } @@ -77,7 +76,7 @@ export interface SendCustomMessageRequest { /** * Peer to send the message to * - * @generated from protobuf field: bytes peer = 1; + * @generated from protobuf field: bytes peer = 1 */ peer: Uint8Array; /** @@ -86,13 +85,13 @@ export interface SendCustomMessageRequest { * build tag, and the message type to override should be specified in lnd's * experimental protocol configuration. * - * @generated from protobuf field: uint32 type = 2; + * @generated from protobuf field: uint32 type = 2 */ type: number; /** * Raw message data. * - * @generated from protobuf field: bytes data = 3; + * @generated from protobuf field: bytes data = 3 */ data: Uint8Array; } @@ -100,6 +99,12 @@ export interface SendCustomMessageRequest { * @generated from protobuf message lnrpc.SendCustomMessageResponse */ export interface SendCustomMessageResponse { + /** + * The status of the send operation. + * + * @generated from protobuf field: string status = 1 + */ + status: string; } /** * @generated from protobuf message lnrpc.Utxo @@ -108,37 +113,37 @@ export interface Utxo { /** * The type of address * - * @generated from protobuf field: lnrpc.AddressType address_type = 1; + * @generated from protobuf field: lnrpc.AddressType address_type = 1 */ addressType: AddressType; /** * The address * - * @generated from protobuf field: string address = 2; + * @generated from protobuf field: string address = 2 */ address: string; /** * The value of the unspent coin in satoshis * - * @generated from protobuf field: int64 amount_sat = 3; + * @generated from protobuf field: int64 amount_sat = 3 */ amountSat: bigint; /** * The pkscript in hex * - * @generated from protobuf field: string pk_script = 4; + * @generated from protobuf field: string pk_script = 4 */ pkScript: string; /** * The outpoint in format txid:n * - * @generated from protobuf field: lnrpc.OutPoint outpoint = 5; + * @generated from protobuf field: lnrpc.OutPoint outpoint = 5 */ outpoint?: OutPoint; /** * The number of confirmations for the Utxo * - * @generated from protobuf field: int64 confirmations = 6; + * @generated from protobuf field: int64 confirmations = 6 */ confirmations: bigint; } @@ -149,37 +154,37 @@ export interface OutputDetail { /** * The type of the output * - * @generated from protobuf field: lnrpc.OutputScriptType output_type = 1; + * @generated from protobuf field: lnrpc.OutputScriptType output_type = 1 */ outputType: OutputScriptType; /** * The address * - * @generated from protobuf field: string address = 2; + * @generated from protobuf field: string address = 2 */ address: string; /** * The pkscript in hex * - * @generated from protobuf field: string pk_script = 3; + * @generated from protobuf field: string pk_script = 3 */ pkScript: string; /** * The output index used in the raw transaction * - * @generated from protobuf field: int64 output_index = 4; + * @generated from protobuf field: int64 output_index = 4 */ outputIndex: bigint; /** * The value of the output coin in satoshis * - * @generated from protobuf field: int64 amount = 5; + * @generated from protobuf field: int64 amount = 5 */ amount: bigint; /** * Denotes if the output is controlled by the internal wallet * - * @generated from protobuf field: bool is_our_address = 6; + * @generated from protobuf field: bool is_our_address = 6 */ isOurAddress: boolean; } @@ -190,43 +195,43 @@ export interface Transaction { /** * The transaction hash * - * @generated from protobuf field: string tx_hash = 1; + * @generated from protobuf field: string tx_hash = 1 */ txHash: string; /** * The transaction amount, denominated in satoshis * - * @generated from protobuf field: int64 amount = 2; + * @generated from protobuf field: int64 amount = 2 */ amount: bigint; /** * The number of confirmations * - * @generated from protobuf field: int32 num_confirmations = 3; + * @generated from protobuf field: int32 num_confirmations = 3 */ numConfirmations: number; /** * The hash of the block this transaction was included in * - * @generated from protobuf field: string block_hash = 4; + * @generated from protobuf field: string block_hash = 4 */ blockHash: string; /** * The height of the block this transaction was included in * - * @generated from protobuf field: int32 block_height = 5; + * @generated from protobuf field: int32 block_height = 5 */ blockHeight: number; /** * Timestamp of this transaction * - * @generated from protobuf field: int64 time_stamp = 6; + * @generated from protobuf field: int64 time_stamp = 6 */ timeStamp: bigint; /** * Fees paid for this transaction * - * @generated from protobuf field: int64 total_fees = 7; + * @generated from protobuf field: int64 total_fees = 7 */ totalFees: bigint; /** @@ -234,31 +239,31 @@ export interface Transaction { * now incorporated in the output_details field. * * @deprecated - * @generated from protobuf field: repeated string dest_addresses = 8 [deprecated = true]; + * @generated from protobuf field: repeated string dest_addresses = 8 [deprecated = true] */ destAddresses: string[]; /** * Outputs that received funds for this transaction * - * @generated from protobuf field: repeated lnrpc.OutputDetail output_details = 11; + * @generated from protobuf field: repeated lnrpc.OutputDetail output_details = 11 */ outputDetails: OutputDetail[]; /** * The raw transaction hex. * - * @generated from protobuf field: string raw_tx_hex = 9; + * @generated from protobuf field: string raw_tx_hex = 9 */ rawTxHex: string; /** * A label that was optionally set on transaction broadcast. * - * @generated from protobuf field: string label = 10; + * @generated from protobuf field: string label = 10 */ label: string; /** * PreviousOutpoints/Inputs of this transaction. * - * @generated from protobuf field: repeated lnrpc.PreviousOutPoint previous_outpoints = 12; + * @generated from protobuf field: repeated lnrpc.PreviousOutPoint previous_outpoints = 12 */ previousOutpoints: PreviousOutPoint[]; } @@ -271,7 +276,7 @@ export interface GetTransactionsRequest { * The height from which to list transactions, inclusive. If this value is * greater than end_height, transactions will be read in reverse. * - * @generated from protobuf field: int32 start_height = 1; + * @generated from protobuf field: int32 start_height = 1 */ startHeight: number; /** @@ -282,15 +287,31 @@ export interface GetTransactionsRequest { * unconfirmed transactions. If no end_height is provided, the call will * default to this option. * - * @generated from protobuf field: int32 end_height = 2; + * @generated from protobuf field: int32 end_height = 2 */ endHeight: number; /** * An optional filter to only include transactions relevant to an account. * - * @generated from protobuf field: string account = 3; + * @generated from protobuf field: string account = 3 */ account: string; + /** + * + * The index of a transaction that will be used in a query to determine which + * transaction should be returned in the response. + * + * @generated from protobuf field: uint32 index_offset = 4 + */ + indexOffset: number; + /** + * + * The maximal number of transactions returned in the response to this query. + * This value should be set to 0 to return all transactions. + * + * @generated from protobuf field: uint32 max_transactions = 5 + */ + maxTransactions: number; } /** * @generated from protobuf message lnrpc.TransactionDetails @@ -299,9 +320,25 @@ export interface TransactionDetails { /** * The list of transactions relevant to the wallet. * - * @generated from protobuf field: repeated lnrpc.Transaction transactions = 1; + * @generated from protobuf field: repeated lnrpc.Transaction transactions = 1 */ transactions: Transaction[]; + /** + * + * The index of the last item in the set of returned transactions. This can be + * used to seek further, pagination style. + * + * @generated from protobuf field: uint64 last_index = 2 + */ + lastIndex: bigint; + /** + * + * The index of the last item in the set of returned transactions. This can be + * used to seek backwards, pagination style. + * + * @generated from protobuf field: uint64 first_index = 3 + */ + firstIndex: bigint; } /** * @generated from protobuf message lnrpc.FeeLimit @@ -318,7 +355,7 @@ export interface FeeLimit { * * The fields fixed and fixed_msat are mutually exclusive. * - * @generated from protobuf field: int64 fixed = 1; + * @generated from protobuf field: int64 fixed = 1 */ fixed: bigint; } | { @@ -329,7 +366,7 @@ export interface FeeLimit { * * The fields fixed and fixed_msat are mutually exclusive. * - * @generated from protobuf field: int64 fixed_msat = 3; + * @generated from protobuf field: int64 fixed_msat = 3 */ fixedMsat: bigint; } | { @@ -337,7 +374,7 @@ export interface FeeLimit { /** * The fee limit expressed as a percentage of the payment amount. * - * @generated from protobuf field: int64 percent = 2; + * @generated from protobuf field: int64 percent = 2 */ percent: bigint; } | { @@ -353,7 +390,7 @@ export interface SendRequest { * The identity pubkey of the payment recipient. When using REST, this field * must be encoded as base64. * - * @generated from protobuf field: bytes dest = 1; + * @generated from protobuf field: bytes dest = 1 */ dest: Uint8Array; /** @@ -362,7 +399,7 @@ export interface SendRequest { * that the REST gateway supports base64 encoding of bytes fields. * * @deprecated - * @generated from protobuf field: string dest_string = 2 [deprecated = true]; + * @generated from protobuf field: string dest_string = 2 [deprecated = true] */ destString: string; /** @@ -371,7 +408,7 @@ export interface SendRequest { * * The fields amt and amt_msat are mutually exclusive. * - * @generated from protobuf field: int64 amt = 3; + * @generated from protobuf field: int64 amt = 3 */ amt: bigint; /** @@ -380,7 +417,7 @@ export interface SendRequest { * * The fields amt and amt_msat are mutually exclusive. * - * @generated from protobuf field: int64 amt_msat = 12; + * @generated from protobuf field: int64 amt_msat = 12 */ amtMsat: bigint; /** @@ -388,7 +425,7 @@ export interface SendRequest { * The hash to use within the payment's HTLC. When using REST, this field * must be encoded as base64. * - * @generated from protobuf field: bytes payment_hash = 4; + * @generated from protobuf field: bytes payment_hash = 4 */ paymentHash: Uint8Array; /** @@ -397,7 +434,7 @@ export interface SendRequest { * that the REST gateway supports base64 encoding of bytes fields. * * @deprecated - * @generated from protobuf field: string payment_hash_string = 5 [deprecated = true]; + * @generated from protobuf field: string payment_hash_string = 5 [deprecated = true] */ paymentHashString: string; /** @@ -406,7 +443,7 @@ export interface SendRequest { * details of the invoice, the sender has all the data necessary to send a * payment to the recipient. * - * @generated from protobuf field: string payment_request = 6; + * @generated from protobuf field: string payment_request = 6 */ paymentRequest: string; /** @@ -414,7 +451,7 @@ export interface SendRequest { * The CLTV delta from the current height that should be used to set the * timelock for the final hop. * - * @generated from protobuf field: int32 final_cltv_delta = 7; + * @generated from protobuf field: int32 final_cltv_delta = 7 */ finalCltvDelta: number; /** @@ -425,7 +462,7 @@ export interface SendRequest { * send the payment. If not specified, lnd will use a default value of 100% * fees for small amounts (<=1k sat) or 5% fees for larger amounts. * - * @generated from protobuf field: lnrpc.FeeLimit fee_limit = 8; + * @generated from protobuf field: lnrpc.FeeLimit fee_limit = 8 */ feeLimit?: FeeLimit; /** @@ -433,14 +470,14 @@ export interface SendRequest { * The channel id of the channel that must be taken to the first hop. If zero, * any channel may be used. * - * @generated from protobuf field: uint64 outgoing_chan_id = 9 [jstype = JS_STRING]; + * @generated from protobuf field: uint64 outgoing_chan_id = 9 [jstype = JS_STRING] */ outgoingChanId: string; /** * * The pubkey of the last hop of the route. If empty, any hop may be used. * - * @generated from protobuf field: bytes last_hop_pubkey = 13; + * @generated from protobuf field: bytes last_hop_pubkey = 13 */ lastHopPubkey: Uint8Array; /** @@ -449,7 +486,7 @@ export interface SendRequest { * lnd's `--max-cltv-expiry` setting. If zero, then the value of * `--max-cltv-expiry` is enforced. * - * @generated from protobuf field: uint32 cltv_limit = 10; + * @generated from protobuf field: uint32 cltv_limit = 10 */ cltvLimit: number; /** @@ -460,7 +497,7 @@ export interface SendRequest { * required to be in the custom range >= 65536. When using REST, the values * must be encoded as base64. * - * @generated from protobuf field: map dest_custom_records = 11; + * @generated from protobuf field: map dest_custom_records = 11 */ destCustomRecords: { [key: string]: Uint8Array; @@ -468,7 +505,7 @@ export interface SendRequest { /** * If set, circular payments to self are permitted. * - * @generated from protobuf field: bool allow_self_payment = 14; + * @generated from protobuf field: bool allow_self_payment = 14 */ allowSelfPayment: boolean; /** @@ -479,7 +516,7 @@ export interface SendRequest { * the router will try to load destination features from the graph as a * fallback. * - * @generated from protobuf field: repeated lnrpc.FeatureBit dest_features = 15; + * @generated from protobuf field: repeated lnrpc.FeatureBit dest_features = 15 */ destFeatures: FeatureBit[]; /** @@ -487,7 +524,7 @@ export interface SendRequest { * The payment address of the generated invoice. This is also called * payment secret in specifications (e.g. BOLT 11). * - * @generated from protobuf field: bytes payment_addr = 16; + * @generated from protobuf field: bytes payment_addr = 16 */ paymentAddr: Uint8Array; } @@ -496,19 +533,19 @@ export interface SendRequest { */ export interface SendResponse { /** - * @generated from protobuf field: string payment_error = 1; + * @generated from protobuf field: string payment_error = 1 */ paymentError: string; /** - * @generated from protobuf field: bytes payment_preimage = 2; + * @generated from protobuf field: bytes payment_preimage = 2 */ paymentPreimage: Uint8Array; /** - * @generated from protobuf field: lnrpc.Route payment_route = 3; + * @generated from protobuf field: lnrpc.Route payment_route = 3 */ paymentRoute?: Route; /** - * @generated from protobuf field: bytes payment_hash = 4; + * @generated from protobuf field: bytes payment_hash = 4 */ paymentHash: Uint8Array; } @@ -521,7 +558,7 @@ export interface SendToRouteRequest { * The payment hash to use for the HTLC. When using REST, this field must be * encoded as base64. * - * @generated from protobuf field: bytes payment_hash = 1; + * @generated from protobuf field: bytes payment_hash = 1 */ paymentHash: Uint8Array; /** @@ -530,13 +567,13 @@ export interface SendToRouteRequest { * that the REST gateway supports base64 encoding of bytes fields. * * @deprecated - * @generated from protobuf field: string payment_hash_string = 2 [deprecated = true]; + * @generated from protobuf field: string payment_hash_string = 2 [deprecated = true] */ paymentHashString: string; /** * Route that should be used to attempt to complete the payment. * - * @generated from protobuf field: lnrpc.Route route = 4; + * @generated from protobuf field: lnrpc.Route route = 4 */ route?: Route; } @@ -547,65 +584,65 @@ export interface ChannelAcceptRequest { /** * The pubkey of the node that wishes to open an inbound channel. * - * @generated from protobuf field: bytes node_pubkey = 1; + * @generated from protobuf field: bytes node_pubkey = 1 */ nodePubkey: Uint8Array; /** * The hash of the genesis block that the proposed channel resides in. * - * @generated from protobuf field: bytes chain_hash = 2; + * @generated from protobuf field: bytes chain_hash = 2 */ chainHash: Uint8Array; /** * The pending channel id. * - * @generated from protobuf field: bytes pending_chan_id = 3; + * @generated from protobuf field: bytes pending_chan_id = 3 */ pendingChanId: Uint8Array; /** * The funding amount in satoshis that initiator wishes to use in the * channel. * - * @generated from protobuf field: uint64 funding_amt = 4; + * @generated from protobuf field: uint64 funding_amt = 4 */ fundingAmt: bigint; /** * The push amount of the proposed channel in millisatoshis. * - * @generated from protobuf field: uint64 push_amt = 5; + * @generated from protobuf field: uint64 push_amt = 5 */ pushAmt: bigint; /** * The dust limit of the initiator's commitment tx. * - * @generated from protobuf field: uint64 dust_limit = 6; + * @generated from protobuf field: uint64 dust_limit = 6 */ dustLimit: bigint; /** * The maximum amount of coins in millisatoshis that can be pending in this * channel. * - * @generated from protobuf field: uint64 max_value_in_flight = 7; + * @generated from protobuf field: uint64 max_value_in_flight = 7 */ maxValueInFlight: bigint; /** * The minimum amount of satoshis the initiator requires us to have at all * times. * - * @generated from protobuf field: uint64 channel_reserve = 8; + * @generated from protobuf field: uint64 channel_reserve = 8 */ channelReserve: bigint; /** * The smallest HTLC in millisatoshis that the initiator will accept. * - * @generated from protobuf field: uint64 min_htlc = 9; + * @generated from protobuf field: uint64 min_htlc = 9 */ minHtlc: bigint; /** * The initial fee rate that the initiator suggests for both commitment * transactions. * - * @generated from protobuf field: uint64 fee_per_kw = 10; + * @generated from protobuf field: uint64 fee_per_kw = 10 */ feePerKw: bigint; /** @@ -613,40 +650,40 @@ export interface ChannelAcceptRequest { * The number of blocks to use for the relative time lock in the pay-to-self * output of both commitment transactions. * - * @generated from protobuf field: uint32 csv_delay = 11; + * @generated from protobuf field: uint32 csv_delay = 11 */ csvDelay: number; /** * The total number of incoming HTLC's that the initiator will accept. * - * @generated from protobuf field: uint32 max_accepted_htlcs = 12; + * @generated from protobuf field: uint32 max_accepted_htlcs = 12 */ maxAcceptedHtlcs: number; /** * A bit-field which the initiator uses to specify proposed channel * behavior. * - * @generated from protobuf field: uint32 channel_flags = 13; + * @generated from protobuf field: uint32 channel_flags = 13 */ channelFlags: number; /** * The commitment type the initiator wishes to use for the proposed channel. * - * @generated from protobuf field: lnrpc.CommitmentType commitment_type = 14; + * @generated from protobuf field: lnrpc.CommitmentType commitment_type = 14 */ commitmentType: CommitmentType; /** * Whether the initiator wants to open a zero-conf channel via the channel * type. * - * @generated from protobuf field: bool wants_zero_conf = 15; + * @generated from protobuf field: bool wants_zero_conf = 15 */ wantsZeroConf: boolean; /** * Whether the initiator wants to use the scid-alias channel type. This is * separate from the feature bit. * - * @generated from protobuf field: bool wants_scid_alias = 16; + * @generated from protobuf field: bool wants_scid_alias = 16 */ wantsScidAlias: boolean; } @@ -657,13 +694,13 @@ export interface ChannelAcceptResponse { /** * Whether or not the client accepts the channel. * - * @generated from protobuf field: bool accept = 1; + * @generated from protobuf field: bool accept = 1 */ accept: boolean; /** * The pending channel id to which this response applies. * - * @generated from protobuf field: bytes pending_chan_id = 2; + * @generated from protobuf field: bytes pending_chan_id = 2 */ pendingChanId: Uint8Array; /** @@ -675,7 +712,7 @@ export interface ChannelAcceptResponse { * because the meaning of this response is ambiguous. Limited to 500 * characters. * - * @generated from protobuf field: string error = 3; + * @generated from protobuf field: string error = 3 */ error: string; /** @@ -685,14 +722,14 @@ export interface ChannelAcceptResponse { * that the channel open will fail if this value is set for a peer that does * not support this feature bit. * - * @generated from protobuf field: string upfront_shutdown = 4; + * @generated from protobuf field: string upfront_shutdown = 4 */ upfrontShutdown: string; /** * * The csv delay (in blocks) that we require for the remote party. * - * @generated from protobuf field: uint32 csv_delay = 5; + * @generated from protobuf field: uint32 csv_delay = 5 */ csvDelay: number; /** @@ -702,7 +739,7 @@ export interface ChannelAcceptResponse { * them so that there is always a disincentive to broadcast old state (if they * hold 0 sats on their side of the channel, there is nothing to lose). * - * @generated from protobuf field: uint64 reserve_sat = 6; + * @generated from protobuf field: uint64 reserve_sat = 6 */ reserveSat: bigint; /** @@ -710,28 +747,28 @@ export interface ChannelAcceptResponse { * The maximum amount of funds in millisatoshis that we allow the remote peer * to have in outstanding htlcs. * - * @generated from protobuf field: uint64 in_flight_max_msat = 7; + * @generated from protobuf field: uint64 in_flight_max_msat = 7 */ inFlightMaxMsat: bigint; /** * * The maximum number of htlcs that the remote peer can offer us. * - * @generated from protobuf field: uint32 max_htlc_count = 8; + * @generated from protobuf field: uint32 max_htlc_count = 8 */ maxHtlcCount: number; /** * * The minimum value in millisatoshis for incoming htlcs on the channel. * - * @generated from protobuf field: uint64 min_htlc_in = 9; + * @generated from protobuf field: uint64 min_htlc_in = 9 */ minHtlcIn: bigint; /** * * The number of confirmations we require before we consider the channel open. * - * @generated from protobuf field: uint32 min_accept_depth = 10; + * @generated from protobuf field: uint32 min_accept_depth = 10 */ minAcceptDepth: number; /** @@ -740,7 +777,7 @@ export interface ChannelAcceptResponse { * if either side does not have the scid-alias feature bit set. The minimum * depth field must be zero if this is true. * - * @generated from protobuf field: bool zero_conf = 11; + * @generated from protobuf field: bool zero_conf = 11 */ zeroConf: boolean; } @@ -758,7 +795,7 @@ export interface ChannelPoint { * Txid of the funding transaction. When using REST, this field must be * encoded as base64. * - * @generated from protobuf field: bytes funding_txid_bytes = 1; + * @generated from protobuf field: bytes funding_txid_bytes = 1 */ fundingTxidBytes: Uint8Array; } | { @@ -768,7 +805,7 @@ export interface ChannelPoint { * Hex-encoded string representing the byte-reversed hash of the funding * transaction. * - * @generated from protobuf field: string funding_txid_str = 2; + * @generated from protobuf field: string funding_txid_str = 2 */ fundingTxidStr: string; } | { @@ -777,7 +814,7 @@ export interface ChannelPoint { /** * The index of the output of the funding transaction * - * @generated from protobuf field: uint32 output_index = 3; + * @generated from protobuf field: uint32 output_index = 3 */ outputIndex: number; } @@ -788,19 +825,19 @@ export interface OutPoint { /** * Raw bytes representing the transaction id. * - * @generated from protobuf field: bytes txid_bytes = 1; + * @generated from protobuf field: bytes txid_bytes = 1 */ txidBytes: Uint8Array; /** * Reversed, hex-encoded string representing the transaction id. * - * @generated from protobuf field: string txid_str = 2; + * @generated from protobuf field: string txid_str = 2 */ txidStr: string; /** * The index of the output on the transaction. * - * @generated from protobuf field: uint32 output_index = 3; + * @generated from protobuf field: uint32 output_index = 3 */ outputIndex: number; } @@ -811,14 +848,14 @@ export interface PreviousOutPoint { /** * The outpoint in format txid:n. * - * @generated from protobuf field: string outpoint = 1; + * @generated from protobuf field: string outpoint = 1 */ outpoint: string; /** * Denotes if the outpoint is controlled by the internal wallet. * The flag will only detect p2wkh, np2wkh and p2tr inputs as its own. * - * @generated from protobuf field: bool is_our_output = 2; + * @generated from protobuf field: bool is_our_output = 2 */ isOurOutput: boolean; } @@ -829,14 +866,14 @@ export interface LightningAddress { /** * The identity pubkey of the Lightning node. * - * @generated from protobuf field: string pubkey = 1; + * @generated from protobuf field: string pubkey = 1 */ pubkey: string; /** * The network location of the lightning node, e.g. `69.69.69.69:1337` or * `localhost:10011`. * - * @generated from protobuf field: string host = 2; + * @generated from protobuf field: string host = 2 */ host: string; } @@ -847,7 +884,7 @@ export interface EstimateFeeRequest { /** * The map from addresses to amounts for the transaction. * - * @generated from protobuf field: map AddrToAmount = 1 [json_name = "AddrToAmount"]; + * @generated from protobuf field: map AddrToAmount = 1 */ addrToAmount: { [key: string]: bigint; @@ -856,26 +893,26 @@ export interface EstimateFeeRequest { * The target number of blocks that this transaction should be confirmed * by. * - * @generated from protobuf field: int32 target_conf = 2; + * @generated from protobuf field: int32 target_conf = 2 */ targetConf: number; /** * The minimum number of confirmations each one of your outputs used for * the transaction must satisfy. * - * @generated from protobuf field: int32 min_confs = 3; + * @generated from protobuf field: int32 min_confs = 3 */ minConfs: number; /** * Whether unconfirmed outputs should be used as inputs for the transaction. * - * @generated from protobuf field: bool spend_unconfirmed = 4; + * @generated from protobuf field: bool spend_unconfirmed = 4 */ spendUnconfirmed: boolean; /** * The strategy to use for selecting coins during fees estimation. * - * @generated from protobuf field: lnrpc.CoinSelectionStrategy coin_selection_strategy = 5; + * @generated from protobuf field: lnrpc.CoinSelectionStrategy coin_selection_strategy = 5 */ coinSelectionStrategy: CoinSelectionStrategy; } @@ -886,7 +923,7 @@ export interface EstimateFeeResponse { /** * The total fee in satoshis. * - * @generated from protobuf field: int64 fee_sat = 1; + * @generated from protobuf field: int64 fee_sat = 1 */ feeSat: bigint; /** @@ -894,13 +931,13 @@ export interface EstimateFeeResponse { * The fee rate in satoshi/vbyte. * * @deprecated - * @generated from protobuf field: int64 feerate_sat_per_byte = 2 [deprecated = true]; + * @generated from protobuf field: int64 feerate_sat_per_byte = 2 [deprecated = true] */ feerateSatPerByte: bigint; /** * The fee rate in satoshi/vbyte. * - * @generated from protobuf field: uint64 sat_per_vbyte = 3; + * @generated from protobuf field: uint64 sat_per_vbyte = 3 */ satPerVbyte: bigint; } @@ -911,7 +948,7 @@ export interface SendManyRequest { /** * The map from addresses to amounts * - * @generated from protobuf field: map AddrToAmount = 1 [json_name = "AddrToAmount"]; + * @generated from protobuf field: map AddrToAmount = 1 */ addrToAmount: { [key: string]: bigint; @@ -920,14 +957,14 @@ export interface SendManyRequest { * The target number of blocks that this transaction should be confirmed * by. * - * @generated from protobuf field: int32 target_conf = 3; + * @generated from protobuf field: int32 target_conf = 3 */ targetConf: number; /** * A manual fee rate set in sat/vbyte that should be used when crafting the * transaction. * - * @generated from protobuf field: uint64 sat_per_vbyte = 4; + * @generated from protobuf field: uint64 sat_per_vbyte = 4 */ satPerVbyte: bigint; /** @@ -936,32 +973,32 @@ export interface SendManyRequest { * transaction. * * @deprecated - * @generated from protobuf field: int64 sat_per_byte = 5 [deprecated = true]; + * @generated from protobuf field: int64 sat_per_byte = 5 [deprecated = true] */ satPerByte: bigint; /** * An optional label for the transaction, limited to 500 characters. * - * @generated from protobuf field: string label = 6; + * @generated from protobuf field: string label = 6 */ label: string; /** * The minimum number of confirmations each one of your outputs used for * the transaction must satisfy. * - * @generated from protobuf field: int32 min_confs = 7; + * @generated from protobuf field: int32 min_confs = 7 */ minConfs: number; /** * Whether unconfirmed outputs should be used as inputs for the transaction. * - * @generated from protobuf field: bool spend_unconfirmed = 8; + * @generated from protobuf field: bool spend_unconfirmed = 8 */ spendUnconfirmed: boolean; /** * The strategy to use for selecting coins during sending many requests. * - * @generated from protobuf field: lnrpc.CoinSelectionStrategy coin_selection_strategy = 9; + * @generated from protobuf field: lnrpc.CoinSelectionStrategy coin_selection_strategy = 9 */ coinSelectionStrategy: CoinSelectionStrategy; } @@ -972,7 +1009,7 @@ export interface SendManyResponse { /** * The id of the transaction * - * @generated from protobuf field: string txid = 1; + * @generated from protobuf field: string txid = 1 */ txid: string; } @@ -983,27 +1020,27 @@ export interface SendCoinsRequest { /** * The address to send coins to * - * @generated from protobuf field: string addr = 1; + * @generated from protobuf field: string addr = 1 */ addr: string; /** * The amount in satoshis to send * - * @generated from protobuf field: int64 amount = 2; + * @generated from protobuf field: int64 amount = 2 */ amount: bigint; /** * The target number of blocks that this transaction should be confirmed * by. * - * @generated from protobuf field: int32 target_conf = 3; + * @generated from protobuf field: int32 target_conf = 3 */ targetConf: number; /** * A manual fee rate set in sat/vbyte that should be used when crafting the * transaction. * - * @generated from protobuf field: uint64 sat_per_vbyte = 4; + * @generated from protobuf field: uint64 sat_per_vbyte = 4 */ satPerVbyte: bigint; /** @@ -1012,7 +1049,7 @@ export interface SendCoinsRequest { * transaction. * * @deprecated - * @generated from protobuf field: int64 sat_per_byte = 5 [deprecated = true]; + * @generated from protobuf field: int64 sat_per_byte = 5 [deprecated = true] */ satPerByte: bigint; /** @@ -1020,38 +1057,38 @@ export interface SendCoinsRequest { * If set, the amount field should be unset. It indicates lnd will send all * wallet coins or all selected coins to the specified address. * - * @generated from protobuf field: bool send_all = 6; + * @generated from protobuf field: bool send_all = 6 */ sendAll: boolean; /** * An optional label for the transaction, limited to 500 characters. * - * @generated from protobuf field: string label = 7; + * @generated from protobuf field: string label = 7 */ label: string; /** * The minimum number of confirmations each one of your outputs used for * the transaction must satisfy. * - * @generated from protobuf field: int32 min_confs = 8; + * @generated from protobuf field: int32 min_confs = 8 */ minConfs: number; /** * Whether unconfirmed outputs should be used as inputs for the transaction. * - * @generated from protobuf field: bool spend_unconfirmed = 9; + * @generated from protobuf field: bool spend_unconfirmed = 9 */ spendUnconfirmed: boolean; /** * The strategy to use for selecting coins. * - * @generated from protobuf field: lnrpc.CoinSelectionStrategy coin_selection_strategy = 10; + * @generated from protobuf field: lnrpc.CoinSelectionStrategy coin_selection_strategy = 10 */ coinSelectionStrategy: CoinSelectionStrategy; /** * A list of selected outpoints as inputs for the transaction. * - * @generated from protobuf field: repeated lnrpc.OutPoint outpoints = 11; + * @generated from protobuf field: repeated lnrpc.OutPoint outpoints = 11 */ outpoints: OutPoint[]; } @@ -1062,7 +1099,7 @@ export interface SendCoinsResponse { /** * The transaction ID of the transaction * - * @generated from protobuf field: string txid = 1; + * @generated from protobuf field: string txid = 1 */ txid: string; } @@ -1073,19 +1110,19 @@ export interface ListUnspentRequest { /** * The minimum number of confirmations to be included. * - * @generated from protobuf field: int32 min_confs = 1; + * @generated from protobuf field: int32 min_confs = 1 */ minConfs: number; /** * The maximum number of confirmations to be included. * - * @generated from protobuf field: int32 max_confs = 2; + * @generated from protobuf field: int32 max_confs = 2 */ maxConfs: number; /** * An optional filter to only include outputs belonging to an account. * - * @generated from protobuf field: string account = 3; + * @generated from protobuf field: string account = 3 */ account: string; } @@ -1096,7 +1133,7 @@ export interface ListUnspentResponse { /** * A list of utxos * - * @generated from protobuf field: repeated lnrpc.Utxo utxos = 1; + * @generated from protobuf field: repeated lnrpc.Utxo utxos = 1 */ utxos: Utxo[]; } @@ -1107,7 +1144,7 @@ export interface NewAddressRequest { /** * The type of address to generate. * - * @generated from protobuf field: lnrpc.AddressType type = 1; + * @generated from protobuf field: lnrpc.AddressType type = 1 */ type: AddressType; /** @@ -1115,7 +1152,7 @@ export interface NewAddressRequest { * The name of the account to generate a new address for. If empty, the * default wallet account is used. * - * @generated from protobuf field: string account = 2; + * @generated from protobuf field: string account = 2 */ account: string; } @@ -1126,7 +1163,7 @@ export interface NewAddressResponse { /** * The newly generated wallet address * - * @generated from protobuf field: string address = 1; + * @generated from protobuf field: string address = 1 */ address: string; } @@ -1139,7 +1176,7 @@ export interface SignMessageRequest { * The message to be signed. When using REST, this field must be encoded as * base64. * - * @generated from protobuf field: bytes msg = 1; + * @generated from protobuf field: bytes msg = 1 */ msg: Uint8Array; /** @@ -1147,7 +1184,7 @@ export interface SignMessageRequest { * Instead of the default double-SHA256 hashing of the message before signing, * only use one round of hashing instead. * - * @generated from protobuf field: bool single_hash = 2; + * @generated from protobuf field: bool single_hash = 2 */ singleHash: boolean; } @@ -1158,7 +1195,7 @@ export interface SignMessageResponse { /** * The signature for the given message * - * @generated from protobuf field: string signature = 1; + * @generated from protobuf field: string signature = 1 */ signature: string; } @@ -1171,13 +1208,13 @@ export interface VerifyMessageRequest { * The message over which the signature is to be verified. When using REST, * this field must be encoded as base64. * - * @generated from protobuf field: bytes msg = 1; + * @generated from protobuf field: bytes msg = 1 */ msg: Uint8Array; /** * The signature to be verified over the given message * - * @generated from protobuf field: string signature = 2; + * @generated from protobuf field: string signature = 2 */ signature: string; } @@ -1188,13 +1225,13 @@ export interface VerifyMessageResponse { /** * Whether the signature was valid over the given message * - * @generated from protobuf field: bool valid = 1; + * @generated from protobuf field: bool valid = 1 */ valid: boolean; /** * The pubkey recovered from the signature * - * @generated from protobuf field: string pubkey = 2; + * @generated from protobuf field: string pubkey = 2 */ pubkey: string; } @@ -1206,7 +1243,7 @@ export interface ConnectPeerRequest { * * Lightning address of the peer to connect to. * - * @generated from protobuf field: lnrpc.LightningAddress addr = 1; + * @generated from protobuf field: lnrpc.LightningAddress addr = 1 */ addr?: LightningAddress; /** @@ -1214,7 +1251,7 @@ export interface ConnectPeerRequest { * If set, the daemon will attempt to persistently connect to the target * peer. Otherwise, the call will be synchronous. * - * @generated from protobuf field: bool perm = 2; + * @generated from protobuf field: bool perm = 2 */ perm: boolean; /** @@ -1222,7 +1259,7 @@ export interface ConnectPeerRequest { * The connection timeout value (in seconds) for this request. It won't affect * other requests. * - * @generated from protobuf field: uint64 timeout = 3; + * @generated from protobuf field: uint64 timeout = 3 */ timeout: bigint; } @@ -1230,6 +1267,12 @@ export interface ConnectPeerRequest { * @generated from protobuf message lnrpc.ConnectPeerResponse */ export interface ConnectPeerResponse { + /** + * The status of the connect operation. + * + * @generated from protobuf field: string status = 1 + */ + status: string; } /** * @generated from protobuf message lnrpc.DisconnectPeerRequest @@ -1238,7 +1281,7 @@ export interface DisconnectPeerRequest { /** * The pubkey of the node to disconnect from * - * @generated from protobuf field: string pub_key = 1; + * @generated from protobuf field: string pub_key = 1 */ pubKey: string; } @@ -1246,31 +1289,37 @@ export interface DisconnectPeerRequest { * @generated from protobuf message lnrpc.DisconnectPeerResponse */ export interface DisconnectPeerResponse { + /** + * The status of the disconnect operation. + * + * @generated from protobuf field: string status = 1 + */ + status: string; } /** * @generated from protobuf message lnrpc.HTLC */ export interface HTLC { /** - * @generated from protobuf field: bool incoming = 1; + * @generated from protobuf field: bool incoming = 1 */ incoming: boolean; /** - * @generated from protobuf field: int64 amount = 2; + * @generated from protobuf field: int64 amount = 2 */ amount: bigint; /** - * @generated from protobuf field: bytes hash_lock = 3; + * @generated from protobuf field: bytes hash_lock = 3 */ hashLock: Uint8Array; /** - * @generated from protobuf field: uint32 expiration_height = 4; + * @generated from protobuf field: uint32 expiration_height = 4 */ expirationHeight: number; /** * Index identifying the htlc on the channel. * - * @generated from protobuf field: uint64 htlc_index = 5; + * @generated from protobuf field: uint64 htlc_index = 5 */ htlcIndex: bigint; /** @@ -1282,15 +1331,24 @@ export interface HTLC { * for htlcs that need to be forwarded but don't have a forwarding decision * persisted yet. * - * @generated from protobuf field: uint64 forwarding_channel = 6; + * @generated from protobuf field: uint64 forwarding_channel = 6 */ forwardingChannel: bigint; /** * Index identifying the htlc on the forwarding channel. * - * @generated from protobuf field: uint64 forwarding_htlc_index = 7; + * @generated from protobuf field: uint64 forwarding_htlc_index = 7 */ forwardingHtlcIndex: bigint; + /** + * + * Whether the HTLC is locked in. An HTLC is considered locked in when the + * remote party has sent us the `revoke_and_ack` to irrevocably commit this + * HTLC. + * + * @generated from protobuf field: bool locked_in = 8 + */ + lockedIn: boolean; } /** * @generated from protobuf message lnrpc.ChannelConstraints @@ -1301,38 +1359,38 @@ export interface ChannelConstraints { * The CSV delay expressed in relative blocks. If the channel is force closed, * we will need to wait for this many blocks before we can regain our funds. * - * @generated from protobuf field: uint32 csv_delay = 1; + * @generated from protobuf field: uint32 csv_delay = 1 */ csvDelay: number; /** * The minimum satoshis this node is required to reserve in its balance. * - * @generated from protobuf field: uint64 chan_reserve_sat = 2; + * @generated from protobuf field: uint64 chan_reserve_sat = 2 */ chanReserveSat: bigint; /** * The dust limit (in satoshis) of the initiator's commitment tx. * - * @generated from protobuf field: uint64 dust_limit_sat = 3; + * @generated from protobuf field: uint64 dust_limit_sat = 3 */ dustLimitSat: bigint; /** * The maximum amount of coins in millisatoshis that can be pending in this * channel. * - * @generated from protobuf field: uint64 max_pending_amt_msat = 4; + * @generated from protobuf field: uint64 max_pending_amt_msat = 4 */ maxPendingAmtMsat: bigint; /** * The smallest HTLC in millisatoshis that the initiator will accept. * - * @generated from protobuf field: uint64 min_htlc_msat = 5; + * @generated from protobuf field: uint64 min_htlc_msat = 5 */ minHtlcMsat: bigint; /** * The total number of incoming HTLC's that the initiator will accept. * - * @generated from protobuf field: uint32 max_accepted_htlcs = 6; + * @generated from protobuf field: uint32 max_accepted_htlcs = 6 */ maxAcceptedHtlcs: number; } @@ -1343,13 +1401,13 @@ export interface Channel { /** * Whether this channel is active or not * - * @generated from protobuf field: bool active = 1; + * @generated from protobuf field: bool active = 1 */ active: boolean; /** * The identity pubkey of the remote node * - * @generated from protobuf field: string remote_pubkey = 2; + * @generated from protobuf field: string remote_pubkey = 2 */ remotePubkey: string; /** @@ -1358,7 +1416,7 @@ export interface Channel { * will be able to generate a signature for Alice's version of the commitment * transaction. * - * @generated from protobuf field: string channel_point = 3; + * @generated from protobuf field: string channel_point = 3 */ channelPoint: string; /** @@ -1367,25 +1425,25 @@ export interface Channel { * height, the next 3 the index within the block, and the last 2 bytes are the * output index for the channel. * - * @generated from protobuf field: uint64 chan_id = 4 [jstype = JS_STRING]; + * @generated from protobuf field: uint64 chan_id = 4 [jstype = JS_STRING] */ chanId: string; /** * The total amount of funds held in this channel * - * @generated from protobuf field: int64 capacity = 5; + * @generated from protobuf field: int64 capacity = 5 */ capacity: bigint; /** * This node's current balance in this channel * - * @generated from protobuf field: int64 local_balance = 6; + * @generated from protobuf field: int64 local_balance = 6 */ localBalance: bigint; /** * The counterparty's current balance in this channel * - * @generated from protobuf field: int64 remote_balance = 7; + * @generated from protobuf field: int64 remote_balance = 7 */ remoteBalance: bigint; /** @@ -1395,13 +1453,13 @@ export interface Channel { * allow the fee amount to be removed and recalculated with each channel state * update, including updates that happen after a system restart. * - * @generated from protobuf field: int64 commit_fee = 8; + * @generated from protobuf field: int64 commit_fee = 8 */ commitFee: bigint; /** * The weight of the commitment transaction * - * @generated from protobuf field: int64 commit_weight = 9; + * @generated from protobuf field: int64 commit_weight = 9 */ commitWeight: bigint; /** @@ -1410,41 +1468,41 @@ export interface Channel { * at all times, for both the funding transaction and commitment transaction. * This value can later be updated once the channel is open. * - * @generated from protobuf field: int64 fee_per_kw = 10; + * @generated from protobuf field: int64 fee_per_kw = 10 */ feePerKw: bigint; /** * The unsettled balance in this channel * - * @generated from protobuf field: int64 unsettled_balance = 11; + * @generated from protobuf field: int64 unsettled_balance = 11 */ unsettledBalance: bigint; /** * * The total number of satoshis we've sent within this channel. * - * @generated from protobuf field: int64 total_satoshis_sent = 12; + * @generated from protobuf field: int64 total_satoshis_sent = 12 */ totalSatoshisSent: bigint; /** * * The total number of satoshis we've received within this channel. * - * @generated from protobuf field: int64 total_satoshis_received = 13; + * @generated from protobuf field: int64 total_satoshis_received = 13 */ totalSatoshisReceived: bigint; /** * * The total number of updates conducted within this channel. * - * @generated from protobuf field: uint64 num_updates = 14; + * @generated from protobuf field: uint64 num_updates = 14 */ numUpdates: bigint; /** * * The list of active, uncleared HTLCs currently pending within the channel. * - * @generated from protobuf field: repeated lnrpc.HTLC pending_htlcs = 15; + * @generated from protobuf field: repeated lnrpc.HTLC pending_htlcs = 15 */ pendingHtlcs: HTLC[]; /** @@ -1454,25 +1512,25 @@ export interface Channel { * our funds. * * @deprecated - * @generated from protobuf field: uint32 csv_delay = 16 [deprecated = true]; + * @generated from protobuf field: uint32 csv_delay = 16 [deprecated = true] */ csvDelay: number; /** * Whether this channel is advertised to the network or not. * - * @generated from protobuf field: bool private = 17; + * @generated from protobuf field: bool private = 17 */ private: boolean; /** * True if we were the ones that created the channel. * - * @generated from protobuf field: bool initiator = 18; + * @generated from protobuf field: bool initiator = 18 */ initiator: boolean; /** * A set of flags showing the current state of the channel. * - * @generated from protobuf field: string chan_status_flags = 19; + * @generated from protobuf field: string chan_status_flags = 19 */ chanStatusFlags: string; /** @@ -1480,7 +1538,7 @@ export interface Channel { * balance. * * @deprecated - * @generated from protobuf field: int64 local_chan_reserve_sat = 20 [deprecated = true]; + * @generated from protobuf field: int64 local_chan_reserve_sat = 20 [deprecated = true] */ localChanReserveSat: bigint; /** @@ -1489,20 +1547,20 @@ export interface Channel { * its balance. * * @deprecated - * @generated from protobuf field: int64 remote_chan_reserve_sat = 21 [deprecated = true]; + * @generated from protobuf field: int64 remote_chan_reserve_sat = 21 [deprecated = true] */ remoteChanReserveSat: bigint; /** * Deprecated. Use commitment_type. * * @deprecated - * @generated from protobuf field: bool static_remote_key = 22 [deprecated = true]; + * @generated from protobuf field: bool static_remote_key = 22 [deprecated = true] */ staticRemoteKey: boolean; /** * The commitment type used by this channel. * - * @generated from protobuf field: lnrpc.CommitmentType commitment_type = 26; + * @generated from protobuf field: lnrpc.CommitmentType commitment_type = 26 */ commitmentType: CommitmentType; /** @@ -1511,7 +1569,7 @@ export interface Channel { * scoring system. Scores are currently not persisted, so this value may be * less than the lifetime of the channel [EXPERIMENTAL]. * - * @generated from protobuf field: int64 lifetime = 23; + * @generated from protobuf field: int64 lifetime = 23 */ lifetime: bigint; /** @@ -1520,7 +1578,7 @@ export interface Channel { * by the channel scoring system over the lifetime of the channel * [EXPERIMENTAL]. * - * @generated from protobuf field: int64 uptime = 24; + * @generated from protobuf field: int64 uptime = 24 */ uptime: bigint; /** @@ -1531,7 +1589,7 @@ export interface Channel { * request. If this value is not set, you can still choose a payout address by * cooperatively closing with the delivery_address field set. * - * @generated from protobuf field: string close_address = 25; + * @generated from protobuf field: string close_address = 25 */ closeAddress: string; /** @@ -1542,7 +1600,7 @@ export interface Channel { * pushed this amount to our peer, if it is false, the remote peer pushed this * amount to us. * - * @generated from protobuf field: uint64 push_amount_sat = 27; + * @generated from protobuf field: uint64 push_amount_sat = 27 */ pushAmountSat: bigint; /** @@ -1555,19 +1613,19 @@ export interface Channel { * height can be interpreted in two ways: as a relative height if the value is * less than 500,000, or as an absolute height otherwise. * - * @generated from protobuf field: uint32 thaw_height = 28; + * @generated from protobuf field: uint32 thaw_height = 28 */ thawHeight: number; /** * List constraints for the local node. * - * @generated from protobuf field: lnrpc.ChannelConstraints local_constraints = 29; + * @generated from protobuf field: lnrpc.ChannelConstraints local_constraints = 29 */ localConstraints?: ChannelConstraints; /** * List constraints for the remote node. * - * @generated from protobuf field: lnrpc.ChannelConstraints remote_constraints = 30; + * @generated from protobuf field: lnrpc.ChannelConstraints remote_constraints = 30 */ remoteConstraints?: ChannelConstraints; /** @@ -1575,31 +1633,31 @@ export interface Channel { * This lists out the set of alias short channel ids that exist for a channel. * This may be empty. * - * @generated from protobuf field: repeated uint64 alias_scids = 31; + * @generated from protobuf field: repeated uint64 alias_scids = 31 */ aliasScids: bigint[]; /** * Whether or not this is a zero-conf channel. * - * @generated from protobuf field: bool zero_conf = 32; + * @generated from protobuf field: bool zero_conf = 32 */ zeroConf: boolean; /** * This is the confirmed / on-chain zero-conf SCID. * - * @generated from protobuf field: uint64 zero_conf_confirmed_scid = 33; + * @generated from protobuf field: uint64 zero_conf_confirmed_scid = 33 */ zeroConfConfirmedScid: bigint; /** * The configured alias name of our peer. * - * @generated from protobuf field: string peer_alias = 34; + * @generated from protobuf field: string peer_alias = 34 */ peerAlias: string; /** * This is the peer SCID alias. * - * @generated from protobuf field: uint64 peer_scid_alias = 35 [jstype = JS_STRING]; + * @generated from protobuf field: uint64 peer_scid_alias = 35 [jstype = JS_STRING] */ peerScidAlias: string; /** @@ -1608,28 +1666,35 @@ export interface Channel { * useful information. This is only ever stored locally and in no way impacts * the channel's operation. * - * @generated from protobuf field: string memo = 36; + * @generated from protobuf field: string memo = 36 */ memo: string; + /** + * + * Custom channel data that might be populated in custom channels. + * + * @generated from protobuf field: bytes custom_channel_data = 37 + */ + customChannelData: Uint8Array; } /** * @generated from protobuf message lnrpc.ListChannelsRequest */ export interface ListChannelsRequest { /** - * @generated from protobuf field: bool active_only = 1; + * @generated from protobuf field: bool active_only = 1 */ activeOnly: boolean; /** - * @generated from protobuf field: bool inactive_only = 2; + * @generated from protobuf field: bool inactive_only = 2 */ inactiveOnly: boolean; /** - * @generated from protobuf field: bool public_only = 3; + * @generated from protobuf field: bool public_only = 3 */ publicOnly: boolean; /** - * @generated from protobuf field: bool private_only = 4; + * @generated from protobuf field: bool private_only = 4 */ privateOnly: boolean; /** @@ -1637,7 +1702,7 @@ export interface ListChannelsRequest { * Filters the response for channels with a target peer's pubkey. If peer is * empty, all channels will be returned. * - * @generated from protobuf field: bytes peer = 5; + * @generated from protobuf field: bytes peer = 5 */ peer: Uint8Array; /** @@ -1645,7 +1710,7 @@ export interface ListChannelsRequest { * enabled. It is turned off by default in order to avoid degradation of * performance for existing clients. * - * @generated from protobuf field: bool peer_alias_lookup = 6; + * @generated from protobuf field: bool peer_alias_lookup = 6 */ peerAliasLookup: boolean; } @@ -1656,7 +1721,7 @@ export interface ListChannelsResponse { /** * The list of active channels * - * @generated from protobuf field: repeated lnrpc.Channel channels = 11; + * @generated from protobuf field: repeated lnrpc.Channel channels = 11 */ channels: Channel[]; } @@ -1669,13 +1734,13 @@ export interface AliasMap { * For non-zero-conf channels, this is the confirmed SCID. Otherwise, this is * the first assigned "base" alias. * - * @generated from protobuf field: uint64 base_scid = 1; + * @generated from protobuf field: uint64 base_scid = 1 */ baseScid: bigint; /** * The set of all aliases stored for the base SCID. * - * @generated from protobuf field: repeated uint64 aliases = 2; + * @generated from protobuf field: repeated uint64 aliases = 2 */ aliases: bigint[]; } @@ -1689,7 +1754,7 @@ export interface ListAliasesRequest { */ export interface ListAliasesResponse { /** - * @generated from protobuf field: repeated lnrpc.AliasMap alias_maps = 1; + * @generated from protobuf field: repeated lnrpc.AliasMap alias_maps = 1 */ aliasMaps: AliasMap[]; } @@ -1700,61 +1765,61 @@ export interface ChannelCloseSummary { /** * The outpoint (txid:index) of the funding transaction. * - * @generated from protobuf field: string channel_point = 1; + * @generated from protobuf field: string channel_point = 1 */ channelPoint: string; /** * The unique channel ID for the channel. * - * @generated from protobuf field: uint64 chan_id = 2 [jstype = JS_STRING]; + * @generated from protobuf field: uint64 chan_id = 2 [jstype = JS_STRING] */ chanId: string; /** * The hash of the genesis block that this channel resides within. * - * @generated from protobuf field: string chain_hash = 3; + * @generated from protobuf field: string chain_hash = 3 */ chainHash: string; /** * The txid of the transaction which ultimately closed this channel. * - * @generated from protobuf field: string closing_tx_hash = 4; + * @generated from protobuf field: string closing_tx_hash = 4 */ closingTxHash: string; /** * Public key of the remote peer that we formerly had a channel with. * - * @generated from protobuf field: string remote_pubkey = 5; + * @generated from protobuf field: string remote_pubkey = 5 */ remotePubkey: string; /** * Total capacity of the channel. * - * @generated from protobuf field: int64 capacity = 6; + * @generated from protobuf field: int64 capacity = 6 */ capacity: bigint; /** * Height at which the funding transaction was spent. * - * @generated from protobuf field: uint32 close_height = 7; + * @generated from protobuf field: uint32 close_height = 7 */ closeHeight: number; /** * Settled balance at the time of channel closure * - * @generated from protobuf field: int64 settled_balance = 8; + * @generated from protobuf field: int64 settled_balance = 8 */ settledBalance: bigint; /** * The sum of all the time-locked outputs at the time of channel closure * - * @generated from protobuf field: int64 time_locked_balance = 9; + * @generated from protobuf field: int64 time_locked_balance = 9 */ timeLockedBalance: bigint; /** * Details on how the channel was closed. * - * @generated from protobuf field: lnrpc.ChannelCloseSummary.ClosureType close_type = 10; + * @generated from protobuf field: lnrpc.ChannelCloseSummary.ClosureType close_type = 10 */ closeType: ChannelCloseSummary_ClosureType; /** @@ -1763,7 +1828,7 @@ export interface ChannelCloseSummary { * this value may be unknown if the channel was closed before we migrated to * store open channel information after close. * - * @generated from protobuf field: lnrpc.Initiator open_initiator = 11; + * @generated from protobuf field: lnrpc.Initiator open_initiator = 11 */ openInitiator: Initiator; /** @@ -1774,11 +1839,11 @@ export interface ChannelCloseSummary { * initiated a close, and it is possible for both to initiate cooperative or * force closes, although only one party's close will be confirmed on chain. * - * @generated from protobuf field: lnrpc.Initiator close_initiator = 12; + * @generated from protobuf field: lnrpc.Initiator close_initiator = 12 */ closeInitiator: Initiator; /** - * @generated from protobuf field: repeated lnrpc.Resolution resolutions = 13; + * @generated from protobuf field: repeated lnrpc.Resolution resolutions = 13 */ resolutions: Resolution[]; /** @@ -1786,15 +1851,22 @@ export interface ChannelCloseSummary { * This lists out the set of alias short channel ids that existed for the * closed channel. This may be empty. * - * @generated from protobuf field: repeated uint64 alias_scids = 14; + * @generated from protobuf field: repeated uint64 alias_scids = 14 */ aliasScids: bigint[]; /** * The confirmed SCID for a zero-conf channel. * - * @generated from protobuf field: uint64 zero_conf_confirmed_scid = 15 [jstype = JS_STRING]; + * @generated from protobuf field: uint64 zero_conf_confirmed_scid = 15 [jstype = JS_STRING] */ zeroConfConfirmedScid: string; + /** + * The TLV encoded custom channel data records for this output, which might + * be set for custom channels. + * + * @generated from protobuf field: bytes custom_channel_data = 16 + */ + customChannelData: Uint8Array; } /** * @generated from protobuf enum lnrpc.ChannelCloseSummary.ClosureType @@ -1832,32 +1904,32 @@ export interface Resolution { /** * The type of output we are resolving. * - * @generated from protobuf field: lnrpc.ResolutionType resolution_type = 1; + * @generated from protobuf field: lnrpc.ResolutionType resolution_type = 1 */ resolutionType: ResolutionType; /** * The outcome of our on chain action that resolved the outpoint. * - * @generated from protobuf field: lnrpc.ResolutionOutcome outcome = 2; + * @generated from protobuf field: lnrpc.ResolutionOutcome outcome = 2 */ outcome: ResolutionOutcome; /** * The outpoint that was spent by the resolution. * - * @generated from protobuf field: lnrpc.OutPoint outpoint = 3; + * @generated from protobuf field: lnrpc.OutPoint outpoint = 3 */ outpoint?: OutPoint; /** * The amount that was claimed by the resolution. * - * @generated from protobuf field: uint64 amount_sat = 4; + * @generated from protobuf field: uint64 amount_sat = 4 */ amountSat: bigint; /** * The hex-encoded transaction ID of the sweep transaction that spent the * output. * - * @generated from protobuf field: string sweep_txid = 5; + * @generated from protobuf field: string sweep_txid = 5 */ sweepTxid: string; } @@ -1866,27 +1938,27 @@ export interface Resolution { */ export interface ClosedChannelsRequest { /** - * @generated from protobuf field: bool cooperative = 1; + * @generated from protobuf field: bool cooperative = 1 */ cooperative: boolean; /** - * @generated from protobuf field: bool local_force = 2; + * @generated from protobuf field: bool local_force = 2 */ localForce: boolean; /** - * @generated from protobuf field: bool remote_force = 3; + * @generated from protobuf field: bool remote_force = 3 */ remoteForce: boolean; /** - * @generated from protobuf field: bool breach = 4; + * @generated from protobuf field: bool breach = 4 */ breach: boolean; /** - * @generated from protobuf field: bool funding_canceled = 5; + * @generated from protobuf field: bool funding_canceled = 5 */ fundingCanceled: boolean; /** - * @generated from protobuf field: bool abandoned = 6; + * @generated from protobuf field: bool abandoned = 6 */ abandoned: boolean; } @@ -1895,7 +1967,7 @@ export interface ClosedChannelsRequest { */ export interface ClosedChannelsResponse { /** - * @generated from protobuf field: repeated lnrpc.ChannelCloseSummary channels = 1; + * @generated from protobuf field: repeated lnrpc.ChannelCloseSummary channels = 1 */ channels: ChannelCloseSummary[]; } @@ -1906,61 +1978,61 @@ export interface Peer { /** * The identity pubkey of the peer * - * @generated from protobuf field: string pub_key = 1; + * @generated from protobuf field: string pub_key = 1 */ pubKey: string; /** * Network address of the peer; eg `127.0.0.1:10011` * - * @generated from protobuf field: string address = 3; + * @generated from protobuf field: string address = 3 */ address: string; /** * Bytes of data transmitted to this peer * - * @generated from protobuf field: uint64 bytes_sent = 4; + * @generated from protobuf field: uint64 bytes_sent = 4 */ bytesSent: bigint; /** * Bytes of data transmitted from this peer * - * @generated from protobuf field: uint64 bytes_recv = 5; + * @generated from protobuf field: uint64 bytes_recv = 5 */ bytesRecv: bigint; /** * Satoshis sent to this peer * - * @generated from protobuf field: int64 sat_sent = 6; + * @generated from protobuf field: int64 sat_sent = 6 */ satSent: bigint; /** * Satoshis received from this peer * - * @generated from protobuf field: int64 sat_recv = 7; + * @generated from protobuf field: int64 sat_recv = 7 */ satRecv: bigint; /** * A channel is inbound if the counterparty initiated the channel * - * @generated from protobuf field: bool inbound = 8; + * @generated from protobuf field: bool inbound = 8 */ inbound: boolean; /** * Ping time to this peer * - * @generated from protobuf field: int64 ping_time = 9; + * @generated from protobuf field: int64 ping_time = 9 */ pingTime: bigint; /** * The type of sync we are currently performing with this peer. * - * @generated from protobuf field: lnrpc.Peer.SyncType sync_type = 10; + * @generated from protobuf field: lnrpc.Peer.SyncType sync_type = 10 */ syncType: Peer_SyncType; /** * Features advertised by the remote peer in their init message. * - * @generated from protobuf field: map features = 11; + * @generated from protobuf field: map features = 11 */ features: { [key: number]: Feature; @@ -1973,7 +2045,7 @@ export interface Peer { * stored for peers that we have channels open with, to prevent peers from * spamming us with errors at no cost. * - * @generated from protobuf field: repeated lnrpc.TimestampedError errors = 12; + * @generated from protobuf field: repeated lnrpc.TimestampedError errors = 12 */ errors: TimestampedError[]; /** @@ -1983,7 +2055,7 @@ export interface Peer { * time if the peer has not recently flapped, so that we can forgive peers * with historically high flap counts. * - * @generated from protobuf field: int32 flap_count = 13; + * @generated from protobuf field: int32 flap_count = 13 */ flapCount: number; /** @@ -1991,14 +2063,14 @@ export interface Peer { * The timestamp of the last flap we observed for this peer. If this value is * zero, we have not observed any flaps for this peer. * - * @generated from protobuf field: int64 last_flap_ns = 14; + * @generated from protobuf field: int64 last_flap_ns = 14 */ lastFlapNs: bigint; /** * * The last ping payload the peer has sent to us. * - * @generated from protobuf field: bytes last_ping_payload = 15; + * @generated from protobuf field: bytes last_ping_payload = 15 */ lastPingPayload: Uint8Array; } @@ -2042,13 +2114,13 @@ export interface TimestampedError { /** * The unix timestamp in seconds when the error occurred. * - * @generated from protobuf field: uint64 timestamp = 1; + * @generated from protobuf field: uint64 timestamp = 1 */ timestamp: bigint; /** * The string representation of the error sent by our peer. * - * @generated from protobuf field: string error = 2; + * @generated from protobuf field: string error = 2 */ error: string; } @@ -2062,7 +2134,7 @@ export interface ListPeersRequest { * the peer's information, rather than the full set of historic errors we have * stored. * - * @generated from protobuf field: bool latest_error = 1; + * @generated from protobuf field: bool latest_error = 1 */ latestError: boolean; } @@ -2073,7 +2145,7 @@ export interface ListPeersResponse { /** * The list of currently connected peers * - * @generated from protobuf field: repeated lnrpc.Peer peers = 1; + * @generated from protobuf field: repeated lnrpc.Peer peers = 1 */ peers: Peer[]; } @@ -2089,11 +2161,11 @@ export interface PeerEvent { /** * The identity pubkey of the peer. * - * @generated from protobuf field: string pub_key = 1; + * @generated from protobuf field: string pub_key = 1 */ pubKey: string; /** - * @generated from protobuf field: lnrpc.PeerEvent.EventType type = 2; + * @generated from protobuf field: lnrpc.PeerEvent.EventType type = 2 */ type: PeerEvent_EventType; } @@ -2122,94 +2194,94 @@ export interface GetInfoResponse { /** * The version of the LND software that the node is running. * - * @generated from protobuf field: string version = 14; + * @generated from protobuf field: string version = 14 */ version: string; /** * The SHA1 commit hash that the daemon is compiled with. * - * @generated from protobuf field: string commit_hash = 20; + * @generated from protobuf field: string commit_hash = 20 */ commitHash: string; /** * The identity pubkey of the current node. * - * @generated from protobuf field: string identity_pubkey = 1; + * @generated from protobuf field: string identity_pubkey = 1 */ identityPubkey: string; /** * If applicable, the alias of the current node, e.g. "bob" * - * @generated from protobuf field: string alias = 2; + * @generated from protobuf field: string alias = 2 */ alias: string; /** * The color of the current node in hex code format * - * @generated from protobuf field: string color = 17; + * @generated from protobuf field: string color = 17 */ color: string; /** * Number of pending channels * - * @generated from protobuf field: uint32 num_pending_channels = 3; + * @generated from protobuf field: uint32 num_pending_channels = 3 */ numPendingChannels: number; /** * Number of active channels * - * @generated from protobuf field: uint32 num_active_channels = 4; + * @generated from protobuf field: uint32 num_active_channels = 4 */ numActiveChannels: number; /** * Number of inactive channels * - * @generated from protobuf field: uint32 num_inactive_channels = 15; + * @generated from protobuf field: uint32 num_inactive_channels = 15 */ numInactiveChannels: number; /** * Number of peers * - * @generated from protobuf field: uint32 num_peers = 5; + * @generated from protobuf field: uint32 num_peers = 5 */ numPeers: number; /** * The node's current view of the height of the best block * - * @generated from protobuf field: uint32 block_height = 6; + * @generated from protobuf field: uint32 block_height = 6 */ blockHeight: number; /** * The node's current view of the hash of the best block * - * @generated from protobuf field: string block_hash = 8; + * @generated from protobuf field: string block_hash = 8 */ blockHash: string; /** * Timestamp of the block best known to the wallet * - * @generated from protobuf field: int64 best_header_timestamp = 13; + * @generated from protobuf field: int64 best_header_timestamp = 13 */ bestHeaderTimestamp: bigint; /** * Whether the wallet's view is synced to the main chain * - * @generated from protobuf field: bool synced_to_chain = 9; + * @generated from protobuf field: bool synced_to_chain = 9 */ syncedToChain: boolean; /** * Whether we consider ourselves synced with the public channel graph. * - * @generated from protobuf field: bool synced_to_graph = 18; + * @generated from protobuf field: bool synced_to_graph = 18 */ syncedToGraph: boolean; /** * - * Whether the current node is connected to testnet. This field is - * deprecated and the network field should be used instead + * Whether the current node is connected to testnet or testnet4. This field is + * deprecated and the network field should be used instead. * * @deprecated - * @generated from protobuf field: bool testnet = 10 [deprecated = true]; + * @generated from protobuf field: bool testnet = 10 [deprecated = true] */ testnet: boolean; /** @@ -2218,13 +2290,13 @@ export interface GetInfoResponse { * ever contain a single entry since LND will only ever have a single * chain backend during its lifetime. * - * @generated from protobuf field: repeated lnrpc.Chain chains = 16; + * @generated from protobuf field: repeated lnrpc.Chain chains = 16 */ chains: Chain[]; /** * The URIs of the current node. * - * @generated from protobuf field: repeated string uris = 12; + * @generated from protobuf field: repeated string uris = 12 */ uris: string[]; /** @@ -2232,7 +2304,7 @@ export interface GetInfoResponse { * Features that our node has advertised in our init message, node * announcements and invoices. * - * @generated from protobuf field: map features = 19; + * @generated from protobuf field: map features = 19 */ features: { [key: number]: Feature; @@ -2241,13 +2313,13 @@ export interface GetInfoResponse { * * Indicates whether the HTLC interceptor API is in always-on mode. * - * @generated from protobuf field: bool require_htlc_interceptor = 21; + * @generated from protobuf field: bool require_htlc_interceptor = 21 */ requireHtlcInterceptor: boolean; /** * Indicates whether final htlc resolutions are stored on disk. * - * @generated from protobuf field: bool store_final_htlc_resolutions = 22; + * @generated from protobuf field: bool store_final_htlc_resolutions = 22 */ storeFinalHtlcResolutions: boolean; } @@ -2261,13 +2333,13 @@ export interface GetDebugInfoRequest { */ export interface GetDebugInfoResponse { /** - * @generated from protobuf field: map config = 1; + * @generated from protobuf field: map config = 1 */ config: { [key: string]: string; }; /** - * @generated from protobuf field: repeated string log = 2; + * @generated from protobuf field: repeated string log = 2 */ log: string[]; } @@ -2283,19 +2355,19 @@ export interface GetRecoveryInfoResponse { /** * Whether the wallet is in recovery mode * - * @generated from protobuf field: bool recovery_mode = 1; + * @generated from protobuf field: bool recovery_mode = 1 */ recoveryMode: boolean; /** * Whether the wallet recovery progress is finished * - * @generated from protobuf field: bool recovery_finished = 2; + * @generated from protobuf field: bool recovery_finished = 2 */ recoveryFinished: boolean; /** * The recovery progress, ranging from 0 to 1. * - * @generated from protobuf field: double progress = 3; + * @generated from protobuf field: double progress = 3 */ progress: number; } @@ -2308,13 +2380,13 @@ export interface Chain { * The blockchain the node is on (must be bitcoin) * * @deprecated - * @generated from protobuf field: string chain = 1 [deprecated = true]; + * @generated from protobuf field: string chain = 1 [deprecated = true] */ chain: string; /** * The network the node is on (eg regtest, testnet, mainnet) * - * @generated from protobuf field: string network = 2; + * @generated from protobuf field: string network = 2 */ network: string; } @@ -2323,15 +2395,15 @@ export interface Chain { */ export interface ConfirmationUpdate { /** - * @generated from protobuf field: bytes block_sha = 1; + * @generated from protobuf field: bytes block_sha = 1 */ blockSha: Uint8Array; /** - * @generated from protobuf field: int32 block_height = 2; + * @generated from protobuf field: int32 block_height = 2 */ blockHeight: number; /** - * @generated from protobuf field: uint32 num_confs_left = 3; + * @generated from protobuf field: uint32 num_confs_left = 3 */ numConfsLeft: number; } @@ -2340,22 +2412,74 @@ export interface ConfirmationUpdate { */ export interface ChannelOpenUpdate { /** - * @generated from protobuf field: lnrpc.ChannelPoint channel_point = 1; + * @generated from protobuf field: lnrpc.ChannelPoint channel_point = 1 */ channelPoint?: ChannelPoint; } +/** + * @generated from protobuf message lnrpc.CloseOutput + */ +export interface CloseOutput { + /** + * The amount in satoshi of this close output. This amount is the final + * commitment balance of the channel and the actual amount paid out on chain + * might be smaller due to subtracted fees. + * + * @generated from protobuf field: int64 amount_sat = 1 + */ + amountSat: bigint; + /** + * The pkScript of the close output. + * + * @generated from protobuf field: bytes pk_script = 2 + */ + pkScript: Uint8Array; + /** + * Whether this output is for the local or remote node. + * + * @generated from protobuf field: bool is_local = 3 + */ + isLocal: boolean; + /** + * The TLV encoded custom channel data records for this output, which might + * be set for custom channels. + * + * @generated from protobuf field: bytes custom_channel_data = 4 + */ + customChannelData: Uint8Array; +} /** * @generated from protobuf message lnrpc.ChannelCloseUpdate */ export interface ChannelCloseUpdate { /** - * @generated from protobuf field: bytes closing_txid = 1; + * @generated from protobuf field: bytes closing_txid = 1 */ closingTxid: Uint8Array; /** - * @generated from protobuf field: bool success = 2; + * @generated from protobuf field: bool success = 2 */ success: boolean; + /** + * The local channel close output. If the local channel balance was dust to + * begin with, this output will not be set. + * + * @generated from protobuf field: lnrpc.CloseOutput local_close_output = 3 + */ + localCloseOutput?: CloseOutput; + /** + * The remote channel close output. If the remote channel balance was dust + * to begin with, this output will not be set. + * + * @generated from protobuf field: lnrpc.CloseOutput remote_close_output = 4 + */ + remoteCloseOutput?: CloseOutput; + /** + * Any additional outputs that might be added for custom channel types. + * + * @generated from protobuf field: repeated lnrpc.CloseOutput additional_outputs = 5 + */ + additionalOutputs: CloseOutput[]; } /** * @generated from protobuf message lnrpc.CloseChannelRequest @@ -2367,21 +2491,21 @@ export interface CloseChannelRequest { * will be able to generate a signature for Alice's version of the commitment * transaction. * - * @generated from protobuf field: lnrpc.ChannelPoint channel_point = 1; + * @generated from protobuf field: lnrpc.ChannelPoint channel_point = 1 */ channelPoint?: ChannelPoint; /** * If true, then the channel will be closed forcibly. This means the * current commitment transaction will be signed and broadcast. * - * @generated from protobuf field: bool force = 2; + * @generated from protobuf field: bool force = 2 */ force: boolean; /** * The target number of blocks that the closure transaction should be * confirmed by. * - * @generated from protobuf field: int32 target_conf = 3; + * @generated from protobuf field: int32 target_conf = 3 */ targetConf: number; /** @@ -2390,7 +2514,7 @@ export interface CloseChannelRequest { * closure transaction. * * @deprecated - * @generated from protobuf field: int64 sat_per_byte = 4 [deprecated = true]; + * @generated from protobuf field: int64 sat_per_byte = 4 [deprecated = true] */ satPerByte: bigint; /** @@ -2400,14 +2524,14 @@ export interface CloseChannelRequest { * is set, the request to close will fail because the channel must pay out * to the upfront shutdown addresss. * - * @generated from protobuf field: string delivery_address = 5; + * @generated from protobuf field: string delivery_address = 5 */ deliveryAddress: string; /** * A manual fee rate set in sat/vbyte that should be used when crafting the * closure transaction. * - * @generated from protobuf field: uint64 sat_per_vbyte = 6; + * @generated from protobuf field: uint64 sat_per_vbyte = 6 */ satPerVbyte: bigint; /** @@ -2415,15 +2539,19 @@ export interface CloseChannelRequest { * * NOTE: This field is only respected if we're the initiator of the channel. * - * @generated from protobuf field: uint64 max_fee_per_vbyte = 7; + * @generated from protobuf field: uint64 max_fee_per_vbyte = 7 */ maxFeePerVbyte: bigint; /** - * If true, then the rpc call will not block while it awaits a closing txid. - * Consequently this RPC call will not return a closing txid if this value - * is set. + * If true, then the rpc call will not block while it awaits a closing txid + * to be broadcasted to the mempool. To obtain the closing tx one has to + * listen to the stream for the particular updates. Moreover if a coop close + * is specified and this flag is set to true the coop closing flow will be + * initiated even if HTLCs are active on the channel. The channel will wait + * until all HTLCs are resolved and then start the coop closing process. The + * channel will be disabled in the meantime and will disallow any new HTLCs. * - * @generated from protobuf field: bool no_wait = 8; + * @generated from protobuf field: bool no_wait = 8 */ noWait: boolean; } @@ -2437,19 +2565,19 @@ export interface CloseStatusUpdate { update: { oneofKind: "closePending"; /** - * @generated from protobuf field: lnrpc.PendingUpdate close_pending = 1; + * @generated from protobuf field: lnrpc.PendingUpdate close_pending = 1 */ closePending: PendingUpdate; } | { oneofKind: "chanClose"; /** - * @generated from protobuf field: lnrpc.ChannelCloseUpdate chan_close = 3; + * @generated from protobuf field: lnrpc.ChannelCloseUpdate chan_close = 3 */ chanClose: ChannelCloseUpdate; } | { oneofKind: "closeInstant"; /** - * @generated from protobuf field: lnrpc.InstantUpdate close_instant = 4; + * @generated from protobuf field: lnrpc.InstantUpdate close_instant = 4 */ closeInstant: InstantUpdate; } | { @@ -2461,18 +2589,34 @@ export interface CloseStatusUpdate { */ export interface PendingUpdate { /** - * @generated from protobuf field: bytes txid = 1; + * @generated from protobuf field: bytes txid = 1 */ txid: Uint8Array; /** - * @generated from protobuf field: uint32 output_index = 2; + * @generated from protobuf field: uint32 output_index = 2 */ outputIndex: number; + /** + * @generated from protobuf field: int64 fee_per_vbyte = 3 + */ + feePerVbyte: bigint; + /** + * @generated from protobuf field: bool local_close_tx = 4 + */ + localCloseTx: boolean; } /** * @generated from protobuf message lnrpc.InstantUpdate */ export interface InstantUpdate { + /** + * The number of pending HTLCs that are currently active on the channel. + * These HTLCs need to be resolved before the channel can be closed + * cooperatively. + * + * @generated from protobuf field: int32 num_pending_htlcs = 1 + */ + numPendingHtlcs: number; } /** * @generated from protobuf message lnrpc.ReadyForPsbtFunding @@ -2483,7 +2627,7 @@ export interface ReadyForPsbtFunding { * The P2WSH address of the channel funding multisig address that the below * specified amount in satoshis needs to be sent to. * - * @generated from protobuf field: string funding_address = 1; + * @generated from protobuf field: string funding_address = 1 */ fundingAddress: string; /** @@ -2491,7 +2635,7 @@ export interface ReadyForPsbtFunding { * The exact amount in satoshis that needs to be sent to the above address to * fund the pending channel. * - * @generated from protobuf field: int64 funding_amount = 2; + * @generated from protobuf field: int64 funding_amount = 2 */ fundingAmount: bigint; /** @@ -2501,7 +2645,7 @@ export interface ReadyForPsbtFunding { * If no base PSBT was specified, this is an otherwise empty PSBT with exactly * one output. * - * @generated from protobuf field: bytes psbt = 3; + * @generated from protobuf field: bytes psbt = 3 */ psbt: Uint8Array; } @@ -2512,47 +2656,47 @@ export interface BatchOpenChannelRequest { /** * The list of channels to open. * - * @generated from protobuf field: repeated lnrpc.BatchOpenChannel channels = 1; + * @generated from protobuf field: repeated lnrpc.BatchOpenChannel channels = 1 */ channels: BatchOpenChannel[]; /** * The target number of blocks that the funding transaction should be * confirmed by. * - * @generated from protobuf field: int32 target_conf = 2; + * @generated from protobuf field: int32 target_conf = 2 */ targetConf: number; /** * A manual fee rate set in sat/vByte that should be used when crafting the * funding transaction. * - * @generated from protobuf field: int64 sat_per_vbyte = 3; + * @generated from protobuf field: int64 sat_per_vbyte = 3 */ satPerVbyte: bigint; /** * The minimum number of confirmations each one of your outputs used for * the funding transaction must satisfy. * - * @generated from protobuf field: int32 min_confs = 4; + * @generated from protobuf field: int32 min_confs = 4 */ minConfs: number; /** * Whether unconfirmed outputs should be used as inputs for the funding * transaction. * - * @generated from protobuf field: bool spend_unconfirmed = 5; + * @generated from protobuf field: bool spend_unconfirmed = 5 */ spendUnconfirmed: boolean; /** * An optional label for the batch transaction, limited to 500 characters. * - * @generated from protobuf field: string label = 6; + * @generated from protobuf field: string label = 6 */ label: string; /** * The strategy to use for selecting coins during batch opening channels. * - * @generated from protobuf field: lnrpc.CoinSelectionStrategy coin_selection_strategy = 7; + * @generated from protobuf field: lnrpc.CoinSelectionStrategy coin_selection_strategy = 7 */ coinSelectionStrategy: CoinSelectionStrategy; } @@ -2564,41 +2708,41 @@ export interface BatchOpenChannel { * The pubkey of the node to open a channel with. When using REST, this * field must be encoded as base64. * - * @generated from protobuf field: bytes node_pubkey = 1; + * @generated from protobuf field: bytes node_pubkey = 1 */ nodePubkey: Uint8Array; /** * The number of satoshis the wallet should commit to the channel. * - * @generated from protobuf field: int64 local_funding_amount = 2; + * @generated from protobuf field: int64 local_funding_amount = 2 */ localFundingAmount: bigint; /** * The number of satoshis to push to the remote side as part of the initial * commitment state. * - * @generated from protobuf field: int64 push_sat = 3; + * @generated from protobuf field: int64 push_sat = 3 */ pushSat: bigint; /** * Whether this channel should be private, not announced to the greater * network. * - * @generated from protobuf field: bool private = 4; + * @generated from protobuf field: bool private = 4 */ private: boolean; /** * The minimum value in millisatoshi we will require for incoming HTLCs on * the channel. * - * @generated from protobuf field: int64 min_htlc_msat = 5; + * @generated from protobuf field: int64 min_htlc_msat = 5 */ minHtlcMsat: bigint; /** * The delay we require on the remote's commitment transaction. If this is * not set, it will be scaled automatically with the channel size. * - * @generated from protobuf field: uint32 remote_csv_delay = 6; + * @generated from protobuf field: uint32 remote_csv_delay = 6 */ remoteCsvDelay: number; /** @@ -2612,7 +2756,7 @@ export interface BatchOpenChannel { * Note: If this value is set on channel creation, you will *not* be able to * cooperatively close out to a different address. * - * @generated from protobuf field: string close_address = 7; + * @generated from protobuf field: string close_address = 7 */ closeAddress: string; /** @@ -2621,7 +2765,7 @@ export interface BatchOpenChannel { * pending channel ID to identify the channel while it is in the pre-pending * state. * - * @generated from protobuf field: bytes pending_chan_id = 8; + * @generated from protobuf field: bytes pending_chan_id = 8 */ pendingChanId: Uint8Array; /** @@ -2629,7 +2773,7 @@ export interface BatchOpenChannel { * The explicit commitment type to use. Note this field will only be used if * the remote peer supports explicit channel negotiation. * - * @generated from protobuf field: lnrpc.CommitmentType commitment_type = 9; + * @generated from protobuf field: lnrpc.CommitmentType commitment_type = 9 */ commitmentType: CommitmentType; /** @@ -2637,7 +2781,7 @@ export interface BatchOpenChannel { * The maximum amount of coins in millisatoshi that can be pending within * the channel. It only applies to the remote party. * - * @generated from protobuf field: uint64 remote_max_value_in_flight_msat = 10; + * @generated from protobuf field: uint64 remote_max_value_in_flight_msat = 10 */ remoteMaxValueInFlightMsat: bigint; /** @@ -2645,7 +2789,7 @@ export interface BatchOpenChannel { * The maximum number of concurrent HTLCs we will allow the remote party to add * to the commitment transaction. * - * @generated from protobuf field: uint32 remote_max_htlcs = 11; + * @generated from protobuf field: uint32 remote_max_htlcs = 11 */ remoteMaxHtlcs: number; /** @@ -2653,14 +2797,14 @@ export interface BatchOpenChannel { * Max local csv is the maximum csv delay we will allow for our own commitment * transaction. * - * @generated from protobuf field: uint32 max_local_csv = 12; + * @generated from protobuf field: uint32 max_local_csv = 12 */ maxLocalCsv: number; /** * * If this is true, then a zero-conf channel open will be attempted. * - * @generated from protobuf field: bool zero_conf = 13; + * @generated from protobuf field: bool zero_conf = 13 */ zeroConf: boolean; /** @@ -2668,14 +2812,14 @@ export interface BatchOpenChannel { * If this is true, then an option-scid-alias channel-type open will be * attempted. * - * @generated from protobuf field: bool scid_alias = 14; + * @generated from protobuf field: bool scid_alias = 14 */ scidAlias: boolean; /** * * The base fee charged regardless of the number of milli-satoshis sent. * - * @generated from protobuf field: uint64 base_fee = 15; + * @generated from protobuf field: uint64 base_fee = 15 */ baseFee: bigint; /** @@ -2683,7 +2827,7 @@ export interface BatchOpenChannel { * The fee rate in ppm (parts per million) that will be charged in * proportion of the value of each forwarded HTLC. * - * @generated from protobuf field: uint64 fee_rate = 16; + * @generated from protobuf field: uint64 fee_rate = 16 */ feeRate: bigint; /** @@ -2693,7 +2837,7 @@ export interface BatchOpenChannel { * a base_fee of 0 use_base_fee is needed downstream to distinguish whether * to use the default base fee value specified in the config or 0. * - * @generated from protobuf field: bool use_base_fee = 17; + * @generated from protobuf field: bool use_base_fee = 17 */ useBaseFee: boolean; /** @@ -2703,7 +2847,7 @@ export interface BatchOpenChannel { * a fee_rate of 0 use_fee_rate is needed downstream to distinguish whether * to use the default fee rate value specified in the config or 0. * - * @generated from protobuf field: bool use_fee_rate = 18; + * @generated from protobuf field: bool use_fee_rate = 18 */ useFeeRate: boolean; /** @@ -2712,7 +2856,7 @@ export interface BatchOpenChannel { * if specified, must be above the dust limit and below 20% of the channel * capacity. * - * @generated from protobuf field: uint64 remote_chan_reserve_sat = 19; + * @generated from protobuf field: uint64 remote_chan_reserve_sat = 19 */ remoteChanReserveSat: bigint; /** @@ -2721,7 +2865,7 @@ export interface BatchOpenChannel { * useful information. This is only ever stored locally and in no way impacts * the channel's operation. * - * @generated from protobuf field: string memo = 20; + * @generated from protobuf field: string memo = 20 */ memo: string; } @@ -2730,7 +2874,7 @@ export interface BatchOpenChannel { */ export interface BatchOpenChannelResponse { /** - * @generated from protobuf field: repeated lnrpc.PendingUpdate pending_channels = 1; + * @generated from protobuf field: repeated lnrpc.PendingUpdate pending_channels = 1 */ pendingChannels: PendingUpdate[]; } @@ -2742,7 +2886,7 @@ export interface OpenChannelRequest { * A manual fee rate set in sat/vbyte that should be used when crafting the * funding transaction. * - * @generated from protobuf field: uint64 sat_per_vbyte = 1; + * @generated from protobuf field: uint64 sat_per_vbyte = 1 */ satPerVbyte: bigint; /** @@ -2750,7 +2894,7 @@ export interface OpenChannelRequest { * The pubkey of the node to open a channel with. When using REST, this field * must be encoded as base64. * - * @generated from protobuf field: bytes node_pubkey = 2; + * @generated from protobuf field: bytes node_pubkey = 2 */ nodePubkey: Uint8Array; /** @@ -2759,27 +2903,27 @@ export interface OpenChannelRequest { * that the REST gateway supports base64 encoding of bytes fields. * * @deprecated - * @generated from protobuf field: string node_pubkey_string = 3 [deprecated = true]; + * @generated from protobuf field: string node_pubkey_string = 3 [deprecated = true] */ nodePubkeyString: string; /** * The number of satoshis the wallet should commit to the channel * - * @generated from protobuf field: int64 local_funding_amount = 4; + * @generated from protobuf field: int64 local_funding_amount = 4 */ localFundingAmount: bigint; /** * The number of satoshis to push to the remote side as part of the initial * commitment state * - * @generated from protobuf field: int64 push_sat = 5; + * @generated from protobuf field: int64 push_sat = 5 */ pushSat: bigint; /** * The target number of blocks that the funding transaction should be * confirmed by. * - * @generated from protobuf field: int32 target_conf = 6; + * @generated from protobuf field: int32 target_conf = 6 */ targetConf: number; /** @@ -2788,42 +2932,42 @@ export interface OpenChannelRequest { * funding transaction. * * @deprecated - * @generated from protobuf field: int64 sat_per_byte = 7 [deprecated = true]; + * @generated from protobuf field: int64 sat_per_byte = 7 [deprecated = true] */ satPerByte: bigint; /** * Whether this channel should be private, not announced to the greater * network. * - * @generated from protobuf field: bool private = 8; + * @generated from protobuf field: bool private = 8 */ private: boolean; /** * The minimum value in millisatoshi we will require for incoming HTLCs on * the channel. * - * @generated from protobuf field: int64 min_htlc_msat = 9; + * @generated from protobuf field: int64 min_htlc_msat = 9 */ minHtlcMsat: bigint; /** * The delay we require on the remote's commitment transaction. If this is * not set, it will be scaled automatically with the channel size. * - * @generated from protobuf field: uint32 remote_csv_delay = 10; + * @generated from protobuf field: uint32 remote_csv_delay = 10 */ remoteCsvDelay: number; /** * The minimum number of confirmations each one of your outputs used for * the funding transaction must satisfy. * - * @generated from protobuf field: int32 min_confs = 11; + * @generated from protobuf field: int32 min_confs = 11 */ minConfs: number; /** * Whether unconfirmed outputs should be used as inputs for the funding * transaction. * - * @generated from protobuf field: bool spend_unconfirmed = 12; + * @generated from protobuf field: bool spend_unconfirmed = 12 */ spendUnconfirmed: boolean; /** @@ -2837,7 +2981,7 @@ export interface OpenChannelRequest { * Note: If this value is set on channel creation, you will *not* be able to * cooperatively close out to a different address. * - * @generated from protobuf field: string close_address = 13; + * @generated from protobuf field: string close_address = 13 */ closeAddress: string; /** @@ -2848,7 +2992,7 @@ export interface OpenChannelRequest { * that is generated by the wallet as normal, or signal that signing will be * carried out in an interactive manner (PSBT based). * - * @generated from protobuf field: lnrpc.FundingShim funding_shim = 14; + * @generated from protobuf field: lnrpc.FundingShim funding_shim = 14 */ fundingShim?: FundingShim; /** @@ -2856,7 +3000,7 @@ export interface OpenChannelRequest { * The maximum amount of coins in millisatoshi that can be pending within * the channel. It only applies to the remote party. * - * @generated from protobuf field: uint64 remote_max_value_in_flight_msat = 15; + * @generated from protobuf field: uint64 remote_max_value_in_flight_msat = 15 */ remoteMaxValueInFlightMsat: bigint; /** @@ -2864,7 +3008,7 @@ export interface OpenChannelRequest { * The maximum number of concurrent HTLCs we will allow the remote party to add * to the commitment transaction. * - * @generated from protobuf field: uint32 remote_max_htlcs = 16; + * @generated from protobuf field: uint32 remote_max_htlcs = 16 */ remoteMaxHtlcs: number; /** @@ -2872,7 +3016,7 @@ export interface OpenChannelRequest { * Max local csv is the maximum csv delay we will allow for our own commitment * transaction. * - * @generated from protobuf field: uint32 max_local_csv = 17; + * @generated from protobuf field: uint32 max_local_csv = 17 */ maxLocalCsv: number; /** @@ -2880,14 +3024,14 @@ export interface OpenChannelRequest { * The explicit commitment type to use. Note this field will only be used if * the remote peer supports explicit channel negotiation. * - * @generated from protobuf field: lnrpc.CommitmentType commitment_type = 18; + * @generated from protobuf field: lnrpc.CommitmentType commitment_type = 18 */ commitmentType: CommitmentType; /** * * If this is true, then a zero-conf channel open will be attempted. * - * @generated from protobuf field: bool zero_conf = 19; + * @generated from protobuf field: bool zero_conf = 19 */ zeroConf: boolean; /** @@ -2895,14 +3039,14 @@ export interface OpenChannelRequest { * If this is true, then an option-scid-alias channel-type open will be * attempted. * - * @generated from protobuf field: bool scid_alias = 20; + * @generated from protobuf field: bool scid_alias = 20 */ scidAlias: boolean; /** * * The base fee charged regardless of the number of milli-satoshis sent. * - * @generated from protobuf field: uint64 base_fee = 21; + * @generated from protobuf field: uint64 base_fee = 21 */ baseFee: bigint; /** @@ -2910,7 +3054,7 @@ export interface OpenChannelRequest { * The fee rate in ppm (parts per million) that will be charged in * proportion of the value of each forwarded HTLC. * - * @generated from protobuf field: uint64 fee_rate = 22; + * @generated from protobuf field: uint64 fee_rate = 22 */ feeRate: bigint; /** @@ -2920,7 +3064,7 @@ export interface OpenChannelRequest { * a base_fee of 0 use_base_fee is needed downstream to distinguish whether * to use the default base fee value specified in the config or 0. * - * @generated from protobuf field: bool use_base_fee = 23; + * @generated from protobuf field: bool use_base_fee = 23 */ useBaseFee: boolean; /** @@ -2930,7 +3074,7 @@ export interface OpenChannelRequest { * a fee_rate of 0 use_fee_rate is needed downstream to distinguish whether * to use the default fee rate value specified in the config or 0. * - * @generated from protobuf field: bool use_fee_rate = 24; + * @generated from protobuf field: bool use_fee_rate = 24 */ useFeeRate: boolean; /** @@ -2939,7 +3083,7 @@ export interface OpenChannelRequest { * if specified, must be above the dust limit and below 20% of the channel * capacity. * - * @generated from protobuf field: uint64 remote_chan_reserve_sat = 25; + * @generated from protobuf field: uint64 remote_chan_reserve_sat = 25 */ remoteChanReserveSat: bigint; /** @@ -2948,7 +3092,7 @@ export interface OpenChannelRequest { * internal wallet to open the channel, and the LocalFundingAmount field must * be zero and is ignored. * - * @generated from protobuf field: bool fund_max = 26; + * @generated from protobuf field: bool fund_max = 26 */ fundMax: boolean; /** @@ -2957,14 +3101,14 @@ export interface OpenChannelRequest { * useful information. This is only ever stored locally and in no way impacts * the channel's operation. * - * @generated from protobuf field: string memo = 27; + * @generated from protobuf field: string memo = 27 */ memo: string; /** * * A list of selected outpoints that are allocated for channel funding. * - * @generated from protobuf field: repeated lnrpc.OutPoint outpoints = 28; + * @generated from protobuf field: repeated lnrpc.OutPoint outpoints = 28 */ outpoints: OutPoint[]; } @@ -2982,7 +3126,7 @@ export interface OpenStatusUpdate { * Signals that the channel is now fully negotiated and the funding * transaction published. * - * @generated from protobuf field: lnrpc.PendingUpdate chan_pending = 1; + * @generated from protobuf field: lnrpc.PendingUpdate chan_pending = 1 */ chanPending: PendingUpdate; } | { @@ -2992,7 +3136,7 @@ export interface OpenStatusUpdate { * Signals that the channel's funding transaction has now reached the * required number of confirmations on chain and can be used. * - * @generated from protobuf field: lnrpc.ChannelOpenUpdate chan_open = 3; + * @generated from protobuf field: lnrpc.ChannelOpenUpdate chan_open = 3 */ chanOpen: ChannelOpenUpdate; } | { @@ -3002,7 +3146,7 @@ export interface OpenStatusUpdate { * Signals that the funding process has been suspended and the construction * of a PSBT that funds the channel PK script is now required. * - * @generated from protobuf field: lnrpc.ReadyForPsbtFunding psbt_fund = 5; + * @generated from protobuf field: lnrpc.ReadyForPsbtFunding psbt_fund = 5 */ psbtFund: ReadyForPsbtFunding; } | { @@ -3013,7 +3157,7 @@ export interface OpenStatusUpdate { * The pending channel ID of the created channel. This value may be used to * further the funding flow manually via the FundingStateStep method. * - * @generated from protobuf field: bytes pending_chan_id = 4; + * @generated from protobuf field: bytes pending_chan_id = 4 */ pendingChanId: Uint8Array; } @@ -3024,13 +3168,13 @@ export interface KeyLocator { /** * The family of key being identified. * - * @generated from protobuf field: int32 key_family = 1; + * @generated from protobuf field: int32 key_family = 1 */ keyFamily: number; /** * The precise index of the key being identified. * - * @generated from protobuf field: int32 key_index = 2; + * @generated from protobuf field: int32 key_index = 2 */ keyIndex: number; } @@ -3042,14 +3186,14 @@ export interface KeyDescriptor { * * The raw bytes of the key being identified. * - * @generated from protobuf field: bytes raw_key_bytes = 1; + * @generated from protobuf field: bytes raw_key_bytes = 1 */ rawKeyBytes: Uint8Array; /** * * The key locator that identifies which key to use for signing. * - * @generated from protobuf field: lnrpc.KeyLocator key_loc = 2; + * @generated from protobuf field: lnrpc.KeyLocator key_loc = 2 */ keyLoc?: KeyLocator; } @@ -3062,25 +3206,25 @@ export interface ChanPointShim { * The size of the pre-crafted output to be used as the channel point for this * channel funding. * - * @generated from protobuf field: int64 amt = 1; + * @generated from protobuf field: int64 amt = 1 */ amt: bigint; /** * The target channel point to refrence in created commitment transactions. * - * @generated from protobuf field: lnrpc.ChannelPoint chan_point = 2; + * @generated from protobuf field: lnrpc.ChannelPoint chan_point = 2 */ chanPoint?: ChannelPoint; /** * Our local key to use when creating the multi-sig output. * - * @generated from protobuf field: lnrpc.KeyDescriptor local_key = 3; + * @generated from protobuf field: lnrpc.KeyDescriptor local_key = 3 */ localKey?: KeyDescriptor; /** * The key of the remote party to use when creating the multi-sig output. * - * @generated from protobuf field: bytes remote_key = 4; + * @generated from protobuf field: bytes remote_key = 4 */ remoteKey: Uint8Array; /** @@ -3090,7 +3234,7 @@ export interface ChanPointShim { * should only be set if the responder is already expecting a specific pending * channel ID. * - * @generated from protobuf field: bytes pending_chan_id = 5; + * @generated from protobuf field: bytes pending_chan_id = 5 */ pendingChanId: Uint8Array; /** @@ -3101,14 +3245,14 @@ export interface ChanPointShim { * channel. The height can be interpreted in two ways: as a relative height if * the value is less than 500,000, or as an absolute height otherwise. * - * @generated from protobuf field: uint32 thaw_height = 6; + * @generated from protobuf field: uint32 thaw_height = 6 */ thawHeight: number; /** * * Indicates that the funding output is using a MuSig2 multi-sig output. * - * @generated from protobuf field: bool musig2 = 7; + * @generated from protobuf field: bool musig2 = 7 */ musig2: boolean; } @@ -3122,7 +3266,7 @@ export interface PsbtShim { * channel ID to identify the PSBT state machine when interacting with it and * on the wire protocol to initiate the funding request. * - * @generated from protobuf field: bytes pending_chan_id = 1; + * @generated from protobuf field: bytes pending_chan_id = 1 */ pendingChanId: Uint8Array; /** @@ -3130,7 +3274,7 @@ export interface PsbtShim { * An optional base PSBT the new channel output will be added to. If this is * non-empty, it must be a binary serialized PSBT. * - * @generated from protobuf field: bytes base_psbt = 2; + * @generated from protobuf field: bytes base_psbt = 2 */ basePsbt: Uint8Array; /** @@ -3142,7 +3286,7 @@ export interface PsbtShim { * after the negotiation with the remote peer. In a batch of channel openings * this flag should be set to true for every channel but the very last. * - * @generated from protobuf field: bool no_publish = 3; + * @generated from protobuf field: bool no_publish = 3 */ noPublish: boolean; } @@ -3160,7 +3304,7 @@ export interface FundingShim { * A channel shim where the channel point was fully constructed outside * of lnd's wallet and the transaction might already be published. * - * @generated from protobuf field: lnrpc.ChanPointShim chan_point_shim = 1; + * @generated from protobuf field: lnrpc.ChanPointShim chan_point_shim = 1 */ chanPointShim: ChanPointShim; } | { @@ -3170,7 +3314,7 @@ export interface FundingShim { * A channel shim that uses a PSBT to fund and sign the channel funding * transaction. * - * @generated from protobuf field: lnrpc.PsbtShim psbt_shim = 2; + * @generated from protobuf field: lnrpc.PsbtShim psbt_shim = 2 */ psbtShim: PsbtShim; } | { @@ -3184,7 +3328,7 @@ export interface FundingShimCancel { /** * The pending channel ID of the channel to cancel the funding shim for. * - * @generated from protobuf field: bytes pending_chan_id = 1; + * @generated from protobuf field: bytes pending_chan_id = 1 */ pendingChanId: Uint8Array; } @@ -3198,13 +3342,13 @@ export interface FundingPsbtVerify { * amount to the PK script returned in the open channel message in a previous * step. * - * @generated from protobuf field: bytes funded_psbt = 1; + * @generated from protobuf field: bytes funded_psbt = 1 */ fundedPsbt: Uint8Array; /** * The pending channel ID of the channel to get the PSBT for. * - * @generated from protobuf field: bytes pending_chan_id = 2; + * @generated from protobuf field: bytes pending_chan_id = 2 */ pendingChanId: Uint8Array; /** @@ -3220,7 +3364,7 @@ export interface FundingPsbtVerify { * TXID changes between this call and the publish step then the channel will * never be created and the funds will be in limbo. * - * @generated from protobuf field: bool skip_finalize = 3; + * @generated from protobuf field: bool skip_finalize = 3 */ skipFinalize: boolean; } @@ -3234,13 +3378,13 @@ export interface FundingPsbtFinalize { * capacity amount to the PK script returned in the open channel message in a * previous step. Cannot be set at the same time as final_raw_tx. * - * @generated from protobuf field: bytes signed_psbt = 1; + * @generated from protobuf field: bytes signed_psbt = 1 */ signedPsbt: Uint8Array; /** * The pending channel ID of the channel to get the PSBT for. * - * @generated from protobuf field: bytes pending_chan_id = 2; + * @generated from protobuf field: bytes pending_chan_id = 2 */ pendingChanId: Uint8Array; /** @@ -3249,7 +3393,7 @@ export interface FundingPsbtFinalize { * wire format transaction can also be specified directly. Cannot be set at the * same time as signed_psbt. * - * @generated from protobuf field: bytes final_raw_tx = 3; + * @generated from protobuf field: bytes final_raw_tx = 3 */ finalRawTx: Uint8Array; } @@ -3268,7 +3412,7 @@ export interface FundingTransitionMsg { * channel funding has began by the remote party, as it is intended as a * preparatory step for the full channel funding. * - * @generated from protobuf field: lnrpc.FundingShim shim_register = 1; + * @generated from protobuf field: lnrpc.FundingShim shim_register = 1 */ shimRegister: FundingShim; } | { @@ -3276,7 +3420,7 @@ export interface FundingTransitionMsg { /** * Used to cancel an existing registered funding shim. * - * @generated from protobuf field: lnrpc.FundingShimCancel shim_cancel = 2; + * @generated from protobuf field: lnrpc.FundingShimCancel shim_cancel = 2 */ shimCancel: FundingShimCancel; } | { @@ -3287,7 +3431,7 @@ export interface FundingTransitionMsg { * through a PSBT. This step verifies that the PSBT contains the correct * outputs to fund the channel. * - * @generated from protobuf field: lnrpc.FundingPsbtVerify psbt_verify = 3; + * @generated from protobuf field: lnrpc.FundingPsbtVerify psbt_verify = 3 */ psbtVerify: FundingPsbtVerify; } | { @@ -3299,7 +3443,7 @@ export interface FundingTransitionMsg { * negotiation with the peer and finally publishes the resulting funding * transaction. * - * @generated from protobuf field: lnrpc.FundingPsbtFinalize psbt_finalize = 4; + * @generated from protobuf field: lnrpc.FundingPsbtFinalize psbt_finalize = 4 */ psbtFinalize: FundingPsbtFinalize; } | { @@ -3318,25 +3462,25 @@ export interface PendingHTLC { /** * The direction within the channel that the htlc was sent * - * @generated from protobuf field: bool incoming = 1; + * @generated from protobuf field: bool incoming = 1 */ incoming: boolean; /** * The total value of the htlc * - * @generated from protobuf field: int64 amount = 2; + * @generated from protobuf field: int64 amount = 2 */ amount: bigint; /** * The final output to be swept back to the user's wallet * - * @generated from protobuf field: string outpoint = 3; + * @generated from protobuf field: string outpoint = 3 */ outpoint: string; /** * The next block height at which we can spend the current stage * - * @generated from protobuf field: uint32 maturity_height = 4; + * @generated from protobuf field: uint32 maturity_height = 4 */ maturityHeight: number; /** @@ -3345,13 +3489,13 @@ export interface PendingHTLC { * Negative values indicate how many blocks have passed since becoming * mature. * - * @generated from protobuf field: int32 blocks_til_maturity = 5; + * @generated from protobuf field: int32 blocks_til_maturity = 5 */ blocksTilMaturity: number; /** * Indicates whether the htlc is in its first or second stage of recovery * - * @generated from protobuf field: uint32 stage = 6; + * @generated from protobuf field: uint32 stage = 6 */ stage: number; } @@ -3363,7 +3507,7 @@ export interface PendingChannelsRequest { * Indicates whether to include the raw transaction hex for * waiting_close_channels. * - * @generated from protobuf field: bool include_raw_tx = 1; + * @generated from protobuf field: bool include_raw_tx = 1 */ includeRawTx: boolean; } @@ -3374,13 +3518,13 @@ export interface PendingChannelsResponse { /** * The balance in satoshis encumbered in pending channels * - * @generated from protobuf field: int64 total_limbo_balance = 1; + * @generated from protobuf field: int64 total_limbo_balance = 1 */ totalLimboBalance: bigint; /** * Channels pending opening * - * @generated from protobuf field: repeated lnrpc.PendingChannelsResponse.PendingOpenChannel pending_open_channels = 2; + * @generated from protobuf field: repeated lnrpc.PendingChannelsResponse.PendingOpenChannel pending_open_channels = 2 */ pendingOpenChannels: PendingChannelsResponse_PendingOpenChannel[]; /** @@ -3390,19 +3534,19 @@ export interface PendingChannelsResponse { * considered closed from the time we see them on chain. * * @deprecated - * @generated from protobuf field: repeated lnrpc.PendingChannelsResponse.ClosedChannel pending_closing_channels = 3 [deprecated = true]; + * @generated from protobuf field: repeated lnrpc.PendingChannelsResponse.ClosedChannel pending_closing_channels = 3 [deprecated = true] */ pendingClosingChannels: PendingChannelsResponse_ClosedChannel[]; /** * Channels pending force closing * - * @generated from protobuf field: repeated lnrpc.PendingChannelsResponse.ForceClosedChannel pending_force_closing_channels = 4; + * @generated from protobuf field: repeated lnrpc.PendingChannelsResponse.ForceClosedChannel pending_force_closing_channels = 4 */ pendingForceClosingChannels: PendingChannelsResponse_ForceClosedChannel[]; /** * Channels waiting for closing tx to confirm * - * @generated from protobuf field: repeated lnrpc.PendingChannelsResponse.WaitingCloseChannel waiting_close_channels = 5; + * @generated from protobuf field: repeated lnrpc.PendingChannelsResponse.WaitingCloseChannel waiting_close_channels = 5 */ waitingCloseChannels: PendingChannelsResponse_WaitingCloseChannel[]; } @@ -3411,30 +3555,30 @@ export interface PendingChannelsResponse { */ export interface PendingChannelsResponse_PendingChannel { /** - * @generated from protobuf field: string remote_node_pub = 1; + * @generated from protobuf field: string remote_node_pub = 1 */ remoteNodePub: string; /** - * @generated from protobuf field: string channel_point = 2; + * @generated from protobuf field: string channel_point = 2 */ channelPoint: string; /** - * @generated from protobuf field: int64 capacity = 3; + * @generated from protobuf field: int64 capacity = 3 */ capacity: bigint; /** - * @generated from protobuf field: int64 local_balance = 4; + * @generated from protobuf field: int64 local_balance = 4 */ localBalance: bigint; /** - * @generated from protobuf field: int64 remote_balance = 5; + * @generated from protobuf field: int64 remote_balance = 5 */ remoteBalance: bigint; /** * The minimum satoshis this node is required to reserve in its * balance. * - * @generated from protobuf field: int64 local_chan_reserve_sat = 6; + * @generated from protobuf field: int64 local_chan_reserve_sat = 6 */ localChanReserveSat: bigint; /** @@ -3442,37 +3586,37 @@ export interface PendingChannelsResponse_PendingChannel { * The minimum satoshis the other node is required to reserve in its * balance. * - * @generated from protobuf field: int64 remote_chan_reserve_sat = 7; + * @generated from protobuf field: int64 remote_chan_reserve_sat = 7 */ remoteChanReserveSat: bigint; /** * The party that initiated opening the channel. * - * @generated from protobuf field: lnrpc.Initiator initiator = 8; + * @generated from protobuf field: lnrpc.Initiator initiator = 8 */ initiator: Initiator; /** * The commitment type used by this channel. * - * @generated from protobuf field: lnrpc.CommitmentType commitment_type = 9; + * @generated from protobuf field: lnrpc.CommitmentType commitment_type = 9 */ commitmentType: CommitmentType; /** * Total number of forwarding packages created in this channel. * - * @generated from protobuf field: int64 num_forwarding_packages = 10; + * @generated from protobuf field: int64 num_forwarding_packages = 10 */ numForwardingPackages: bigint; /** * A set of flags showing the current state of the channel. * - * @generated from protobuf field: string chan_status_flags = 11; + * @generated from protobuf field: string chan_status_flags = 11 */ chanStatusFlags: string; /** * Whether this channel is advertised to the network or not. * - * @generated from protobuf field: bool private = 12; + * @generated from protobuf field: bool private = 12 */ private: boolean; /** @@ -3481,9 +3625,16 @@ export interface PendingChannelsResponse_PendingChannel { * useful information. This is only ever stored locally and in no way * impacts the channel's operation. * - * @generated from protobuf field: string memo = 13; + * @generated from protobuf field: string memo = 13 */ memo: string; + /** + * + * Custom channel data that might be populated in custom channels. + * + * @generated from protobuf field: bytes custom_channel_data = 34 + */ + customChannelData: Uint8Array; } /** * @generated from protobuf message lnrpc.PendingChannelsResponse.PendingOpenChannel @@ -3492,7 +3643,7 @@ export interface PendingChannelsResponse_PendingOpenChannel { /** * The pending channel * - * @generated from protobuf field: lnrpc.PendingChannelsResponse.PendingChannel channel = 1; + * @generated from protobuf field: lnrpc.PendingChannelsResponse.PendingChannel channel = 1 */ channel?: PendingChannelsResponse_PendingChannel; /** @@ -3503,13 +3654,13 @@ export interface PendingChannelsResponse_PendingOpenChannel { * each channel state update, including updates that happen after a system * restart. * - * @generated from protobuf field: int64 commit_fee = 4; + * @generated from protobuf field: int64 commit_fee = 4 */ commitFee: bigint; /** * The weight of the commitment transaction * - * @generated from protobuf field: int64 commit_weight = 5; + * @generated from protobuf field: int64 commit_weight = 5 */ commitWeight: bigint; /** @@ -3518,7 +3669,7 @@ export interface PendingChannelsResponse_PendingOpenChannel { * pay at all times, for both the funding transaction and commitment * transaction. This value can later be updated once the channel is open. * - * @generated from protobuf field: int64 fee_per_kw = 6; + * @generated from protobuf field: int64 fee_per_kw = 6 */ feePerKw: bigint; /** @@ -3532,7 +3683,7 @@ export interface PendingChannelsResponse_PendingOpenChannel { * very likely canceled the funding and the channel will never become * fully operational. * - * @generated from protobuf field: int32 funding_expiry_blocks = 3; + * @generated from protobuf field: int32 funding_expiry_blocks = 3 */ fundingExpiryBlocks: number; } @@ -3543,13 +3694,13 @@ export interface PendingChannelsResponse_WaitingCloseChannel { /** * The pending channel waiting for closing tx to confirm * - * @generated from protobuf field: lnrpc.PendingChannelsResponse.PendingChannel channel = 1; + * @generated from protobuf field: lnrpc.PendingChannelsResponse.PendingChannel channel = 1 */ channel?: PendingChannelsResponse_PendingChannel; /** * The balance in satoshis encumbered in this channel * - * @generated from protobuf field: int64 limbo_balance = 2; + * @generated from protobuf field: int64 limbo_balance = 2 */ limboBalance: bigint; /** @@ -3557,20 +3708,20 @@ export interface PendingChannelsResponse_WaitingCloseChannel { * A list of valid commitment transactions. Any of these can confirm at * this point. * - * @generated from protobuf field: lnrpc.PendingChannelsResponse.Commitments commitments = 3; + * @generated from protobuf field: lnrpc.PendingChannelsResponse.Commitments commitments = 3 */ commitments?: PendingChannelsResponse_Commitments; /** * The transaction id of the closing transaction * - * @generated from protobuf field: string closing_txid = 4; + * @generated from protobuf field: string closing_txid = 4 */ closingTxid: string; /** * The raw hex encoded bytes of the closing transaction. Included if * include_raw_tx in the request is true. * - * @generated from protobuf field: string closing_tx_hex = 5; + * @generated from protobuf field: string closing_tx_hex = 5 */ closingTxHex: string; } @@ -3581,19 +3732,19 @@ export interface PendingChannelsResponse_Commitments { /** * Hash of the local version of the commitment tx. * - * @generated from protobuf field: string local_txid = 1; + * @generated from protobuf field: string local_txid = 1 */ localTxid: string; /** * Hash of the remote version of the commitment tx. * - * @generated from protobuf field: string remote_txid = 2; + * @generated from protobuf field: string remote_txid = 2 */ remoteTxid: string; /** * Hash of the remote pending version of the commitment tx. * - * @generated from protobuf field: string remote_pending_txid = 3; + * @generated from protobuf field: string remote_pending_txid = 3 */ remotePendingTxid: string; /** @@ -3601,7 +3752,7 @@ export interface PendingChannelsResponse_Commitments { * The amount in satoshis calculated to be paid in fees for the local * commitment. * - * @generated from protobuf field: uint64 local_commit_fee_sat = 4; + * @generated from protobuf field: uint64 local_commit_fee_sat = 4 */ localCommitFeeSat: bigint; /** @@ -3609,7 +3760,7 @@ export interface PendingChannelsResponse_Commitments { * The amount in satoshis calculated to be paid in fees for the remote * commitment. * - * @generated from protobuf field: uint64 remote_commit_fee_sat = 5; + * @generated from protobuf field: uint64 remote_commit_fee_sat = 5 */ remoteCommitFeeSat: bigint; /** @@ -3617,7 +3768,7 @@ export interface PendingChannelsResponse_Commitments { * The amount in satoshis calculated to be paid in fees for the remote * pending commitment. * - * @generated from protobuf field: uint64 remote_pending_commit_fee_sat = 6; + * @generated from protobuf field: uint64 remote_pending_commit_fee_sat = 6 */ remotePendingCommitFeeSat: bigint; } @@ -3628,13 +3779,13 @@ export interface PendingChannelsResponse_ClosedChannel { /** * The pending channel to be closed * - * @generated from protobuf field: lnrpc.PendingChannelsResponse.PendingChannel channel = 1; + * @generated from protobuf field: lnrpc.PendingChannelsResponse.PendingChannel channel = 1 */ channel?: PendingChannelsResponse_PendingChannel; /** * The transaction id of the closing transaction * - * @generated from protobuf field: string closing_txid = 2; + * @generated from protobuf field: string closing_txid = 2 */ closingTxid: string; } @@ -3645,25 +3796,25 @@ export interface PendingChannelsResponse_ForceClosedChannel { /** * The pending channel to be force closed * - * @generated from protobuf field: lnrpc.PendingChannelsResponse.PendingChannel channel = 1; + * @generated from protobuf field: lnrpc.PendingChannelsResponse.PendingChannel channel = 1 */ channel?: PendingChannelsResponse_PendingChannel; /** * The transaction id of the closing transaction * - * @generated from protobuf field: string closing_txid = 2; + * @generated from protobuf field: string closing_txid = 2 */ closingTxid: string; /** * The balance in satoshis encumbered in this pending channel * - * @generated from protobuf field: int64 limbo_balance = 3; + * @generated from protobuf field: int64 limbo_balance = 3 */ limboBalance: bigint; /** * The height at which funds can be swept into the wallet * - * @generated from protobuf field: uint32 maturity_height = 4; + * @generated from protobuf field: uint32 maturity_height = 4 */ maturityHeight: number; /** @@ -3672,21 +3823,21 @@ export interface PendingChannelsResponse_ForceClosedChannel { * Negative values indicate how many blocks have passed since becoming * mature. * - * @generated from protobuf field: int32 blocks_til_maturity = 5; + * @generated from protobuf field: int32 blocks_til_maturity = 5 */ blocksTilMaturity: number; /** * The total value of funds successfully recovered from this channel * - * @generated from protobuf field: int64 recovered_balance = 6; + * @generated from protobuf field: int64 recovered_balance = 6 */ recoveredBalance: bigint; /** - * @generated from protobuf field: repeated lnrpc.PendingHTLC pending_htlcs = 8; + * @generated from protobuf field: repeated lnrpc.PendingHTLC pending_htlcs = 8 */ pendingHtlcs: PendingHTLC[]; /** - * @generated from protobuf field: lnrpc.PendingChannelsResponse.ForceClosedChannel.AnchorState anchor = 9; + * @generated from protobuf field: lnrpc.PendingChannelsResponse.ForceClosedChannel.AnchorState anchor = 9 */ anchor: PendingChannelsResponse_ForceClosedChannel_AnchorState; } @@ -3733,44 +3884,50 @@ export interface ChannelEventUpdate { channel: { oneofKind: "openChannel"; /** - * @generated from protobuf field: lnrpc.Channel open_channel = 1; + * @generated from protobuf field: lnrpc.Channel open_channel = 1 */ openChannel: Channel; } | { oneofKind: "closedChannel"; /** - * @generated from protobuf field: lnrpc.ChannelCloseSummary closed_channel = 2; + * @generated from protobuf field: lnrpc.ChannelCloseSummary closed_channel = 2 */ closedChannel: ChannelCloseSummary; } | { oneofKind: "activeChannel"; /** - * @generated from protobuf field: lnrpc.ChannelPoint active_channel = 3; + * @generated from protobuf field: lnrpc.ChannelPoint active_channel = 3 */ activeChannel: ChannelPoint; } | { oneofKind: "inactiveChannel"; /** - * @generated from protobuf field: lnrpc.ChannelPoint inactive_channel = 4; + * @generated from protobuf field: lnrpc.ChannelPoint inactive_channel = 4 */ inactiveChannel: ChannelPoint; } | { oneofKind: "pendingOpenChannel"; /** - * @generated from protobuf field: lnrpc.PendingUpdate pending_open_channel = 6; + * @generated from protobuf field: lnrpc.PendingUpdate pending_open_channel = 6 */ pendingOpenChannel: PendingUpdate; } | { oneofKind: "fullyResolvedChannel"; /** - * @generated from protobuf field: lnrpc.ChannelPoint fully_resolved_channel = 7; + * @generated from protobuf field: lnrpc.ChannelPoint fully_resolved_channel = 7 */ fullyResolvedChannel: ChannelPoint; + } | { + oneofKind: "channelFundingTimeout"; + /** + * @generated from protobuf field: lnrpc.ChannelPoint channel_funding_timeout = 8 + */ + channelFundingTimeout: ChannelPoint; } | { oneofKind: undefined; }; /** - * @generated from protobuf field: lnrpc.ChannelEventUpdate.UpdateType type = 5; + * @generated from protobuf field: lnrpc.ChannelEventUpdate.UpdateType type = 5 */ type: ChannelEventUpdate_UpdateType; } @@ -3801,7 +3958,11 @@ export enum ChannelEventUpdate_UpdateType { /** * @generated from protobuf enum value: FULLY_RESOLVED_CHANNEL = 5; */ - FULLY_RESOLVED_CHANNEL = 5 + FULLY_RESOLVED_CHANNEL = 5, + /** + * @generated from protobuf enum value: CHANNEL_FUNDING_TIMEOUT = 6; + */ + CHANNEL_FUNDING_TIMEOUT = 6 } /** * @generated from protobuf message lnrpc.WalletAccountBalance @@ -3810,13 +3971,13 @@ export interface WalletAccountBalance { /** * The confirmed balance of the account (with >= 1 confirmations). * - * @generated from protobuf field: int64 confirmed_balance = 1; + * @generated from protobuf field: int64 confirmed_balance = 1 */ confirmedBalance: bigint; /** * The unconfirmed balance of the account (with 0 confirmations). * - * @generated from protobuf field: int64 unconfirmed_balance = 2; + * @generated from protobuf field: int64 unconfirmed_balance = 2 */ unconfirmedBalance: bigint; } @@ -3828,7 +3989,7 @@ export interface WalletBalanceRequest { * The wallet account the balance is shown for. * If this is not specified, the balance of the "default" account is shown. * - * @generated from protobuf field: string account = 1; + * @generated from protobuf field: string account = 1 */ account: string; /** @@ -3836,7 +3997,7 @@ export interface WalletBalanceRequest { * funding transaction must satisfy. If this is not specified, the default * value of 1 is used. * - * @generated from protobuf field: int32 min_confs = 2; + * @generated from protobuf field: int32 min_confs = 2 */ minConfs: number; } @@ -3847,38 +4008,38 @@ export interface WalletBalanceResponse { /** * The balance of the wallet * - * @generated from protobuf field: int64 total_balance = 1; + * @generated from protobuf field: int64 total_balance = 1 */ totalBalance: bigint; /** * The confirmed balance of a wallet(with >= 1 confirmations) * - * @generated from protobuf field: int64 confirmed_balance = 2; + * @generated from protobuf field: int64 confirmed_balance = 2 */ confirmedBalance: bigint; /** * The unconfirmed balance of a wallet(with 0 confirmations) * - * @generated from protobuf field: int64 unconfirmed_balance = 3; + * @generated from protobuf field: int64 unconfirmed_balance = 3 */ unconfirmedBalance: bigint; /** * The total amount of wallet UTXOs held in outputs that are locked for * other usage. * - * @generated from protobuf field: int64 locked_balance = 5; + * @generated from protobuf field: int64 locked_balance = 5 */ lockedBalance: bigint; /** * The amount of reserve required. * - * @generated from protobuf field: int64 reserved_balance_anchor_chan = 6; + * @generated from protobuf field: int64 reserved_balance_anchor_chan = 6 */ reservedBalanceAnchorChan: bigint; /** * A mapping of each wallet account's name to its balance. * - * @generated from protobuf field: map account_balance = 4; + * @generated from protobuf field: map account_balance = 4 */ accountBalance: { [key: string]: WalletAccountBalance; @@ -3891,13 +4052,13 @@ export interface Amount { /** * Value denominated in satoshis. * - * @generated from protobuf field: uint64 sat = 1; + * @generated from protobuf field: uint64 sat = 1 */ sat: bigint; /** * Value denominated in milli-satoshis. * - * @generated from protobuf field: uint64 msat = 2; + * @generated from protobuf field: uint64 msat = 2 */ msat: bigint; } @@ -3914,52 +4075,60 @@ export interface ChannelBalanceResponse { * Deprecated. Sum of channels balances denominated in satoshis * * @deprecated - * @generated from protobuf field: int64 balance = 1 [deprecated = true]; + * @generated from protobuf field: int64 balance = 1 [deprecated = true] */ balance: bigint; /** * Deprecated. Sum of channels pending balances denominated in satoshis * * @deprecated - * @generated from protobuf field: int64 pending_open_balance = 2 [deprecated = true]; + * @generated from protobuf field: int64 pending_open_balance = 2 [deprecated = true] */ pendingOpenBalance: bigint; /** * Sum of channels local balances. * - * @generated from protobuf field: lnrpc.Amount local_balance = 3; + * @generated from protobuf field: lnrpc.Amount local_balance = 3 */ localBalance?: Amount; /** * Sum of channels remote balances. * - * @generated from protobuf field: lnrpc.Amount remote_balance = 4; + * @generated from protobuf field: lnrpc.Amount remote_balance = 4 */ remoteBalance?: Amount; /** * Sum of channels local unsettled balances. * - * @generated from protobuf field: lnrpc.Amount unsettled_local_balance = 5; + * @generated from protobuf field: lnrpc.Amount unsettled_local_balance = 5 */ unsettledLocalBalance?: Amount; /** * Sum of channels remote unsettled balances. * - * @generated from protobuf field: lnrpc.Amount unsettled_remote_balance = 6; + * @generated from protobuf field: lnrpc.Amount unsettled_remote_balance = 6 */ unsettledRemoteBalance?: Amount; /** * Sum of channels pending local balances. * - * @generated from protobuf field: lnrpc.Amount pending_open_local_balance = 7; + * @generated from protobuf field: lnrpc.Amount pending_open_local_balance = 7 */ pendingOpenLocalBalance?: Amount; /** * Sum of channels pending remote balances. * - * @generated from protobuf field: lnrpc.Amount pending_open_remote_balance = 8; + * @generated from protobuf field: lnrpc.Amount pending_open_remote_balance = 8 */ pendingOpenRemoteBalance?: Amount; + /** + * + * Custom channel data that might be populated if there are custom channels + * present. + * + * @generated from protobuf field: bytes custom_channel_data = 9 + */ + customChannelData: Uint8Array; } /** * @generated from protobuf message lnrpc.QueryRoutesRequest @@ -3968,7 +4137,7 @@ export interface QueryRoutesRequest { /** * The 33-byte hex-encoded public key for the payment destination * - * @generated from protobuf field: string pub_key = 1; + * @generated from protobuf field: string pub_key = 1 */ pubKey: string; /** @@ -3977,7 +4146,7 @@ export interface QueryRoutesRequest { * * The fields amt and amt_msat are mutually exclusive. * - * @generated from protobuf field: int64 amt = 2; + * @generated from protobuf field: int64 amt = 2 */ amt: bigint; /** @@ -3986,7 +4155,7 @@ export interface QueryRoutesRequest { * * The fields amt and amt_msat are mutually exclusive. * - * @generated from protobuf field: int64 amt_msat = 12; + * @generated from protobuf field: int64 amt_msat = 12 */ amtMsat: bigint; /** @@ -4000,7 +4169,7 @@ export interface QueryRoutesRequest { * Note: must not be set if making a payment to a blinded path (delta is * set by the aggregate parameters provided by blinded_payment_paths) * - * @generated from protobuf field: int32 final_cltv_delta = 4; + * @generated from protobuf field: int32 final_cltv_delta = 4 */ finalCltvDelta: number; /** @@ -4011,7 +4180,7 @@ export interface QueryRoutesRequest { * send the payment. If not specified, lnd will use a default value of 100% * fees for small amounts (<=1k sat) or 5% fees for larger amounts. * - * @generated from protobuf field: lnrpc.FeeLimit fee_limit = 5; + * @generated from protobuf field: lnrpc.FeeLimit fee_limit = 5 */ feeLimit?: FeeLimit; /** @@ -4019,7 +4188,7 @@ export interface QueryRoutesRequest { * A list of nodes to ignore during path finding. When using REST, these fields * must be encoded as base64. * - * @generated from protobuf field: repeated bytes ignored_nodes = 6; + * @generated from protobuf field: repeated bytes ignored_nodes = 6 */ ignoredNodes: Uint8Array[]; /** @@ -4027,7 +4196,7 @@ export interface QueryRoutesRequest { * Deprecated. A list of edges to ignore during path finding. * * @deprecated - * @generated from protobuf field: repeated lnrpc.EdgeLocator ignored_edges = 7 [deprecated = true]; + * @generated from protobuf field: repeated lnrpc.EdgeLocator ignored_edges = 7 [deprecated = true] */ ignoredEdges: EdgeLocator[]; /** @@ -4035,7 +4204,7 @@ export interface QueryRoutesRequest { * The source node where the request route should originated from. If empty, * self is assumed. * - * @generated from protobuf field: string source_pub_key = 8; + * @generated from protobuf field: string source_pub_key = 8 */ sourcePubKey: string; /** @@ -4043,14 +4212,14 @@ export interface QueryRoutesRequest { * If set to true, edge probabilities from mission control will be used to get * the optimal route. * - * @generated from protobuf field: bool use_mission_control = 9; + * @generated from protobuf field: bool use_mission_control = 9 */ useMissionControl: boolean; /** * * A list of directed node pairs that will be ignored during path finding. * - * @generated from protobuf field: repeated lnrpc.NodePair ignored_pairs = 10; + * @generated from protobuf field: repeated lnrpc.NodePair ignored_pairs = 10 */ ignoredPairs: NodePair[]; /** @@ -4059,7 +4228,7 @@ export interface QueryRoutesRequest { * ourselves, this should not exceed lnd's `--max-cltv-expiry` setting. If * zero, then the value of `--max-cltv-expiry` is used as the limit. * - * @generated from protobuf field: uint32 cltv_limit = 11; + * @generated from protobuf field: uint32 cltv_limit = 11 */ cltvLimit: number; /** @@ -4071,7 +4240,7 @@ export interface QueryRoutesRequest { * Record types are required to be in the custom range >= 65536. When using * REST, the values must be encoded as base64. * - * @generated from protobuf field: map dest_custom_records = 13; + * @generated from protobuf field: map dest_custom_records = 13 */ destCustomRecords: { [key: string]: Uint8Array; @@ -4081,21 +4250,21 @@ export interface QueryRoutesRequest { * The channel id of the channel that must be taken to the first hop. If zero, * any channel may be used. * - * @generated from protobuf field: uint64 outgoing_chan_id = 14 [jstype = JS_STRING]; + * @generated from protobuf field: uint64 outgoing_chan_id = 14 [jstype = JS_STRING] */ outgoingChanId: string; /** * * The pubkey of the last hop of the route. If empty, any hop may be used. * - * @generated from protobuf field: bytes last_hop_pubkey = 15; + * @generated from protobuf field: bytes last_hop_pubkey = 15 */ lastHopPubkey: Uint8Array; /** * * Optional route hints to reach the destination through private channels. * - * @generated from protobuf field: repeated lnrpc.RouteHint route_hints = 16; + * @generated from protobuf field: repeated lnrpc.RouteHint route_hints = 16 */ routeHints: RouteHint[]; /** @@ -4103,7 +4272,7 @@ export interface QueryRoutesRequest { * An optional blinded path(s) to reach the destination. Note that the * introduction node must be provided as the first hop in the route. * - * @generated from protobuf field: repeated lnrpc.BlindedPaymentPath blinded_payment_paths = 19; + * @generated from protobuf field: repeated lnrpc.BlindedPaymentPath blinded_payment_paths = 19 */ blindedPaymentPaths: BlindedPaymentPath[]; /** @@ -4117,7 +4286,7 @@ export interface QueryRoutesRequest { * Note: must not be set if making a payment to a blinded route (features * are provided in blinded_payment_paths). * - * @generated from protobuf field: repeated lnrpc.FeatureBit dest_features = 17; + * @generated from protobuf field: repeated lnrpc.FeatureBit dest_features = 17 */ destFeatures: FeatureBit[]; /** @@ -4125,7 +4294,7 @@ export interface QueryRoutesRequest { * The time preference for this payment. Set to -1 to optimize for fees * only, to 1 to optimize for reliability only or a value inbetween for a mix. * - * @generated from protobuf field: double time_pref = 18; + * @generated from protobuf field: double time_pref = 18 */ timePref: number; } @@ -4138,7 +4307,7 @@ export interface NodePair { * The sending node of the pair. When using REST, this field must be encoded as * base64. * - * @generated from protobuf field: bytes from = 1; + * @generated from protobuf field: bytes from = 1 */ from: Uint8Array; /** @@ -4146,7 +4315,7 @@ export interface NodePair { * The receiving node of the pair. When using REST, this field must be encoded * as base64. * - * @generated from protobuf field: bytes to = 2; + * @generated from protobuf field: bytes to = 2 */ to: Uint8Array; } @@ -4157,7 +4326,7 @@ export interface EdgeLocator { /** * The short channel id of this edge. * - * @generated from protobuf field: uint64 channel_id = 1 [jstype = JS_STRING]; + * @generated from protobuf field: uint64 channel_id = 1 [jstype = JS_STRING] */ channelId: string; /** @@ -4167,7 +4336,7 @@ export interface EdgeLocator { * pub key to the endpoint with the larger pub key. If direction_reverse is * is true, the edge goes the other way. * - * @generated from protobuf field: bool direction_reverse = 2; + * @generated from protobuf field: bool direction_reverse = 2 */ directionReverse: boolean; } @@ -4180,7 +4349,7 @@ export interface QueryRoutesResponse { * The route that results from the path finding operation. This is still a * repeated field to retain backwards compatibility. * - * @generated from protobuf field: repeated lnrpc.Route routes = 1; + * @generated from protobuf field: repeated lnrpc.Route routes = 1 */ routes: Route[]; /** @@ -4188,7 +4357,7 @@ export interface QueryRoutesResponse { * The success probability of the returned route based on the current mission * control state. [EXPERIMENTAL] * - * @generated from protobuf field: double success_prob = 2; + * @generated from protobuf field: double success_prob = 2 */ successProb: number; } @@ -4202,34 +4371,34 @@ export interface Hop { * height, the next 3 the index within the block, and the last 2 bytes are the * output index for the channel. * - * @generated from protobuf field: uint64 chan_id = 1 [jstype = JS_STRING]; + * @generated from protobuf field: uint64 chan_id = 1 [jstype = JS_STRING] */ chanId: string; /** * @deprecated - * @generated from protobuf field: int64 chan_capacity = 2 [deprecated = true]; + * @generated from protobuf field: int64 chan_capacity = 2 [deprecated = true] */ chanCapacity: bigint; /** * @deprecated - * @generated from protobuf field: int64 amt_to_forward = 3 [deprecated = true]; + * @generated from protobuf field: int64 amt_to_forward = 3 [deprecated = true] */ amtToForward: bigint; /** * @deprecated - * @generated from protobuf field: int64 fee = 4 [deprecated = true]; + * @generated from protobuf field: int64 fee = 4 [deprecated = true] */ fee: bigint; /** - * @generated from protobuf field: uint32 expiry = 5; + * @generated from protobuf field: uint32 expiry = 5 */ expiry: number; /** - * @generated from protobuf field: int64 amt_to_forward_msat = 6; + * @generated from protobuf field: int64 amt_to_forward_msat = 6 */ amtToForwardMsat: bigint; /** - * @generated from protobuf field: int64 fee_msat = 7; + * @generated from protobuf field: int64 fee_msat = 7 */ feeMsat: bigint; /** @@ -4237,7 +4406,7 @@ export interface Hop { * An optional public key of the hop. If the public key is given, the payment * can be executed without relying on a copy of the channel graph. * - * @generated from protobuf field: string pub_key = 8; + * @generated from protobuf field: string pub_key = 8 */ pubKey: string; /** @@ -4247,7 +4416,7 @@ export interface Hop { * this field MUST be set to true for them to be encoded properly. * * @deprecated - * @generated from protobuf field: bool tlv_payload = 9 [deprecated = true]; + * @generated from protobuf field: bool tlv_payload = 9 [deprecated = true] */ tlvPayload: boolean; /** @@ -4257,7 +4426,7 @@ export interface Hop { * hop payload of all non-zero payments in the HTLC set. If empty, a regular * single-shot payment is or was attempted. * - * @generated from protobuf field: lnrpc.MPPRecord mpp_record = 10; + * @generated from protobuf field: lnrpc.MPPRecord mpp_record = 10 */ mppRecord?: MPPRecord; /** @@ -4269,7 +4438,7 @@ export interface Hop { * child hashes and preimages according to BOLT XX. Must be used in conjunction * with mpp_record. * - * @generated from protobuf field: lnrpc.AMPRecord amp_record = 12; + * @generated from protobuf field: lnrpc.AMPRecord amp_record = 12 */ ampRecord?: AMPRecord; /** @@ -4278,7 +4447,7 @@ export interface Hop { * of the SendToRoute call as it allows callers to specify arbitrary K-V pairs * to drop off at each hop within the onion. * - * @generated from protobuf field: map custom_records = 11; + * @generated from protobuf field: map custom_records = 11 */ customRecords: { [key: string]: Uint8Array; @@ -4286,7 +4455,7 @@ export interface Hop { /** * The payment metadata to send along with the payment to the payee. * - * @generated from protobuf field: bytes metadata = 13; + * @generated from protobuf field: bytes metadata = 13 */ metadata: Uint8Array; /** @@ -4295,7 +4464,7 @@ export interface Hop { * nodes in blinded paths. This field is mandatory for hops that represents * the introduction point in a blinded path. * - * @generated from protobuf field: bytes blinding_point = 14; + * @generated from protobuf field: bytes blinding_point = 14 */ blindingPoint: Uint8Array; /** @@ -4307,7 +4476,7 @@ export interface Hop { * mandatory for all hops in a blinded path, including the introduction * node. * - * @generated from protobuf field: bytes encrypted_data = 15; + * @generated from protobuf field: bytes encrypted_data = 15 */ encryptedData: Uint8Array; /** @@ -4318,7 +4487,7 @@ export interface Hop { * value is analogous to the MPPRecord that is used for regular (non-blinded) * MPP payments. * - * @generated from protobuf field: uint64 total_amt_msat = 16; + * @generated from protobuf field: uint64 total_amt_msat = 16 */ totalAmtMsat: bigint; } @@ -4334,7 +4503,7 @@ export interface MPPRecord { * The same payment_addr must be used on all subpayments. This is also called * payment secret in specifications (e.g. BOLT 11). * - * @generated from protobuf field: bytes payment_addr = 11; + * @generated from protobuf field: bytes payment_addr = 11 */ paymentAddr: Uint8Array; /** @@ -4344,7 +4513,7 @@ export interface MPPRecord { * and payment_hash sum exactly to total_amt_msat. The same * total_amt_msat must be used on all subpayments. * - * @generated from protobuf field: int64 total_amt_msat = 10; + * @generated from protobuf field: int64 total_amt_msat = 10 */ totalAmtMsat: bigint; } @@ -4353,15 +4522,15 @@ export interface MPPRecord { */ export interface AMPRecord { /** - * @generated from protobuf field: bytes root_share = 1; + * @generated from protobuf field: bytes root_share = 1 */ rootShare: Uint8Array; /** - * @generated from protobuf field: bytes set_id = 2; + * @generated from protobuf field: bytes set_id = 2 */ setId: Uint8Array; /** - * @generated from protobuf field: uint32 child_index = 3; + * @generated from protobuf field: uint32 child_index = 3 */ childIndex: number; } @@ -4383,7 +4552,7 @@ export interface Route { * will decrement the time-lock as advertised, leaving enough time for all * hops to wait for or present the payment preimage to complete the payment. * - * @generated from protobuf field: uint32 total_time_lock = 1; + * @generated from protobuf field: uint32 total_time_lock = 1 */ totalTimeLock: number; /** @@ -4393,7 +4562,7 @@ export interface Route { * to ourselves. * * @deprecated - * @generated from protobuf field: int64 total_fees = 2 [deprecated = true]; + * @generated from protobuf field: int64 total_fees = 2 [deprecated = true] */ totalFees: bigint; /** @@ -4405,30 +4574,48 @@ export interface Route { * insufficient amount of fees. * * @deprecated - * @generated from protobuf field: int64 total_amt = 3 [deprecated = true]; + * @generated from protobuf field: int64 total_amt = 3 [deprecated = true] */ totalAmt: bigint; /** * * Contains details concerning the specific forwarding details at each hop. * - * @generated from protobuf field: repeated lnrpc.Hop hops = 4; + * @generated from protobuf field: repeated lnrpc.Hop hops = 4 */ hops: Hop[]; /** * * The total fees in millisatoshis. * - * @generated from protobuf field: int64 total_fees_msat = 5; + * @generated from protobuf field: int64 total_fees_msat = 5 */ totalFeesMsat: bigint; /** * * The total amount in millisatoshis. * - * @generated from protobuf field: int64 total_amt_msat = 6; + * @generated from protobuf field: int64 total_amt_msat = 6 */ totalAmtMsat: bigint; + /** + * + * The actual on-chain amount that was sent out to the first hop. This value is + * only different from the total_amt_msat field if this is a custom channel + * payment and the value transported in the HTLC is different from the BTC + * amount in the HTLC. If this value is zero, then this is an old payment that + * didn't have this value yet and can be ignored. + * + * @generated from protobuf field: int64 first_hop_amount_msat = 7 + */ + firstHopAmountMsat: bigint; + /** + * + * Custom channel data that might be populated in custom channels. + * + * @generated from protobuf field: bytes custom_channel_data = 8 + */ + customChannelData: Uint8Array; } /** * @generated from protobuf message lnrpc.NodeInfoRequest @@ -4437,13 +4624,13 @@ export interface NodeInfoRequest { /** * The 33-byte hex-encoded compressed public of the target node * - * @generated from protobuf field: string pub_key = 1; + * @generated from protobuf field: string pub_key = 1 */ pubKey: string; /** * If true, will include all known channels associated with the node. * - * @generated from protobuf field: bool include_channels = 2; + * @generated from protobuf field: bool include_channels = 2 */ includeChannels: boolean; } @@ -4458,25 +4645,25 @@ export interface NodeInfo { * the graph is directed, a node will also have an incoming edge attached to * it for each outgoing edge. * - * @generated from protobuf field: lnrpc.LightningNode node = 1; + * @generated from protobuf field: lnrpc.LightningNode node = 1 */ node?: LightningNode; /** * The total number of channels for the node. * - * @generated from protobuf field: uint32 num_channels = 2; + * @generated from protobuf field: uint32 num_channels = 2 */ numChannels: number; /** * The sum of all channels capacity for the node, denominated in satoshis. * - * @generated from protobuf field: int64 total_capacity = 3; + * @generated from protobuf field: int64 total_capacity = 3 */ totalCapacity: bigint; /** * A list of all public channels for the node. * - * @generated from protobuf field: repeated lnrpc.ChannelEdge channels = 4; + * @generated from protobuf field: repeated lnrpc.ChannelEdge channels = 4 */ channels: ChannelEdge[]; } @@ -4491,27 +4678,27 @@ export interface NodeInfo { */ export interface LightningNode { /** - * @generated from protobuf field: uint32 last_update = 1; + * @generated from protobuf field: uint32 last_update = 1 */ lastUpdate: number; /** - * @generated from protobuf field: string pub_key = 2; + * @generated from protobuf field: string pub_key = 2 */ pubKey: string; /** - * @generated from protobuf field: string alias = 3; + * @generated from protobuf field: string alias = 3 */ alias: string; /** - * @generated from protobuf field: repeated lnrpc.NodeAddress addresses = 4; + * @generated from protobuf field: repeated lnrpc.NodeAddress addresses = 4 */ addresses: NodeAddress[]; /** - * @generated from protobuf field: string color = 5; + * @generated from protobuf field: string color = 5 */ color: string; /** - * @generated from protobuf field: map features = 6; + * @generated from protobuf field: map features = 6 */ features: { [key: number]: Feature; @@ -4519,7 +4706,7 @@ export interface LightningNode { /** * Custom node announcement tlv records. * - * @generated from protobuf field: map custom_records = 7; + * @generated from protobuf field: map custom_records = 7 */ customRecords: { [key: string]: Uint8Array; @@ -4530,11 +4717,11 @@ export interface LightningNode { */ export interface NodeAddress { /** - * @generated from protobuf field: string network = 1; + * @generated from protobuf field: string network = 1 */ network: string; /** - * @generated from protobuf field: string addr = 2; + * @generated from protobuf field: string addr = 2 */ addr: string; } @@ -4543,47 +4730,47 @@ export interface NodeAddress { */ export interface RoutingPolicy { /** - * @generated from protobuf field: uint32 time_lock_delta = 1; + * @generated from protobuf field: uint32 time_lock_delta = 1 */ timeLockDelta: number; /** - * @generated from protobuf field: int64 min_htlc = 2; + * @generated from protobuf field: int64 min_htlc = 2 */ minHtlc: bigint; /** - * @generated from protobuf field: int64 fee_base_msat = 3; + * @generated from protobuf field: int64 fee_base_msat = 3 */ feeBaseMsat: bigint; /** - * @generated from protobuf field: int64 fee_rate_milli_msat = 4; + * @generated from protobuf field: int64 fee_rate_milli_msat = 4 */ feeRateMilliMsat: bigint; /** - * @generated from protobuf field: bool disabled = 5; + * @generated from protobuf field: bool disabled = 5 */ disabled: boolean; /** - * @generated from protobuf field: uint64 max_htlc_msat = 6; + * @generated from protobuf field: uint64 max_htlc_msat = 6 */ maxHtlcMsat: bigint; /** - * @generated from protobuf field: uint32 last_update = 7; + * @generated from protobuf field: uint32 last_update = 7 */ lastUpdate: number; /** * Custom channel update tlv records. * - * @generated from protobuf field: map custom_records = 8; + * @generated from protobuf field: map custom_records = 8 */ customRecords: { [key: string]: Uint8Array; }; /** - * @generated from protobuf field: int32 inbound_fee_base_msat = 9; + * @generated from protobuf field: int32 inbound_fee_base_msat = 9 */ inboundFeeBaseMsat: number; /** - * @generated from protobuf field: int32 inbound_fee_rate_milli_msat = 10; + * @generated from protobuf field: int32 inbound_fee_rate_milli_msat = 10 */ inboundFeeRateMilliMsat: number; } @@ -4604,42 +4791,42 @@ export interface ChannelEdge { * height, the next 3 the index within the block, and the last 2 bytes are the * output index for the channel. * - * @generated from protobuf field: uint64 channel_id = 1 [jstype = JS_STRING]; + * @generated from protobuf field: uint64 channel_id = 1 [jstype = JS_STRING] */ channelId: string; /** - * @generated from protobuf field: string chan_point = 2; + * @generated from protobuf field: string chan_point = 2 */ chanPoint: string; /** * @deprecated - * @generated from protobuf field: uint32 last_update = 3 [deprecated = true]; + * @generated from protobuf field: uint32 last_update = 3 [deprecated = true] */ lastUpdate: number; /** - * @generated from protobuf field: string node1_pub = 4; + * @generated from protobuf field: string node1_pub = 4 */ node1Pub: string; /** - * @generated from protobuf field: string node2_pub = 5; + * @generated from protobuf field: string node2_pub = 5 */ node2Pub: string; /** - * @generated from protobuf field: int64 capacity = 6; + * @generated from protobuf field: int64 capacity = 6 */ capacity: bigint; /** - * @generated from protobuf field: lnrpc.RoutingPolicy node1_policy = 7; + * @generated from protobuf field: lnrpc.RoutingPolicy node1_policy = 7 */ node1Policy?: RoutingPolicy; /** - * @generated from protobuf field: lnrpc.RoutingPolicy node2_policy = 8; + * @generated from protobuf field: lnrpc.RoutingPolicy node2_policy = 8 */ node2Policy?: RoutingPolicy; /** * Custom channel announcement tlv records. * - * @generated from protobuf field: map custom_records = 9; + * @generated from protobuf field: map custom_records = 9 */ customRecords: { [key: string]: Uint8Array; @@ -4655,7 +4842,7 @@ export interface ChannelGraphRequest { * unannounced channels are included. Unannounced channels are both private * channels, and public channels that are not yet announced to the network. * - * @generated from protobuf field: bool include_unannounced = 1; + * @generated from protobuf field: bool include_unannounced = 1 */ includeUnannounced: boolean; } @@ -4668,13 +4855,13 @@ export interface ChannelGraph { /** * The list of `LightningNode`s in this channel graph * - * @generated from protobuf field: repeated lnrpc.LightningNode nodes = 1; + * @generated from protobuf field: repeated lnrpc.LightningNode nodes = 1 */ nodes: LightningNode[]; /** * The list of `ChannelEdge`s in this channel graph * - * @generated from protobuf field: repeated lnrpc.ChannelEdge edges = 2; + * @generated from protobuf field: repeated lnrpc.ChannelEdge edges = 2 */ edges: ChannelEdge[]; } @@ -4685,7 +4872,7 @@ export interface NodeMetricsRequest { /** * The requested node metrics. * - * @generated from protobuf field: repeated lnrpc.NodeMetricType types = 1; + * @generated from protobuf field: repeated lnrpc.NodeMetricType types = 1 */ types: NodeMetricType[]; } @@ -4701,7 +4888,7 @@ export interface NodeMetricsResponse { * Map of node pubkey to betweenness centrality of the node. Normalized * values are in the [0,1] closed interval. * - * @generated from protobuf field: map betweenness_centrality = 1; + * @generated from protobuf field: map betweenness_centrality = 1 */ betweennessCentrality: { [key: string]: FloatMetric; @@ -4714,13 +4901,13 @@ export interface FloatMetric { /** * Arbitrary float value. * - * @generated from protobuf field: double value = 1; + * @generated from protobuf field: double value = 1 */ value: number; /** * The value normalized to [0,1] or [-1,1]. * - * @generated from protobuf field: double normalized_value = 2; + * @generated from protobuf field: double normalized_value = 2 */ normalizedValue: number; } @@ -4734,14 +4921,14 @@ export interface ChanInfoRequest { * height, the next 3 the index within the block, and the last 2 bytes are the * output index for the channel. * - * @generated from protobuf field: uint64 chan_id = 1 [jstype = JS_STRING]; + * @generated from protobuf field: uint64 chan_id = 1 [jstype = JS_STRING] */ chanId: string; /** * The channel point of the channel in format funding_txid:output_index. If * chan_id is specified, this field is ignored. * - * @generated from protobuf field: string chan_point = 2; + * @generated from protobuf field: string chan_point = 2 */ chanPoint: string; } @@ -4755,49 +4942,49 @@ export interface NetworkInfoRequest { */ export interface NetworkInfo { /** - * @generated from protobuf field: uint32 graph_diameter = 1; + * @generated from protobuf field: uint32 graph_diameter = 1 */ graphDiameter: number; /** - * @generated from protobuf field: double avg_out_degree = 2; + * @generated from protobuf field: double avg_out_degree = 2 */ avgOutDegree: number; /** - * @generated from protobuf field: uint32 max_out_degree = 3; + * @generated from protobuf field: uint32 max_out_degree = 3 */ maxOutDegree: number; /** - * @generated from protobuf field: uint32 num_nodes = 4; + * @generated from protobuf field: uint32 num_nodes = 4 */ numNodes: number; /** - * @generated from protobuf field: uint32 num_channels = 5; + * @generated from protobuf field: uint32 num_channels = 5 */ numChannels: number; /** - * @generated from protobuf field: int64 total_network_capacity = 6; + * @generated from protobuf field: int64 total_network_capacity = 6 */ totalNetworkCapacity: bigint; /** - * @generated from protobuf field: double avg_channel_size = 7; + * @generated from protobuf field: double avg_channel_size = 7 */ avgChannelSize: number; /** - * @generated from protobuf field: int64 min_channel_size = 8; + * @generated from protobuf field: int64 min_channel_size = 8 */ minChannelSize: bigint; /** - * @generated from protobuf field: int64 max_channel_size = 9; + * @generated from protobuf field: int64 max_channel_size = 9 */ maxChannelSize: bigint; /** - * @generated from protobuf field: int64 median_channel_size_sat = 10; + * @generated from protobuf field: int64 median_channel_size_sat = 10 */ medianChannelSizeSat: bigint; /** * The number of edges marked as zombies. * - * @generated from protobuf field: uint64 num_zombie_chans = 11; + * @generated from protobuf field: uint64 num_zombie_chans = 11 */ numZombieChans: bigint; } @@ -4810,6 +4997,12 @@ export interface StopRequest { * @generated from protobuf message lnrpc.StopResponse */ export interface StopResponse { + /** + * The status of the stop operation. + * + * @generated from protobuf field: string status = 1 + */ + status: string; } /** * @generated from protobuf message lnrpc.GraphTopologySubscription @@ -4821,15 +5014,15 @@ export interface GraphTopologySubscription { */ export interface GraphTopologyUpdate { /** - * @generated from protobuf field: repeated lnrpc.NodeUpdate node_updates = 1; + * @generated from protobuf field: repeated lnrpc.NodeUpdate node_updates = 1 */ nodeUpdates: NodeUpdate[]; /** - * @generated from protobuf field: repeated lnrpc.ChannelEdgeUpdate channel_updates = 2; + * @generated from protobuf field: repeated lnrpc.ChannelEdgeUpdate channel_updates = 2 */ channelUpdates: ChannelEdgeUpdate[]; /** - * @generated from protobuf field: repeated lnrpc.ClosedChannelUpdate closed_chans = 3; + * @generated from protobuf field: repeated lnrpc.ClosedChannelUpdate closed_chans = 3 */ closedChans: ClosedChannelUpdate[]; } @@ -4842,11 +5035,11 @@ export interface NodeUpdate { * Deprecated, use node_addresses. * * @deprecated - * @generated from protobuf field: repeated string addresses = 1 [deprecated = true]; + * @generated from protobuf field: repeated string addresses = 1 [deprecated = true] */ addresses: string[]; /** - * @generated from protobuf field: string identity_key = 2; + * @generated from protobuf field: string identity_key = 2 */ identityKey: string; /** @@ -4854,19 +5047,19 @@ export interface NodeUpdate { * Deprecated, use features. * * @deprecated - * @generated from protobuf field: bytes global_features = 3 [deprecated = true]; + * @generated from protobuf field: bytes global_features = 3 [deprecated = true] */ globalFeatures: Uint8Array; /** - * @generated from protobuf field: string alias = 4; + * @generated from protobuf field: string alias = 4 */ alias: string; /** - * @generated from protobuf field: string color = 5; + * @generated from protobuf field: string color = 5 */ color: string; /** - * @generated from protobuf field: repeated lnrpc.NodeAddress node_addresses = 7; + * @generated from protobuf field: repeated lnrpc.NodeAddress node_addresses = 7 */ nodeAddresses: NodeAddress[]; /** @@ -4874,7 +5067,7 @@ export interface NodeUpdate { * Features that the node has advertised in the init message, node * announcements and invoices. * - * @generated from protobuf field: map features = 6; + * @generated from protobuf field: map features = 6 */ features: { [key: number]: Feature; @@ -4890,27 +5083,27 @@ export interface ChannelEdgeUpdate { * height, the next 3 the index within the block, and the last 2 bytes are the * output index for the channel. * - * @generated from protobuf field: uint64 chan_id = 1 [jstype = JS_STRING]; + * @generated from protobuf field: uint64 chan_id = 1 [jstype = JS_STRING] */ chanId: string; /** - * @generated from protobuf field: lnrpc.ChannelPoint chan_point = 2; + * @generated from protobuf field: lnrpc.ChannelPoint chan_point = 2 */ chanPoint?: ChannelPoint; /** - * @generated from protobuf field: int64 capacity = 3; + * @generated from protobuf field: int64 capacity = 3 */ capacity: bigint; /** - * @generated from protobuf field: lnrpc.RoutingPolicy routing_policy = 4; + * @generated from protobuf field: lnrpc.RoutingPolicy routing_policy = 4 */ routingPolicy?: RoutingPolicy; /** - * @generated from protobuf field: string advertising_node = 5; + * @generated from protobuf field: string advertising_node = 5 */ advertisingNode: string; /** - * @generated from protobuf field: string connecting_node = 6; + * @generated from protobuf field: string connecting_node = 6 */ connectingNode: string; } @@ -4924,19 +5117,19 @@ export interface ClosedChannelUpdate { * height, the next 3 the index within the block, and the last 2 bytes are the * output index for the channel. * - * @generated from protobuf field: uint64 chan_id = 1 [jstype = JS_STRING]; + * @generated from protobuf field: uint64 chan_id = 1 [jstype = JS_STRING] */ chanId: string; /** - * @generated from protobuf field: int64 capacity = 2; + * @generated from protobuf field: int64 capacity = 2 */ capacity: bigint; /** - * @generated from protobuf field: uint32 closed_height = 3; + * @generated from protobuf field: uint32 closed_height = 3 */ closedHeight: number; /** - * @generated from protobuf field: lnrpc.ChannelPoint chan_point = 4; + * @generated from protobuf field: lnrpc.ChannelPoint chan_point = 4 */ chanPoint?: ChannelPoint; } @@ -4947,19 +5140,19 @@ export interface HopHint { /** * The public key of the node at the start of the channel. * - * @generated from protobuf field: string node_id = 1; + * @generated from protobuf field: string node_id = 1 */ nodeId: string; /** * The unique identifier of the channel. * - * @generated from protobuf field: uint64 chan_id = 2 [jstype = JS_STRING]; + * @generated from protobuf field: uint64 chan_id = 2 [jstype = JS_STRING] */ chanId: string; /** * The base fee of the channel denominated in millisatoshis. * - * @generated from protobuf field: uint32 fee_base_msat = 3; + * @generated from protobuf field: uint32 fee_base_msat = 3 */ feeBaseMsat: number; /** @@ -4967,13 +5160,13 @@ export interface HopHint { * The fee rate of the channel for sending one satoshi across it denominated in * millionths of a satoshi. * - * @generated from protobuf field: uint32 fee_proportional_millionths = 4; + * @generated from protobuf field: uint32 fee_proportional_millionths = 4 */ feeProportionalMillionths: number; /** * The time-lock delta of the channel. * - * @generated from protobuf field: uint32 cltv_expiry_delta = 5; + * @generated from protobuf field: uint32 cltv_expiry_delta = 5 */ cltvExpiryDelta: number; } @@ -4982,7 +5175,7 @@ export interface HopHint { */ export interface SetID { /** - * @generated from protobuf field: bytes set_id = 1; + * @generated from protobuf field: bytes set_id = 1 */ setId: Uint8Array; } @@ -4995,7 +5188,7 @@ export interface RouteHint { * A list of hop hints that when chained together can assist in reaching a * specific destination. * - * @generated from protobuf field: repeated lnrpc.HopHint hop_hints = 1; + * @generated from protobuf field: repeated lnrpc.HopHint hop_hints = 1 */ hopHints: HopHint[]; } @@ -5006,13 +5199,13 @@ export interface BlindedPaymentPath { /** * The blinded path to send the payment to. * - * @generated from protobuf field: lnrpc.BlindedPath blinded_path = 1; + * @generated from protobuf field: lnrpc.BlindedPath blinded_path = 1 */ blindedPath?: BlindedPath; /** * The base fee for the blinded path provided, expressed in msat. * - * @generated from protobuf field: uint64 base_fee_msat = 2; + * @generated from protobuf field: uint64 base_fee_msat = 2 */ baseFeeMsat: bigint; /** @@ -5020,7 +5213,7 @@ export interface BlindedPaymentPath { * The proportional fee for the blinded path provided, expressed in parts * per million. * - * @generated from protobuf field: uint32 proportional_fee_rate = 3; + * @generated from protobuf field: uint32 proportional_fee_rate = 3 */ proportionalFeeRate: number; /** @@ -5028,7 +5221,7 @@ export interface BlindedPaymentPath { * The total CLTV delta for the blinded path provided, including the * final CLTV delta for the receiving node. * - * @generated from protobuf field: uint32 total_cltv_delta = 4; + * @generated from protobuf field: uint32 total_cltv_delta = 4 */ totalCltvDelta: number; /** @@ -5036,7 +5229,7 @@ export interface BlindedPaymentPath { * The minimum hltc size that may be sent over the blinded path, expressed * in msat. * - * @generated from protobuf field: uint64 htlc_min_msat = 5; + * @generated from protobuf field: uint64 htlc_min_msat = 5 */ htlcMinMsat: bigint; /** @@ -5044,13 +5237,13 @@ export interface BlindedPaymentPath { * The maximum htlc size that may be sent over the blinded path, expressed * in msat. * - * @generated from protobuf field: uint64 htlc_max_msat = 6; + * @generated from protobuf field: uint64 htlc_max_msat = 6 */ htlcMaxMsat: bigint; /** * The feature bits for the route. * - * @generated from protobuf field: repeated lnrpc.FeatureBit features = 7; + * @generated from protobuf field: repeated lnrpc.FeatureBit features = 7 */ features: FeatureBit[]; } @@ -5061,13 +5254,13 @@ export interface BlindedPath { /** * The unblinded pubkey of the introduction node for the route. * - * @generated from protobuf field: bytes introduction_node = 1; + * @generated from protobuf field: bytes introduction_node = 1 */ introductionNode: Uint8Array; /** * The ephemeral pubkey used by nodes in the blinded route. * - * @generated from protobuf field: bytes blinding_point = 2; + * @generated from protobuf field: bytes blinding_point = 2 */ blindingPoint: Uint8Array; /** @@ -5076,7 +5269,7 @@ export interface BlindedPath { * route. Note that the first hop is expected to be the introduction node, * so the route is always expected to have at least one hop. * - * @generated from protobuf field: repeated lnrpc.BlindedHop blinded_hops = 3; + * @generated from protobuf field: repeated lnrpc.BlindedHop blinded_hops = 3 */ blindedHops: BlindedHop[]; } @@ -5087,13 +5280,13 @@ export interface BlindedHop { /** * The blinded public key of the node. * - * @generated from protobuf field: bytes blinded_node = 1; + * @generated from protobuf field: bytes blinded_node = 1 */ blindedNode: Uint8Array; /** * An encrypted blob of data provided to the blinded node. * - * @generated from protobuf field: bytes encrypted_data = 2; + * @generated from protobuf field: bytes encrypted_data = 2 */ encryptedData: Uint8Array; } @@ -5104,25 +5297,25 @@ export interface AMPInvoiceState { /** * The state the HTLCs associated with this setID are in. * - * @generated from protobuf field: lnrpc.InvoiceHTLCState state = 1; + * @generated from protobuf field: lnrpc.InvoiceHTLCState state = 1 */ state: InvoiceHTLCState; /** * The settle index of this HTLC set, if the invoice state is settled. * - * @generated from protobuf field: uint64 settle_index = 2; + * @generated from protobuf field: uint64 settle_index = 2 */ settleIndex: bigint; /** * The time this HTLC set was settled expressed in unix epoch. * - * @generated from protobuf field: int64 settle_time = 3; + * @generated from protobuf field: int64 settle_time = 3 */ settleTime: bigint; /** * The total amount paid for the sub-invoice expressed in milli satoshis. * - * @generated from protobuf field: int64 amt_paid_msat = 5; + * @generated from protobuf field: int64 amt_paid_msat = 5 */ amtPaidMsat: bigint; } @@ -5137,7 +5330,7 @@ export interface Invoice { * field of the encoded payment request if the description_hash field is not * being used. * - * @generated from protobuf field: string memo = 1; + * @generated from protobuf field: string memo = 1 */ memo: string; /** @@ -5146,7 +5339,7 @@ export interface Invoice { * HTLC payable to this preimage. When using REST, this field must be encoded * as base64. * - * @generated from protobuf field: bytes r_preimage = 3; + * @generated from protobuf field: bytes r_preimage = 3 */ rPreimage: Uint8Array; /** @@ -5155,7 +5348,7 @@ export interface Invoice { * base64. * Note: Output only, don't specify for creating an invoice. * - * @generated from protobuf field: bytes r_hash = 4; + * @generated from protobuf field: bytes r_hash = 4 */ rHash: Uint8Array; /** @@ -5164,7 +5357,7 @@ export interface Invoice { * * The fields value and value_msat are mutually exclusive. * - * @generated from protobuf field: int64 value = 5; + * @generated from protobuf field: int64 value = 5 */ value: bigint; /** @@ -5173,7 +5366,7 @@ export interface Invoice { * * The fields value and value_msat are mutually exclusive. * - * @generated from protobuf field: int64 value_msat = 23; + * @generated from protobuf field: int64 value_msat = 23 */ valueMsat: bigint; /** @@ -5183,7 +5376,7 @@ export interface Invoice { * The field is deprecated. Use the state field instead (compare to SETTLED). * * @deprecated - * @generated from protobuf field: bool settled = 6 [deprecated = true]; + * @generated from protobuf field: bool settled = 6 [deprecated = true] */ settled: boolean; /** @@ -5192,7 +5385,7 @@ export interface Invoice { * Measured in seconds since the unix epoch. * Note: Output only, don't specify for creating an invoice. * - * @generated from protobuf field: int64 creation_date = 7; + * @generated from protobuf field: int64 creation_date = 7 */ creationDate: bigint; /** @@ -5201,7 +5394,7 @@ export interface Invoice { * Measured in seconds since the unix epoch. * Note: Output only, don't specify for creating an invoice. * - * @generated from protobuf field: int64 settle_date = 8; + * @generated from protobuf field: int64 settle_date = 8 */ settleDate: bigint; /** @@ -5211,7 +5404,7 @@ export interface Invoice { * payment to the recipient. * Note: Output only, don't specify for creating an invoice. * - * @generated from protobuf field: string payment_request = 9; + * @generated from protobuf field: string payment_request = 9 */ paymentRequest: string; /** @@ -5221,25 +5414,25 @@ export interface Invoice { * of an encoded payment request. When using REST, this field must be encoded * as base64. * - * @generated from protobuf field: bytes description_hash = 10; + * @generated from protobuf field: bytes description_hash = 10 */ descriptionHash: Uint8Array; /** * Payment request expiry time in seconds. Default is 86400 (24 hours). * - * @generated from protobuf field: int64 expiry = 11; + * @generated from protobuf field: int64 expiry = 11 */ expiry: bigint; /** * Fallback on-chain address. * - * @generated from protobuf field: string fallback_addr = 12; + * @generated from protobuf field: string fallback_addr = 12 */ fallbackAddr: string; /** * Delta to use for the time-lock of the CLTV extended to the final hop. * - * @generated from protobuf field: uint64 cltv_expiry = 13; + * @generated from protobuf field: uint64 cltv_expiry = 13 */ cltvExpiry: bigint; /** @@ -5247,7 +5440,7 @@ export interface Invoice { * Route hints that can each be individually used to assist in reaching the * invoice's destination. * - * @generated from protobuf field: repeated lnrpc.RouteHint route_hints = 14; + * @generated from protobuf field: repeated lnrpc.RouteHint route_hints = 14 */ routeHints: RouteHint[]; /** @@ -5255,7 +5448,7 @@ export interface Invoice { * Note: When enabled, if value and value_msat are zero, a large number of * hints with these channels can be included, which might not be desirable. * - * @generated from protobuf field: bool private = 15; + * @generated from protobuf field: bool private = 15 */ private: boolean; /** @@ -5266,7 +5459,7 @@ export interface Invoice { * invoices with an add_index greater than this one. * Note: Output only, don't specify for creating an invoice. * - * @generated from protobuf field: uint64 add_index = 16; + * @generated from protobuf field: uint64 add_index = 16 */ addIndex: bigint; /** @@ -5277,14 +5470,14 @@ export interface Invoice { * settled invoices with an settle_index greater than this one. * Note: Output only, don't specify for creating an invoice. * - * @generated from protobuf field: uint64 settle_index = 17; + * @generated from protobuf field: uint64 settle_index = 17 */ settleIndex: bigint; /** * Deprecated, use amt_paid_sat or amt_paid_msat. * * @deprecated - * @generated from protobuf field: int64 amt_paid = 18 [deprecated = true]; + * @generated from protobuf field: int64 amt_paid = 18 [deprecated = true] */ amtPaid: bigint; /** @@ -5297,7 +5490,7 @@ export interface Invoice { * here as well. * Note: Output only, don't specify for creating an invoice. * - * @generated from protobuf field: int64 amt_paid_sat = 19; + * @generated from protobuf field: int64 amt_paid_sat = 19 */ amtPaidSat: bigint; /** @@ -5310,7 +5503,7 @@ export interface Invoice { * record that here as well. * Note: Output only, don't specify for creating an invoice. * - * @generated from protobuf field: int64 amt_paid_msat = 20; + * @generated from protobuf field: int64 amt_paid_msat = 20 */ amtPaidMsat: bigint; /** @@ -5318,7 +5511,7 @@ export interface Invoice { * The state the invoice is in. * Note: Output only, don't specify for creating an invoice. * - * @generated from protobuf field: lnrpc.Invoice.InvoiceState state = 21; + * @generated from protobuf field: lnrpc.Invoice.InvoiceState state = 21 */ state: Invoice_InvoiceState; /** @@ -5326,7 +5519,7 @@ export interface Invoice { * List of HTLCs paying to this invoice [EXPERIMENTAL]. * Note: Output only, don't specify for creating an invoice. * - * @generated from protobuf field: repeated lnrpc.InvoiceHTLC htlcs = 22; + * @generated from protobuf field: repeated lnrpc.InvoiceHTLC htlcs = 22 */ htlcs: InvoiceHTLC[]; /** @@ -5334,7 +5527,7 @@ export interface Invoice { * List of features advertised on the invoice. * Note: Output only, don't specify for creating an invoice. * - * @generated from protobuf field: map features = 24; + * @generated from protobuf field: map features = 24 */ features: { [key: number]: Feature; @@ -5345,7 +5538,7 @@ export interface Invoice { * [EXPERIMENTAL]. * Note: Output only, don't specify for creating an invoice. * - * @generated from protobuf field: bool is_keysend = 25; + * @generated from protobuf field: bool is_keysend = 25 */ isKeysend: boolean; /** @@ -5356,14 +5549,14 @@ export interface Invoice { * end-to-end security. * Note: Output only, don't specify for creating an invoice. * - * @generated from protobuf field: bytes payment_addr = 26; + * @generated from protobuf field: bytes payment_addr = 26 */ paymentAddr: Uint8Array; /** * * Signals whether or not this is an AMP invoice. * - * @generated from protobuf field: bool is_amp = 27; + * @generated from protobuf field: bool is_amp = 27 */ isAmp: boolean; /** @@ -5376,7 +5569,7 @@ export interface Invoice { * given sub-invoice. * Note: Output only, don't specify for creating an invoice. * - * @generated from protobuf field: map amp_invoice_state = 28; + * @generated from protobuf field: map amp_invoice_state = 28 */ ampInvoiceState: { [key: string]: AMPInvoiceState; @@ -5386,7 +5579,7 @@ export interface Invoice { * Signals that the invoice should include blinded paths to hide the true * identity of the recipient. * - * @generated from protobuf field: bool is_blinded = 29; + * @generated from protobuf field: bool is_blinded = 29 */ isBlinded: boolean; /** @@ -5395,7 +5588,7 @@ export interface Invoice { * can be used to override the defaults config values provided in by the * global config. This field is only used if is_blinded is true. * - * @generated from protobuf field: lnrpc.BlindedPathConfig blinded_path_config = 30; + * @generated from protobuf field: lnrpc.BlindedPathConfig blinded_path_config = 30 */ blindedPathConfig?: BlindedPathConfig; } @@ -5431,7 +5624,7 @@ export interface BlindedPathConfig { * minimum our node along with an introduction node hop. If it is zero then * the shortest path will use our node as an introduction node. * - * @generated from protobuf field: optional uint32 min_num_real_hops = 1; + * @generated from protobuf field: optional uint32 min_num_real_hops = 1 */ minNumRealHops?: number; /** @@ -5441,14 +5634,14 @@ export interface BlindedPathConfig { * introduction node or dummy node hop. If paths shorter than NumHops is * found, then they will be padded using dummy hops. * - * @generated from protobuf field: optional uint32 num_hops = 2; + * @generated from protobuf field: optional uint32 num_hops = 2 */ numHops?: number; /** * * The maximum number of blinded paths to select and add to an invoice. * - * @generated from protobuf field: optional uint32 max_num_paths = 3; + * @generated from protobuf field: optional uint32 max_num_paths = 3 */ maxNumPaths?: number; /** @@ -5456,7 +5649,7 @@ export interface BlindedPathConfig { * A list of node IDs of nodes that should not be used in any of our generated * blinded paths. * - * @generated from protobuf field: repeated bytes node_omission_list = 4; + * @generated from protobuf field: repeated bytes node_omission_list = 4 */ nodeOmissionList: Uint8Array[]; } @@ -5469,55 +5662,55 @@ export interface InvoiceHTLC { /** * Short channel id over which the htlc was received. * - * @generated from protobuf field: uint64 chan_id = 1 [jstype = JS_STRING]; + * @generated from protobuf field: uint64 chan_id = 1 [jstype = JS_STRING] */ chanId: string; /** * Index identifying the htlc on the channel. * - * @generated from protobuf field: uint64 htlc_index = 2; + * @generated from protobuf field: uint64 htlc_index = 2 */ htlcIndex: bigint; /** * The amount of the htlc in msat. * - * @generated from protobuf field: uint64 amt_msat = 3; + * @generated from protobuf field: uint64 amt_msat = 3 */ amtMsat: bigint; /** * Block height at which this htlc was accepted. * - * @generated from protobuf field: int32 accept_height = 4; + * @generated from protobuf field: int32 accept_height = 4 */ acceptHeight: number; /** * Time at which this htlc was accepted. * - * @generated from protobuf field: int64 accept_time = 5; + * @generated from protobuf field: int64 accept_time = 5 */ acceptTime: bigint; /** * Time at which this htlc was settled or canceled. * - * @generated from protobuf field: int64 resolve_time = 6; + * @generated from protobuf field: int64 resolve_time = 6 */ resolveTime: bigint; /** * Block height at which this htlc expires. * - * @generated from protobuf field: int32 expiry_height = 7; + * @generated from protobuf field: int32 expiry_height = 7 */ expiryHeight: number; /** * Current state the htlc is in. * - * @generated from protobuf field: lnrpc.InvoiceHTLCState state = 8; + * @generated from protobuf field: lnrpc.InvoiceHTLCState state = 8 */ state: InvoiceHTLCState; /** * Custom tlv records. * - * @generated from protobuf field: map custom_records = 9; + * @generated from protobuf field: map custom_records = 9 */ customRecords: { [key: string]: Uint8Array; @@ -5525,15 +5718,22 @@ export interface InvoiceHTLC { /** * The total amount of the mpp payment in msat. * - * @generated from protobuf field: uint64 mpp_total_amt_msat = 10; + * @generated from protobuf field: uint64 mpp_total_amt_msat = 10 */ mppTotalAmtMsat: bigint; /** * Details relevant to AMP HTLCs, only populated if this is an AMP HTLC. * - * @generated from protobuf field: lnrpc.AMP amp = 11; + * @generated from protobuf field: lnrpc.AMP amp = 11 */ amp?: AMP; + /** + * + * Custom channel data that might be populated in custom channels. + * + * @generated from protobuf field: bytes custom_channel_data = 12 + */ + customChannelData: Uint8Array; } /** * Details specific to AMP HTLCs. @@ -5545,26 +5745,26 @@ export interface AMP { * An n-of-n secret share of the root seed from which child payment hashes * and preimages are derived. * - * @generated from protobuf field: bytes root_share = 1; + * @generated from protobuf field: bytes root_share = 1 */ rootShare: Uint8Array; /** * An identifier for the HTLC set that this HTLC belongs to. * - * @generated from protobuf field: bytes set_id = 2; + * @generated from protobuf field: bytes set_id = 2 */ setId: Uint8Array; /** * A nonce used to randomize the child preimage and child hash from a given * root_share. * - * @generated from protobuf field: uint32 child_index = 3; + * @generated from protobuf field: uint32 child_index = 3 */ childIndex: number; /** * The payment hash of the AMP HTLC. * - * @generated from protobuf field: bytes hash = 4; + * @generated from protobuf field: bytes hash = 4 */ hash: Uint8Array; /** @@ -5572,7 +5772,7 @@ export interface AMP { * populated if the invoice is in InvoiceState_ACCEPTED or * InvoiceState_SETTLED. * - * @generated from protobuf field: bytes preimage = 5; + * @generated from protobuf field: bytes preimage = 5 */ preimage: Uint8Array; } @@ -5581,7 +5781,7 @@ export interface AMP { */ export interface AddInvoiceResponse { /** - * @generated from protobuf field: bytes r_hash = 1; + * @generated from protobuf field: bytes r_hash = 1 */ rHash: Uint8Array; /** @@ -5590,7 +5790,7 @@ export interface AddInvoiceResponse { * details of the invoice, the sender has all the data necessary to send a * payment to the recipient. * - * @generated from protobuf field: string payment_request = 2; + * @generated from protobuf field: string payment_request = 2 */ paymentRequest: string; /** @@ -5600,7 +5800,7 @@ export interface AddInvoiceResponse { * SubscribeInvoices call can use this to instantly get notified of all added * invoices with an add_index greater than this one. * - * @generated from protobuf field: uint64 add_index = 16; + * @generated from protobuf field: uint64 add_index = 16 */ addIndex: bigint; /** @@ -5609,7 +5809,7 @@ export interface AddInvoiceResponse { * payment secret in specifications (e.g. BOLT 11). This value should be used * in all payments for this invoice as we require it for end to end security. * - * @generated from protobuf field: bytes payment_addr = 17; + * @generated from protobuf field: bytes payment_addr = 17 */ paymentAddr: Uint8Array; } @@ -5625,7 +5825,7 @@ export interface PaymentHash { * fields. * * @deprecated - * @generated from protobuf field: string r_hash_str = 1 [deprecated = true]; + * @generated from protobuf field: string r_hash_str = 1 [deprecated = true] */ rHashStr: string; /** @@ -5633,7 +5833,7 @@ export interface PaymentHash { * The payment hash of the invoice to be looked up. When using REST, this field * must be encoded as base64. * - * @generated from protobuf field: bytes r_hash = 2; + * @generated from protobuf field: bytes r_hash = 2 */ rHash: Uint8Array; } @@ -5646,7 +5846,7 @@ export interface ListInvoiceRequest { * If set, only invoices that are not settled and not canceled will be returned * in the response. * - * @generated from protobuf field: bool pending_only = 1; + * @generated from protobuf field: bool pending_only = 1 */ pendingOnly: boolean; /** @@ -5654,13 +5854,13 @@ export interface ListInvoiceRequest { * The index of an invoice that will be used as either the start or end of a * query to determine which invoices should be returned in the response. * - * @generated from protobuf field: uint64 index_offset = 4; + * @generated from protobuf field: uint64 index_offset = 4 */ indexOffset: bigint; /** * The max number of invoices to return in the response to this query. * - * @generated from protobuf field: uint64 num_max_invoices = 5; + * @generated from protobuf field: uint64 num_max_invoices = 5 */ numMaxInvoices: bigint; /** @@ -5668,21 +5868,21 @@ export interface ListInvoiceRequest { * If set, the invoices returned will result from seeking backwards from the * specified index offset. This can be used to paginate backwards. * - * @generated from protobuf field: bool reversed = 6; + * @generated from protobuf field: bool reversed = 6 */ reversed: boolean; /** * If set, returns all invoices with a creation date greater than or equal * to it. Measured in seconds since the unix epoch. * - * @generated from protobuf field: uint64 creation_date_start = 7; + * @generated from protobuf field: uint64 creation_date_start = 7 */ creationDateStart: bigint; /** * If set, returns all invoices with a creation date less than or equal to * it. Measured in seconds since the unix epoch. * - * @generated from protobuf field: uint64 creation_date_end = 8; + * @generated from protobuf field: uint64 creation_date_end = 8 */ creationDateEnd: bigint; } @@ -5695,7 +5895,7 @@ export interface ListInvoiceResponse { * A list of invoices from the time slice of the time series specified in the * request. * - * @generated from protobuf field: repeated lnrpc.Invoice invoices = 1; + * @generated from protobuf field: repeated lnrpc.Invoice invoices = 1 */ invoices: Invoice[]; /** @@ -5703,7 +5903,7 @@ export interface ListInvoiceResponse { * The index of the last item in the set of returned invoices. This can be used * to seek further, pagination style. * - * @generated from protobuf field: uint64 last_index_offset = 2; + * @generated from protobuf field: uint64 last_index_offset = 2 */ lastIndexOffset: bigint; /** @@ -5711,7 +5911,7 @@ export interface ListInvoiceResponse { * The index of the last item in the set of returned invoices. This can be used * to seek backwards, pagination style. * - * @generated from protobuf field: uint64 first_index_offset = 3; + * @generated from protobuf field: uint64 first_index_offset = 3 */ firstIndexOffset: bigint; } @@ -5726,7 +5926,7 @@ export interface InvoiceSubscription { * value. This allows callers to catch up on any events they missed while they * weren't connected to the streaming RPC. * - * @generated from protobuf field: uint64 add_index = 1; + * @generated from protobuf field: uint64 add_index = 1 */ addIndex: bigint; /** @@ -5736,7 +5936,7 @@ export interface InvoiceSubscription { * this value. This allows callers to catch up on any events they missed while * they weren't connected to the streaming RPC. * - * @generated from protobuf field: uint64 settle_index = 2; + * @generated from protobuf field: uint64 settle_index = 2 */ settleIndex: bigint; } @@ -5747,82 +5947,82 @@ export interface Payment { /** * The payment hash * - * @generated from protobuf field: string payment_hash = 1; + * @generated from protobuf field: string payment_hash = 1 */ paymentHash: string; /** * Deprecated, use value_sat or value_msat. * * @deprecated - * @generated from protobuf field: int64 value = 2 [deprecated = true]; + * @generated from protobuf field: int64 value = 2 [deprecated = true] */ value: bigint; /** * Deprecated, use creation_time_ns * * @deprecated - * @generated from protobuf field: int64 creation_date = 3 [deprecated = true]; + * @generated from protobuf field: int64 creation_date = 3 [deprecated = true] */ creationDate: bigint; /** * Deprecated, use fee_sat or fee_msat. * * @deprecated - * @generated from protobuf field: int64 fee = 5 [deprecated = true]; + * @generated from protobuf field: int64 fee = 5 [deprecated = true] */ fee: bigint; /** * The payment preimage * - * @generated from protobuf field: string payment_preimage = 6; + * @generated from protobuf field: string payment_preimage = 6 */ paymentPreimage: string; /** * The value of the payment in satoshis * - * @generated from protobuf field: int64 value_sat = 7; + * @generated from protobuf field: int64 value_sat = 7 */ valueSat: bigint; /** * The value of the payment in milli-satoshis * - * @generated from protobuf field: int64 value_msat = 8; + * @generated from protobuf field: int64 value_msat = 8 */ valueMsat: bigint; /** * The optional payment request being fulfilled. * - * @generated from protobuf field: string payment_request = 9; + * @generated from protobuf field: string payment_request = 9 */ paymentRequest: string; /** * The status of the payment. * - * @generated from protobuf field: lnrpc.Payment.PaymentStatus status = 10; + * @generated from protobuf field: lnrpc.Payment.PaymentStatus status = 10 */ status: Payment_PaymentStatus; /** * The fee paid for this payment in satoshis * - * @generated from protobuf field: int64 fee_sat = 11; + * @generated from protobuf field: int64 fee_sat = 11 */ feeSat: bigint; /** * The fee paid for this payment in milli-satoshis * - * @generated from protobuf field: int64 fee_msat = 12; + * @generated from protobuf field: int64 fee_msat = 12 */ feeMsat: bigint; /** * The time in UNIX nanoseconds at which the payment was created. * - * @generated from protobuf field: int64 creation_time_ns = 13; + * @generated from protobuf field: int64 creation_time_ns = 13 */ creationTimeNs: bigint; /** * The HTLCs made in attempt to settle the payment. * - * @generated from protobuf field: repeated lnrpc.HTLCAttempt htlcs = 14; + * @generated from protobuf field: repeated lnrpc.HTLCAttempt htlcs = 14 */ htlcs: HTLCAttempt[]; /** @@ -5831,13 +6031,23 @@ export interface Payment { * by this index, which may not strictly increment by 1 for payments made in * older versions of lnd. * - * @generated from protobuf field: uint64 payment_index = 15; + * @generated from protobuf field: uint64 payment_index = 15 */ paymentIndex: bigint; /** - * @generated from protobuf field: lnrpc.PaymentFailureReason failure_reason = 16; + * @generated from protobuf field: lnrpc.PaymentFailureReason failure_reason = 16 */ failureReason: PaymentFailureReason; + /** + * + * The custom TLV records that were sent to the first hop as part of the HTLC + * wire message for this payment. + * + * @generated from protobuf field: map first_hop_custom_records = 17 + */ + firstHopCustomRecords: { + [key: string]: Uint8Array; + }; } /** * @generated from protobuf enum lnrpc.Payment.PaymentStatus @@ -5882,25 +6092,25 @@ export interface HTLCAttempt { /** * The unique ID that is used for this attempt. * - * @generated from protobuf field: uint64 attempt_id = 7; + * @generated from protobuf field: uint64 attempt_id = 7 */ attemptId: bigint; /** * The status of the HTLC. * - * @generated from protobuf field: lnrpc.HTLCAttempt.HTLCStatus status = 1; + * @generated from protobuf field: lnrpc.HTLCAttempt.HTLCStatus status = 1 */ status: HTLCAttempt_HTLCStatus; /** * The route taken by this HTLC. * - * @generated from protobuf field: lnrpc.Route route = 2; + * @generated from protobuf field: lnrpc.Route route = 2 */ route?: Route; /** * The time in UNIX nanoseconds at which this HTLC was sent. * - * @generated from protobuf field: int64 attempt_time_ns = 3; + * @generated from protobuf field: int64 attempt_time_ns = 3 */ attemptTimeNs: bigint; /** @@ -5908,19 +6118,19 @@ export interface HTLCAttempt { * The time in UNIX nanoseconds at which this HTLC was settled or failed. * This value will not be set if the HTLC is still IN_FLIGHT. * - * @generated from protobuf field: int64 resolve_time_ns = 4; + * @generated from protobuf field: int64 resolve_time_ns = 4 */ resolveTimeNs: bigint; /** * Detailed htlc failure info. * - * @generated from protobuf field: lnrpc.Failure failure = 5; + * @generated from protobuf field: lnrpc.Failure failure = 5 */ failure?: Failure; /** * The preimage that was used to settle the HTLC. * - * @generated from protobuf field: bytes preimage = 6; + * @generated from protobuf field: bytes preimage = 6 */ preimage: Uint8Array; } @@ -5952,7 +6162,7 @@ export interface ListPaymentsRequest { * field is set to true. This flag doesn't change the meaning of the indices, * which are tied to individual payments. * - * @generated from protobuf field: bool include_incomplete = 1; + * @generated from protobuf field: bool include_incomplete = 1 */ includeIncomplete: boolean; /** @@ -5963,13 +6173,13 @@ export interface ListPaymentsRequest { * will start with the oldest payment when paginating forwards, or will end * with the most recent payment when paginating backwards. * - * @generated from protobuf field: uint64 index_offset = 2; + * @generated from protobuf field: uint64 index_offset = 2 */ indexOffset: bigint; /** * The maximal number of payments returned in the response to this query. * - * @generated from protobuf field: uint64 max_payments = 3; + * @generated from protobuf field: uint64 max_payments = 3 */ maxPayments: bigint; /** @@ -5978,7 +6188,7 @@ export interface ListPaymentsRequest { * specified index offset. This can be used to paginate backwards. The order * of the returned payments is always oldest first (ascending index order). * - * @generated from protobuf field: bool reversed = 4; + * @generated from protobuf field: bool reversed = 4 */ reversed: boolean; /** @@ -5988,21 +6198,21 @@ export interface ListPaymentsRequest { * increase the run time of the call significantly on systems that have a lot * of payments, as all of them have to be iterated through to be counted. * - * @generated from protobuf field: bool count_total_payments = 5; + * @generated from protobuf field: bool count_total_payments = 5 */ countTotalPayments: boolean; /** * If set, returns all payments with a creation date greater than or equal * to it. Measured in seconds since the unix epoch. * - * @generated from protobuf field: uint64 creation_date_start = 6; + * @generated from protobuf field: uint64 creation_date_start = 6 */ creationDateStart: bigint; /** * If set, returns all payments with a creation date less than or equal to * it. Measured in seconds since the unix epoch. * - * @generated from protobuf field: uint64 creation_date_end = 7; + * @generated from protobuf field: uint64 creation_date_end = 7 */ creationDateEnd: bigint; } @@ -6013,7 +6223,7 @@ export interface ListPaymentsResponse { /** * The list of payments * - * @generated from protobuf field: repeated lnrpc.Payment payments = 1; + * @generated from protobuf field: repeated lnrpc.Payment payments = 1 */ payments: Payment[]; /** @@ -6021,7 +6231,7 @@ export interface ListPaymentsResponse { * The index of the first item in the set of returned payments. This can be * used as the index_offset to continue seeking backwards in the next request. * - * @generated from protobuf field: uint64 first_index_offset = 2; + * @generated from protobuf field: uint64 first_index_offset = 2 */ firstIndexOffset: bigint; /** @@ -6029,7 +6239,7 @@ export interface ListPaymentsResponse { * The index of the last item in the set of returned payments. This can be used * as the index_offset to continue seeking forwards in the next request. * - * @generated from protobuf field: uint64 last_index_offset = 3; + * @generated from protobuf field: uint64 last_index_offset = 3 */ lastIndexOffset: bigint; /** @@ -6039,7 +6249,7 @@ export interface ListPaymentsResponse { * number of payments requested in the query) currently present in the payments * database. * - * @generated from protobuf field: uint64 total_num_payments = 4; + * @generated from protobuf field: uint64 total_num_payments = 4 */ totalNumPayments: bigint; } @@ -6050,14 +6260,14 @@ export interface DeletePaymentRequest { /** * Payment hash to delete. * - * @generated from protobuf field: bytes payment_hash = 1; + * @generated from protobuf field: bytes payment_hash = 1 */ paymentHash: Uint8Array; /** * * Only delete failed HTLCs from the payment, not the payment itself. * - * @generated from protobuf field: bool failed_htlcs_only = 2; + * @generated from protobuf field: bool failed_htlcs_only = 2 */ failedHtlcsOnly: boolean; } @@ -6068,21 +6278,21 @@ export interface DeleteAllPaymentsRequest { /** * Only delete failed payments. * - * @generated from protobuf field: bool failed_payments_only = 1; + * @generated from protobuf field: bool failed_payments_only = 1 */ failedPaymentsOnly: boolean; /** * * Only delete failed HTLCs from payments, not the payment itself. * - * @generated from protobuf field: bool failed_htlcs_only = 2; + * @generated from protobuf field: bool failed_htlcs_only = 2 */ failedHtlcsOnly: boolean; /** * Delete all payments. NOTE: Using this option requires careful * consideration as it is a destructive operation. * - * @generated from protobuf field: bool all_payments = 3; + * @generated from protobuf field: bool all_payments = 3 */ allPayments: boolean; } @@ -6090,22 +6300,34 @@ export interface DeleteAllPaymentsRequest { * @generated from protobuf message lnrpc.DeletePaymentResponse */ export interface DeletePaymentResponse { + /** + * The status of the delete operation. + * + * @generated from protobuf field: string status = 1 + */ + status: string; } /** * @generated from protobuf message lnrpc.DeleteAllPaymentsResponse */ export interface DeleteAllPaymentsResponse { + /** + * The status of the delete operation. + * + * @generated from protobuf field: string status = 1 + */ + status: string; } /** * @generated from protobuf message lnrpc.AbandonChannelRequest */ export interface AbandonChannelRequest { /** - * @generated from protobuf field: lnrpc.ChannelPoint channel_point = 1; + * @generated from protobuf field: lnrpc.ChannelPoint channel_point = 1 */ channelPoint?: ChannelPoint; /** - * @generated from protobuf field: bool pending_funding_shim_only = 2; + * @generated from protobuf field: bool pending_funding_shim_only = 2 */ pendingFundingShimOnly: boolean; /** @@ -6114,7 +6336,7 @@ export interface AbandonChannelRequest { * confirming the user knows what they are doing and this is a potential foot * gun to lose funds if used on active channels. * - * @generated from protobuf field: bool i_know_what_i_am_doing = 3; + * @generated from protobuf field: bool i_know_what_i_am_doing = 3 */ iKnowWhatIAmDoing: boolean; } @@ -6122,17 +6344,23 @@ export interface AbandonChannelRequest { * @generated from protobuf message lnrpc.AbandonChannelResponse */ export interface AbandonChannelResponse { + /** + * The status of the abandon operation. + * + * @generated from protobuf field: string status = 1 + */ + status: string; } /** * @generated from protobuf message lnrpc.DebugLevelRequest */ export interface DebugLevelRequest { /** - * @generated from protobuf field: bool show = 1; + * @generated from protobuf field: bool show = 1 */ show: boolean; /** - * @generated from protobuf field: string level_spec = 2; + * @generated from protobuf field: string level_spec = 2 */ levelSpec: string; } @@ -6141,7 +6369,7 @@ export interface DebugLevelRequest { */ export interface DebugLevelResponse { /** - * @generated from protobuf field: string sub_systems = 1; + * @generated from protobuf field: string sub_systems = 1 */ subSystems: string; } @@ -6152,7 +6380,7 @@ export interface PayReqString { /** * The payment request string to be decoded * - * @generated from protobuf field: string pay_req = 1; + * @generated from protobuf field: string pay_req = 1 */ payReq: string; } @@ -6161,61 +6389,61 @@ export interface PayReqString { */ export interface PayReq { /** - * @generated from protobuf field: string destination = 1; + * @generated from protobuf field: string destination = 1 */ destination: string; /** - * @generated from protobuf field: string payment_hash = 2; + * @generated from protobuf field: string payment_hash = 2 */ paymentHash: string; /** - * @generated from protobuf field: int64 num_satoshis = 3; + * @generated from protobuf field: int64 num_satoshis = 3 */ numSatoshis: bigint; /** - * @generated from protobuf field: int64 timestamp = 4; + * @generated from protobuf field: int64 timestamp = 4 */ timestamp: bigint; /** - * @generated from protobuf field: int64 expiry = 5; + * @generated from protobuf field: int64 expiry = 5 */ expiry: bigint; /** - * @generated from protobuf field: string description = 6; + * @generated from protobuf field: string description = 6 */ description: string; /** - * @generated from protobuf field: string description_hash = 7; + * @generated from protobuf field: string description_hash = 7 */ descriptionHash: string; /** - * @generated from protobuf field: string fallback_addr = 8; + * @generated from protobuf field: string fallback_addr = 8 */ fallbackAddr: string; /** - * @generated from protobuf field: int64 cltv_expiry = 9; + * @generated from protobuf field: int64 cltv_expiry = 9 */ cltvExpiry: bigint; /** - * @generated from protobuf field: repeated lnrpc.RouteHint route_hints = 10; + * @generated from protobuf field: repeated lnrpc.RouteHint route_hints = 10 */ routeHints: RouteHint[]; /** - * @generated from protobuf field: bytes payment_addr = 11; + * @generated from protobuf field: bytes payment_addr = 11 */ paymentAddr: Uint8Array; /** - * @generated from protobuf field: int64 num_msat = 12; + * @generated from protobuf field: int64 num_msat = 12 */ numMsat: bigint; /** - * @generated from protobuf field: map features = 13; + * @generated from protobuf field: map features = 13 */ features: { [key: number]: Feature; }; /** - * @generated from protobuf field: repeated lnrpc.BlindedPaymentPath blinded_paths = 14; + * @generated from protobuf field: repeated lnrpc.BlindedPaymentPath blinded_paths = 14 */ blindedPaths: BlindedPaymentPath[]; } @@ -6224,15 +6452,15 @@ export interface PayReq { */ export interface Feature { /** - * @generated from protobuf field: string name = 2; + * @generated from protobuf field: string name = 2 */ name: string; /** - * @generated from protobuf field: bool is_required = 3; + * @generated from protobuf field: bool is_required = 3 */ isRequired: boolean; /** - * @generated from protobuf field: bool is_known = 4; + * @generated from protobuf field: bool is_known = 4 */ isKnown: boolean; } @@ -6248,46 +6476,46 @@ export interface ChannelFeeReport { /** * The short channel id that this fee report belongs to. * - * @generated from protobuf field: uint64 chan_id = 5 [jstype = JS_STRING]; + * @generated from protobuf field: uint64 chan_id = 5 [jstype = JS_STRING] */ chanId: string; /** * The channel that this fee report belongs to. * - * @generated from protobuf field: string channel_point = 1; + * @generated from protobuf field: string channel_point = 1 */ channelPoint: string; /** * The base fee charged regardless of the number of milli-satoshis sent. * - * @generated from protobuf field: int64 base_fee_msat = 2; + * @generated from protobuf field: int64 base_fee_msat = 2 */ baseFeeMsat: bigint; /** * The amount charged per milli-satoshis transferred expressed in * millionths of a satoshi. * - * @generated from protobuf field: int64 fee_per_mil = 3; + * @generated from protobuf field: int64 fee_per_mil = 3 */ feePerMil: bigint; /** * The effective fee rate in milli-satoshis. Computed by dividing the * fee_per_mil value by 1 million. * - * @generated from protobuf field: double fee_rate = 4; + * @generated from protobuf field: double fee_rate = 4 */ feeRate: number; /** * The base fee charged regardless of the number of milli-satoshis sent. * - * @generated from protobuf field: int32 inbound_base_fee_msat = 6; + * @generated from protobuf field: int32 inbound_base_fee_msat = 6 */ inboundBaseFeeMsat: number; /** * The amount charged per milli-satoshis transferred expressed in * millionths of a satoshi. * - * @generated from protobuf field: int32 inbound_fee_per_mil = 7; + * @generated from protobuf field: int32 inbound_fee_per_mil = 7 */ inboundFeePerMil: number; } @@ -6299,28 +6527,28 @@ export interface FeeReportResponse { * An array of channel fee reports which describes the current fee schedule * for each channel. * - * @generated from protobuf field: repeated lnrpc.ChannelFeeReport channel_fees = 1; + * @generated from protobuf field: repeated lnrpc.ChannelFeeReport channel_fees = 1 */ channelFees: ChannelFeeReport[]; /** * The total amount of fee revenue (in satoshis) the switch has collected * over the past 24 hrs. * - * @generated from protobuf field: uint64 day_fee_sum = 2; + * @generated from protobuf field: uint64 day_fee_sum = 2 */ dayFeeSum: bigint; /** * The total amount of fee revenue (in satoshis) the switch has collected * over the past 1 week. * - * @generated from protobuf field: uint64 week_fee_sum = 3; + * @generated from protobuf field: uint64 week_fee_sum = 3 */ weekFeeSum: bigint; /** * The total amount of fee revenue (in satoshis) the switch has collected * over the past 1 month. * - * @generated from protobuf field: uint64 month_fee_sum = 4; + * @generated from protobuf field: uint64 month_fee_sum = 4 */ monthFeeSum: bigint; } @@ -6332,14 +6560,14 @@ export interface InboundFee { * The inbound base fee charged regardless of the number of milli-satoshis * received in the channel. By default, only negative values are accepted. * - * @generated from protobuf field: int32 base_fee_msat = 1; + * @generated from protobuf field: int32 base_fee_msat = 1 */ baseFeeMsat: number; /** * The effective inbound fee rate in micro-satoshis (parts per million). * By default, only negative values are accepted. * - * @generated from protobuf field: int32 fee_rate_ppm = 2; + * @generated from protobuf field: int32 fee_rate_ppm = 2 */ feeRatePpm: number; } @@ -6355,7 +6583,7 @@ export interface PolicyUpdateRequest { /** * If set, then this update applies to all currently active channels. * - * @generated from protobuf field: bool global = 1; + * @generated from protobuf field: bool global = 1 */ global: boolean; } | { @@ -6363,7 +6591,7 @@ export interface PolicyUpdateRequest { /** * If set, this update will target a specific channel. * - * @generated from protobuf field: lnrpc.ChannelPoint chan_point = 2; + * @generated from protobuf field: lnrpc.ChannelPoint chan_point = 2 */ chanPoint: ChannelPoint; } | { @@ -6372,55 +6600,67 @@ export interface PolicyUpdateRequest { /** * The base fee charged regardless of the number of milli-satoshis sent. * - * @generated from protobuf field: int64 base_fee_msat = 3; + * @generated from protobuf field: int64 base_fee_msat = 3 */ baseFeeMsat: bigint; /** * The effective fee rate in milli-satoshis. The precision of this value * goes up to 6 decimal places, so 1e-6. * - * @generated from protobuf field: double fee_rate = 4; + * @generated from protobuf field: double fee_rate = 4 */ feeRate: number; /** * The effective fee rate in micro-satoshis (parts per million). * - * @generated from protobuf field: uint32 fee_rate_ppm = 9; + * @generated from protobuf field: uint32 fee_rate_ppm = 9 */ feeRatePpm: number; /** * The required timelock delta for HTLCs forwarded over the channel. * - * @generated from protobuf field: uint32 time_lock_delta = 5; + * @generated from protobuf field: uint32 time_lock_delta = 5 */ timeLockDelta: number; /** * If set, the maximum HTLC size in milli-satoshis. If unset, the maximum * HTLC will be unchanged. * - * @generated from protobuf field: uint64 max_htlc_msat = 6; + * @generated from protobuf field: uint64 max_htlc_msat = 6 */ maxHtlcMsat: bigint; /** * The minimum HTLC size in milli-satoshis. Only applied if * min_htlc_msat_specified is true. * - * @generated from protobuf field: uint64 min_htlc_msat = 7; + * @generated from protobuf field: uint64 min_htlc_msat = 7 */ minHtlcMsat: bigint; /** * If true, min_htlc_msat is applied. * - * @generated from protobuf field: bool min_htlc_msat_specified = 8; + * @generated from protobuf field: bool min_htlc_msat_specified = 8 */ minHtlcMsatSpecified: boolean; /** * Optional inbound fee. If unset, the previously set value will be * retained [EXPERIMENTAL]. * - * @generated from protobuf field: lnrpc.InboundFee inbound_fee = 10; + * @generated from protobuf field: lnrpc.InboundFee inbound_fee = 10 */ inboundFee?: InboundFee; + /** + * Under unknown circumstances a channel can exist with a missing edge in + * the graph database. This can cause an 'edge not found' error when calling + * `getchaninfo` and/or cause the default channel policy to be used during + * forwards. Setting this flag will recreate the edge if not found, allowing + * updating this channel policy and fixing the missing edge problem for this + * channel permanently. For fields not set in this command, the default + * policy will be created. + * + * @generated from protobuf field: bool create_missing_edge = 11 + */ + createMissingEdge: boolean; } /** * @generated from protobuf message lnrpc.FailedUpdate @@ -6429,19 +6669,19 @@ export interface FailedUpdate { /** * The outpoint in format txid:n * - * @generated from protobuf field: lnrpc.OutPoint outpoint = 1; + * @generated from protobuf field: lnrpc.OutPoint outpoint = 1 */ outpoint?: OutPoint; /** * Reason for the policy update failure. * - * @generated from protobuf field: lnrpc.UpdateFailure reason = 2; + * @generated from protobuf field: lnrpc.UpdateFailure reason = 2 */ reason: UpdateFailure; /** * A string representation of the policy update error. * - * @generated from protobuf field: string update_error = 3; + * @generated from protobuf field: string update_error = 3 */ updateError: string; } @@ -6452,7 +6692,7 @@ export interface PolicyUpdateResponse { /** * List of failed policy updates. * - * @generated from protobuf field: repeated lnrpc.FailedUpdate failed_updates = 1; + * @generated from protobuf field: repeated lnrpc.FailedUpdate failed_updates = 1 */ failedUpdates: FailedUpdate[]; } @@ -6465,7 +6705,7 @@ export interface ForwardingHistoryRequest { * records beyond this point will be included, respecting the end time, and * the index offset. * - * @generated from protobuf field: uint64 start_time = 1; + * @generated from protobuf field: uint64 start_time = 1 */ startTime: bigint; /** @@ -6473,7 +6713,7 @@ export interface ForwardingHistoryRequest { * response will carry at most 50k records between the start time and the * end time. The index offset can be used to implement pagination. * - * @generated from protobuf field: uint64 end_time = 2; + * @generated from protobuf field: uint64 end_time = 2 */ endTime: bigint; /** @@ -6481,20 +6721,20 @@ export interface ForwardingHistoryRequest { * response can only contain 50k records, callers can use this to skip * around within a packed time series. * - * @generated from protobuf field: uint32 index_offset = 3; + * @generated from protobuf field: uint32 index_offset = 3 */ indexOffset: number; /** * The max number of events to return in the response to this query. * - * @generated from protobuf field: uint32 num_max_events = 4; + * @generated from protobuf field: uint32 num_max_events = 4 */ numMaxEvents: number; /** * Informs the server if the peer alias should be looked up for each * forwarding event. * - * @generated from protobuf field: bool peer_alias_lookup = 5; + * @generated from protobuf field: bool peer_alias_lookup = 5 */ peerAliasLookup: boolean; } @@ -6507,81 +6747,95 @@ export interface ForwardingEvent { * completed. Deprecated by timestamp_ns. * * @deprecated - * @generated from protobuf field: uint64 timestamp = 1 [deprecated = true]; + * @generated from protobuf field: uint64 timestamp = 1 [deprecated = true] */ timestamp: bigint; /** * The incoming channel ID that carried the HTLC that created the circuit. * - * @generated from protobuf field: uint64 chan_id_in = 2 [jstype = JS_STRING]; + * @generated from protobuf field: uint64 chan_id_in = 2 [jstype = JS_STRING] */ chanIdIn: string; /** * The outgoing channel ID that carried the preimage that completed the * circuit. * - * @generated from protobuf field: uint64 chan_id_out = 4 [jstype = JS_STRING]; + * @generated from protobuf field: uint64 chan_id_out = 4 [jstype = JS_STRING] */ chanIdOut: string; /** * The total amount (in satoshis) of the incoming HTLC that created half * the circuit. * - * @generated from protobuf field: uint64 amt_in = 5; + * @generated from protobuf field: uint64 amt_in = 5 */ amtIn: bigint; /** * The total amount (in satoshis) of the outgoing HTLC that created the * second half of the circuit. * - * @generated from protobuf field: uint64 amt_out = 6; + * @generated from protobuf field: uint64 amt_out = 6 */ amtOut: bigint; /** * The total fee (in satoshis) that this payment circuit carried. * - * @generated from protobuf field: uint64 fee = 7; + * @generated from protobuf field: uint64 fee = 7 */ fee: bigint; /** * The total fee (in milli-satoshis) that this payment circuit carried. * - * @generated from protobuf field: uint64 fee_msat = 8; + * @generated from protobuf field: uint64 fee_msat = 8 */ feeMsat: bigint; /** * The total amount (in milli-satoshis) of the incoming HTLC that created * half the circuit. * - * @generated from protobuf field: uint64 amt_in_msat = 9; + * @generated from protobuf field: uint64 amt_in_msat = 9 */ amtInMsat: bigint; /** * The total amount (in milli-satoshis) of the outgoing HTLC that created * the second half of the circuit. * - * @generated from protobuf field: uint64 amt_out_msat = 10; + * @generated from protobuf field: uint64 amt_out_msat = 10 */ amtOutMsat: bigint; /** * The number of nanoseconds elapsed since January 1, 1970 UTC when this * circuit was completed. * - * @generated from protobuf field: uint64 timestamp_ns = 11; + * @generated from protobuf field: uint64 timestamp_ns = 11 */ timestampNs: bigint; /** * The peer alias of the incoming channel. * - * @generated from protobuf field: string peer_alias_in = 12; + * @generated from protobuf field: string peer_alias_in = 12 */ peerAliasIn: string; /** * The peer alias of the outgoing channel. * - * @generated from protobuf field: string peer_alias_out = 13; + * @generated from protobuf field: string peer_alias_out = 13 */ peerAliasOut: string; + /** + * The ID of the incoming HTLC in the payment circuit. This field is + * optional and is unset for forwarding events happened before v0.20. + * + * @generated from protobuf field: optional uint64 incoming_htlc_id = 14 + */ + incomingHtlcId?: bigint; + /** + * The ID of the outgoing HTLC in the payment circuit. This field is + * optional and may be unset for legacy forwarding events. + * + * @generated from protobuf field: optional uint64 outgoing_htlc_id = 15 + */ + outgoingHtlcId?: bigint; } /** * @generated from protobuf message lnrpc.ForwardingHistoryResponse @@ -6591,14 +6845,14 @@ export interface ForwardingHistoryResponse { * A list of forwarding events from the time slice of the time series * specified in the request. * - * @generated from protobuf field: repeated lnrpc.ForwardingEvent forwarding_events = 1; + * @generated from protobuf field: repeated lnrpc.ForwardingEvent forwarding_events = 1 */ forwardingEvents: ForwardingEvent[]; /** * The index of the last time in the set of returned forwarding events. Can * be used to seek further, pagination style. * - * @generated from protobuf field: uint32 last_offset_index = 2; + * @generated from protobuf field: uint32 last_offset_index = 2 */ lastOffsetIndex: number; } @@ -6609,7 +6863,7 @@ export interface ExportChannelBackupRequest { /** * The target channel point to obtain a back up for. * - * @generated from protobuf field: lnrpc.ChannelPoint chan_point = 1; + * @generated from protobuf field: lnrpc.ChannelPoint chan_point = 1 */ chanPoint?: ChannelPoint; } @@ -6621,7 +6875,7 @@ export interface ChannelBackup { * * Identifies the channel that this backup belongs to. * - * @generated from protobuf field: lnrpc.ChannelPoint chan_point = 1; + * @generated from protobuf field: lnrpc.ChannelPoint chan_point = 1 */ chanPoint?: ChannelPoint; /** @@ -6631,7 +6885,7 @@ export interface ChannelBackup { * order to trigger the recovery protocol. When using REST, this field must be * encoded as base64. * - * @generated from protobuf field: bytes chan_backup = 2; + * @generated from protobuf field: bytes chan_backup = 2 */ chanBackup: Uint8Array; } @@ -6643,7 +6897,7 @@ export interface MultiChanBackup { * * Is the set of all channels that are included in this multi-channel backup. * - * @generated from protobuf field: repeated lnrpc.ChannelPoint chan_points = 1; + * @generated from protobuf field: repeated lnrpc.ChannelPoint chan_points = 1 */ chanPoints: ChannelPoint[]; /** @@ -6653,7 +6907,7 @@ export interface MultiChanBackup { * safely be replaced with any prior/future versions. When using REST, this * field must be encoded as base64. * - * @generated from protobuf field: bytes multi_chan_backup = 2; + * @generated from protobuf field: bytes multi_chan_backup = 2 */ multiChanBackup: Uint8Array; } @@ -6671,7 +6925,7 @@ export interface ChanBackupSnapshot { * The set of new channels that have been added since the last channel backup * snapshot was requested. * - * @generated from protobuf field: lnrpc.ChannelBackups single_chan_backups = 1; + * @generated from protobuf field: lnrpc.ChannelBackups single_chan_backups = 1 */ singleChanBackups?: ChannelBackups; /** @@ -6679,7 +6933,7 @@ export interface ChanBackupSnapshot { * A multi-channel backup that covers all open channels currently known to * lnd. * - * @generated from protobuf field: lnrpc.MultiChanBackup multi_chan_backup = 2; + * @generated from protobuf field: lnrpc.MultiChanBackup multi_chan_backup = 2 */ multiChanBackup?: MultiChanBackup; } @@ -6691,7 +6945,7 @@ export interface ChannelBackups { * * A set of single-chan static channel backups. * - * @generated from protobuf field: repeated lnrpc.ChannelBackup chan_backups = 1; + * @generated from protobuf field: repeated lnrpc.ChannelBackup chan_backups = 1 */ chanBackups: ChannelBackup[]; } @@ -6708,7 +6962,7 @@ export interface RestoreChanBackupRequest { * * The channels to restore as a list of channel/backup pairs. * - * @generated from protobuf field: lnrpc.ChannelBackups chan_backups = 1; + * @generated from protobuf field: lnrpc.ChannelBackups chan_backups = 1 */ chanBackups: ChannelBackups; } | { @@ -6718,7 +6972,7 @@ export interface RestoreChanBackupRequest { * The channels to restore in the packed multi backup format. When using * REST, this field must be encoded as base64. * - * @generated from protobuf field: bytes multi_chan_backup = 2; + * @generated from protobuf field: bytes multi_chan_backup = 2 */ multiChanBackup: Uint8Array; } | { @@ -6729,6 +6983,12 @@ export interface RestoreChanBackupRequest { * @generated from protobuf message lnrpc.RestoreBackupResponse */ export interface RestoreBackupResponse { + /** + * The number of channels successfully restored. + * + * @generated from protobuf field: uint32 num_restored = 1 + */ + numRestored: number; } /** * @generated from protobuf message lnrpc.ChannelBackupSubscription @@ -6739,6 +6999,10 @@ export interface ChannelBackupSubscription { * @generated from protobuf message lnrpc.VerifyChanBackupResponse */ export interface VerifyChanBackupResponse { + /** + * @generated from protobuf field: repeated string chan_points = 1 + */ + chanPoints: string[]; } /** * @generated from protobuf message lnrpc.MacaroonPermission @@ -6747,13 +7011,13 @@ export interface MacaroonPermission { /** * The entity a permission grants access to. * - * @generated from protobuf field: string entity = 1; + * @generated from protobuf field: string entity = 1 */ entity: string; /** * The action that is granted. * - * @generated from protobuf field: string action = 2; + * @generated from protobuf field: string action = 2 */ action: string; } @@ -6764,13 +7028,13 @@ export interface BakeMacaroonRequest { /** * The list of permissions the new macaroon should grant. * - * @generated from protobuf field: repeated lnrpc.MacaroonPermission permissions = 1; + * @generated from protobuf field: repeated lnrpc.MacaroonPermission permissions = 1 */ permissions: MacaroonPermission[]; /** * The root key ID used to create the macaroon, must be a positive integer. * - * @generated from protobuf field: uint64 root_key_id = 2; + * @generated from protobuf field: uint64 root_key_id = 2 */ rootKeyId: bigint; /** @@ -6778,7 +7042,7 @@ export interface BakeMacaroonRequest { * Informs the RPC on whether to allow external permissions that LND is not * aware of. * - * @generated from protobuf field: bool allow_external_permissions = 3; + * @generated from protobuf field: bool allow_external_permissions = 3 */ allowExternalPermissions: boolean; } @@ -6789,7 +7053,7 @@ export interface BakeMacaroonResponse { /** * The hex encoded macaroon, serialized in binary format. * - * @generated from protobuf field: string macaroon = 1; + * @generated from protobuf field: string macaroon = 1 */ macaroon: string; } @@ -6805,7 +7069,7 @@ export interface ListMacaroonIDsResponse { /** * The list of root key IDs that are in use. * - * @generated from protobuf field: repeated uint64 root_key_ids = 1; + * @generated from protobuf field: repeated uint64 root_key_ids = 1 */ rootKeyIds: bigint[]; } @@ -6816,7 +7080,7 @@ export interface DeleteMacaroonIDRequest { /** * The root key ID to be removed. * - * @generated from protobuf field: uint64 root_key_id = 1; + * @generated from protobuf field: uint64 root_key_id = 1 */ rootKeyId: bigint; } @@ -6827,7 +7091,7 @@ export interface DeleteMacaroonIDResponse { /** * A boolean indicates that the deletion is successful. * - * @generated from protobuf field: bool deleted = 1; + * @generated from protobuf field: bool deleted = 1 */ deleted: boolean; } @@ -6838,7 +7102,7 @@ export interface MacaroonPermissionList { /** * A list of macaroon permissions. * - * @generated from protobuf field: repeated lnrpc.MacaroonPermission permissions = 1; + * @generated from protobuf field: repeated lnrpc.MacaroonPermission permissions = 1 */ permissions: MacaroonPermission[]; } @@ -6856,7 +7120,7 @@ export interface ListPermissionsResponse { * A map between all RPC method URIs and their required macaroon permissions to * access them. * - * @generated from protobuf field: map method_permissions = 1; + * @generated from protobuf field: map method_permissions = 1 */ methodPermissions: { [key: string]: MacaroonPermissionList; @@ -6869,37 +7133,37 @@ export interface Failure { /** * Failure code as defined in the Lightning spec * - * @generated from protobuf field: lnrpc.Failure.FailureCode code = 1; + * @generated from protobuf field: lnrpc.Failure.FailureCode code = 1 */ code: Failure_FailureCode; /** * An optional channel update message. * - * @generated from protobuf field: lnrpc.ChannelUpdate channel_update = 3; + * @generated from protobuf field: lnrpc.ChannelUpdate channel_update = 3 */ channelUpdate?: ChannelUpdate; /** * A failure type-dependent htlc value. * - * @generated from protobuf field: uint64 htlc_msat = 4; + * @generated from protobuf field: uint64 htlc_msat = 4 */ htlcMsat: bigint; /** * The sha256 sum of the onion payload. * - * @generated from protobuf field: bytes onion_sha_256 = 5; + * @generated from protobuf field: bytes onion_sha_256 = 5 */ onionSha256: Uint8Array; /** * A failure type-dependent cltv expiry value. * - * @generated from protobuf field: uint32 cltv_expiry = 6; + * @generated from protobuf field: uint32 cltv_expiry = 6 */ cltvExpiry: number; /** * A failure type-dependent flags value. * - * @generated from protobuf field: uint32 flags = 7; + * @generated from protobuf field: uint32 flags = 7 */ flags: number; /** @@ -6907,13 +7171,13 @@ export interface Failure { * The position in the path of the intermediate or final node that generated * the failure message. Position zero is the sender node. * - * @generated from protobuf field: uint32 failure_source_index = 8; + * @generated from protobuf field: uint32 failure_source_index = 8 */ failureSourceIndex: number; /** * A failure type-dependent block height. * - * @generated from protobuf field: uint32 height = 9; + * @generated from protobuf field: uint32 height = 9 */ height: number; } @@ -7062,7 +7326,7 @@ export interface ChannelUpdate { * The signature that validates the announced data and proves the ownership * of node id. * - * @generated from protobuf field: bytes signature = 1; + * @generated from protobuf field: bytes signature = 1 */ signature: Uint8Array; /** @@ -7072,14 +7336,14 @@ export interface ChannelUpdate { * channel ID, this uniquely identifies the channel globally in a * blockchain. * - * @generated from protobuf field: bytes chain_hash = 2; + * @generated from protobuf field: bytes chain_hash = 2 */ chainHash: Uint8Array; /** * * The unique description of the funding transaction. * - * @generated from protobuf field: uint64 chan_id = 3 [jstype = JS_STRING]; + * @generated from protobuf field: uint64 chan_id = 3 [jstype = JS_STRING] */ chanId: string; /** @@ -7088,7 +7352,7 @@ export interface ChannelUpdate { * We should ignore the message if timestamp is not greater than the * last-received. * - * @generated from protobuf field: uint32 timestamp = 4; + * @generated from protobuf field: uint32 timestamp = 4 */ timestamp: number; /** @@ -7097,7 +7361,7 @@ export interface ChannelUpdate { * update. Currently, the least-significant bit must be set to 1 if the * optional field MaxHtlc is present. * - * @generated from protobuf field: uint32 message_flags = 10; + * @generated from protobuf field: uint32 message_flags = 10 */ messageFlags: number; /** @@ -7108,7 +7372,7 @@ export interface ChannelUpdate { * previously sent channel announcement and 1 otherwise. If the second bit * is set, then the channel is set to be disabled. * - * @generated from protobuf field: uint32 channel_flags = 5; + * @generated from protobuf field: uint32 channel_flags = 5 */ channelFlags: number; /** @@ -7118,14 +7382,14 @@ export interface ChannelUpdate { * This value represents the required gap between the time locks of the * incoming and outgoing HTLC's set to this node. * - * @generated from protobuf field: uint32 time_lock_delta = 6; + * @generated from protobuf field: uint32 time_lock_delta = 6 */ timeLockDelta: number; /** * * The minimum HTLC value which will be accepted. * - * @generated from protobuf field: uint64 htlc_minimum_msat = 7; + * @generated from protobuf field: uint64 htlc_minimum_msat = 7 */ htlcMinimumMsat: bigint; /** @@ -7134,21 +7398,21 @@ export interface ChannelUpdate { * channel. This value will be tacked onto the required for a payment * independent of the size of the payment. * - * @generated from protobuf field: uint32 base_fee = 8; + * @generated from protobuf field: uint32 base_fee = 8 */ baseFee: number; /** * * The fee rate that will be charged per millionth of a satoshi. * - * @generated from protobuf field: uint32 fee_rate = 9; + * @generated from protobuf field: uint32 fee_rate = 9 */ feeRate: number; /** * * The maximum HTLC value which will be accepted. * - * @generated from protobuf field: uint64 htlc_maximum_msat = 11; + * @generated from protobuf field: uint64 htlc_maximum_msat = 11 */ htlcMaximumMsat: bigint; /** @@ -7159,7 +7423,7 @@ export interface ChannelUpdate { * cover these new fields, and ensure we're able to make upgrades to the * network in a forwards compatible manner. * - * @generated from protobuf field: bytes extra_opaque_data = 12; + * @generated from protobuf field: bytes extra_opaque_data = 12 */ extraOpaqueData: Uint8Array; } @@ -7168,15 +7432,15 @@ export interface ChannelUpdate { */ export interface MacaroonId { /** - * @generated from protobuf field: bytes nonce = 1; + * @generated from protobuf field: bytes nonce = 1 */ nonce: Uint8Array; /** - * @generated from protobuf field: bytes storageId = 2; + * @generated from protobuf field: bytes storageId = 2 */ storageId: Uint8Array; /** - * @generated from protobuf field: repeated lnrpc.Op ops = 3; + * @generated from protobuf field: repeated lnrpc.Op ops = 3 */ ops: Op[]; } @@ -7185,11 +7449,11 @@ export interface MacaroonId { */ export interface Op { /** - * @generated from protobuf field: string entity = 1; + * @generated from protobuf field: string entity = 1 */ entity: string; /** - * @generated from protobuf field: repeated string actions = 2; + * @generated from protobuf field: repeated string actions = 2 */ actions: string[]; } @@ -7198,15 +7462,15 @@ export interface Op { */ export interface CheckMacPermRequest { /** - * @generated from protobuf field: bytes macaroon = 1; + * @generated from protobuf field: bytes macaroon = 1 */ macaroon: Uint8Array; /** - * @generated from protobuf field: repeated lnrpc.MacaroonPermission permissions = 2; + * @generated from protobuf field: repeated lnrpc.MacaroonPermission permissions = 2 */ permissions: MacaroonPermission[]; /** - * @generated from protobuf field: string fullMethod = 3; + * @generated from protobuf field: string fullMethod = 3 */ fullMethod: string; } @@ -7215,7 +7479,7 @@ export interface CheckMacPermRequest { */ export interface CheckMacPermResponse { /** - * @generated from protobuf field: bool valid = 1; + * @generated from protobuf field: bool valid = 1 */ valid: boolean; } @@ -7230,7 +7494,7 @@ export interface RPCMiddlewareRequest { * streaming requests, this will be the same ID for all incoming and outgoing * middleware intercept messages of the _same_ stream. * - * @generated from protobuf field: uint64 request_id = 1; + * @generated from protobuf field: uint64 request_id = 1 */ requestId: bigint; /** @@ -7239,7 +7503,7 @@ export interface RPCMiddlewareRequest { * original request. This might be empty for a request that doesn't require * macaroons such as the wallet unlocker RPCs. * - * @generated from protobuf field: bytes raw_macaroon = 2; + * @generated from protobuf field: bytes raw_macaroon = 2 */ rawMacaroon: Uint8Array; /** @@ -7249,10 +7513,17 @@ export interface RPCMiddlewareRequest { * middleware has registered itself for. The condition _must_ be validated for * messages of intercept_type stream_auth and request! * - * @generated from protobuf field: string custom_caveat_condition = 3; + * @generated from protobuf field: string custom_caveat_condition = 3 */ customCaveatCondition: string; /** + * + * There are three types of messages that will be sent to the middleware for + * inspection and approval: Stream authentication, request and response + * interception. The first two can only be accepted (=forward to main RPC + * server) or denied (=return error to client). Intercepted responses can also + * be replaced/overwritten. + * * @generated from protobuf oneof: intercept_type */ interceptType: { @@ -7266,7 +7537,7 @@ export interface RPCMiddlewareRequest { * must handle the macaroon authentication in the request interception to * avoid an additional message round trip between lnd and the middleware. * - * @generated from protobuf field: lnrpc.StreamAuth stream_auth = 4; + * @generated from protobuf field: lnrpc.StreamAuth stream_auth = 4 */ streamAuth: StreamAuth; } | { @@ -7278,7 +7549,7 @@ export interface RPCMiddlewareRequest { * inspection. For unary RPC messages the middleware is also expected to * validate the custom macaroon caveat of the request. * - * @generated from protobuf field: lnrpc.RPCMessage request = 5; + * @generated from protobuf field: lnrpc.RPCMessage request = 5 */ request: RPCMessage; } | { @@ -7292,7 +7563,7 @@ export interface RPCMiddlewareRequest { * (=forwarded to the client), replaced/overwritten with a new message of * the same type, or replaced by an error message. * - * @generated from protobuf field: lnrpc.RPCMessage response = 6; + * @generated from protobuf field: lnrpc.RPCMessage response = 6 */ response: RPCMessage; } | { @@ -7304,7 +7575,7 @@ export interface RPCMiddlewareRequest { * that the server sends to the client after the client sends the server * the middleware registration message. * - * @generated from protobuf field: bool reg_complete = 8; + * @generated from protobuf field: bool reg_complete = 8 */ regComplete: boolean; } | { @@ -7319,9 +7590,34 @@ export interface RPCMiddlewareRequest { * must be referenced when responding (accepting/rejecting/modifying) to an * intercept message. * - * @generated from protobuf field: uint64 msg_id = 7; + * @generated from protobuf field: uint64 msg_id = 7 */ msgId: bigint; + /** + * + * The metadata pairs that were sent along with the original gRPC request via + * the golang context.Context using explicit [gRPC + * metadata](https://grpc.io/docs/guides/metadata/). Context values are not + * propagated via gRPC and so we send any pairs along explicitly here so that + * the interceptor can access them. + * + * @generated from protobuf field: map metadata_pairs = 9 + */ + metadataPairs: { + [key: string]: MetadataValues; + }; +} +/** + * @generated from protobuf message lnrpc.MetadataValues + */ +export interface MetadataValues { + /** + * + * The set of metadata values that correspond to the metadata key. + * + * @generated from protobuf field: repeated string values = 1 + */ + values: string[]; } /** * @generated from protobuf message lnrpc.StreamAuth @@ -7333,7 +7629,7 @@ export interface StreamAuth { * example /lnrpc.Lightning/GetInfo) of the streaming RPC method that was just * established. * - * @generated from protobuf field: string method_full_uri = 1; + * @generated from protobuf field: string method_full_uri = 1 */ methodFullUri: string; } @@ -7347,14 +7643,14 @@ export interface RPCMessage { * example /lnrpc.Lightning/GetInfo) of the RPC method the message was sent * to/from. * - * @generated from protobuf field: string method_full_uri = 1; + * @generated from protobuf field: string method_full_uri = 1 */ methodFullUri: string; /** * * Indicates whether the message was sent over a streaming RPC method or not. * - * @generated from protobuf field: bool stream_rpc = 2; + * @generated from protobuf field: bool stream_rpc = 2 */ streamRpc: boolean; /** @@ -7363,7 +7659,7 @@ export interface RPCMessage { * .TypeName, for example lnrpc.GetInfoRequest). In case of an * error being returned from lnd, this simply contains the string "error". * - * @generated from protobuf field: string type_name = 3; + * @generated from protobuf field: string type_name = 3 */ typeName: string; /** @@ -7371,7 +7667,7 @@ export interface RPCMessage { * The full content of the gRPC message, serialized in the binary protobuf * format. * - * @generated from protobuf field: bytes serialized = 4; + * @generated from protobuf field: bytes serialized = 4 */ serialized: Uint8Array; /** @@ -7380,7 +7676,7 @@ export interface RPCMessage { * this is set to true then the type_name contains the string "error" and * serialized contains the error string. * - * @generated from protobuf field: bool is_error = 5; + * @generated from protobuf field: bool is_error = 5 */ isError: boolean; } @@ -7394,10 +7690,15 @@ export interface RPCMiddlewareResponse { * giving feedback to an intercept but is ignored for the initial registration * message. * - * @generated from protobuf field: uint64 ref_msg_id = 1; + * @generated from protobuf field: uint64 ref_msg_id = 1 */ refMsgId: bigint; /** + * + * The middleware can only send two types of messages to lnd: The initial + * registration message that identifies the middleware and after that only + * feedback messages to requests sent to the middleware. + * * @generated from protobuf oneof: middleware_message */ middlewareMessage: { @@ -7414,7 +7715,7 @@ export interface RPCMiddlewareResponse { * measure, _no_ middleware can intercept requests made with _unencumbered_ * macaroons! * - * @generated from protobuf field: lnrpc.MiddlewareRegistration register = 2; + * @generated from protobuf field: lnrpc.MiddlewareRegistration register = 2 */ register: MiddlewareRegistration; } | { @@ -7424,7 +7725,7 @@ export interface RPCMiddlewareResponse { * The middleware received an interception request and gives feedback to * it. The request_id indicates what message the feedback refers to. * - * @generated from protobuf field: lnrpc.InterceptFeedback feedback = 3; + * @generated from protobuf field: lnrpc.InterceptFeedback feedback = 3 */ feedback: InterceptFeedback; } | { @@ -7440,7 +7741,7 @@ export interface MiddlewareRegistration { * The name of the middleware to register. The name should be as informative * as possible and is logged on registration. * - * @generated from protobuf field: string middleware_name = 1; + * @generated from protobuf field: string middleware_name = 1 */ middlewareName: string; /** @@ -7454,7 +7755,7 @@ export interface MiddlewareRegistration { * change responses to requests made with _unencumbered_ macaroons! * NOTE: Cannot be used at the same time as read_only_mode. * - * @generated from protobuf field: string custom_macaroon_caveat_name = 2; + * @generated from protobuf field: string custom_macaroon_caveat_name = 2 */ customMacaroonCaveatName: string; /** @@ -7465,7 +7766,7 @@ export interface MiddlewareRegistration { * the responses. * NOTE: Cannot be used at the same time as custom_macaroon_caveat_name. * - * @generated from protobuf field: bool read_only_mode = 3; + * @generated from protobuf field: bool read_only_mode = 3 */ readOnlyMode: boolean; } @@ -7480,7 +7781,7 @@ export interface InterceptFeedback { * this value is empty, it means the middleware accepts the stream/request/ * response and the processing of it can continue. * - * @generated from protobuf field: string error = 1; + * @generated from protobuf field: string error = 1 */ error: string; /** @@ -7490,7 +7791,7 @@ export interface InterceptFeedback { * a 0-length or nil byte slice and we wouldn't be able to distinguish between * an empty replacement message and the "don't replace anything" case. * - * @generated from protobuf field: bool replace_response = 2; + * @generated from protobuf field: bool replace_response = 2 */ replaceResponse: boolean; /** @@ -7498,7 +7799,7 @@ export interface InterceptFeedback { * If the replace_response field is set to true, this field must contain the * binary serialized gRPC message in the protobuf format. * - * @generated from protobuf field: bytes replacement_serialized = 3; + * @generated from protobuf field: bytes replacement_serialized = 3 */ replacementSerialized: Uint8Array; } @@ -7657,11 +7958,22 @@ export enum CommitmentType { */ SCRIPT_ENFORCED_LEASE = 4, /** - * TODO(roasbeef): need script enforce mirror type for the above as well? + * + * A channel that uses musig2 for the funding output, and the new tapscript + * features where relevant. * * @generated from protobuf enum value: SIMPLE_TAPROOT = 5; */ - SIMPLE_TAPROOT = 5 + SIMPLE_TAPROOT = 5, + /** + * + * Identical to the SIMPLE_TAPROOT channel type, but with extra functionality. + * This channel type also commits to additional meta data in the tapscript + * leaves for the scripts in a channel. + * + * @generated from protobuf enum value: SIMPLE_TAPROOT_OVERLAY = 6; + */ + SIMPLE_TAPROOT_OVERLAY = 6 } /** * @generated from protobuf enum lnrpc.Initiator @@ -8004,8 +8316,9 @@ class LookupHtlcResolutionRequest$Type extends MessageType): LookupHtlcResolutionRequest { - const message = { chanId: 0n, htlcIndex: 0n }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.chanId = 0n; + message.htlcIndex = 0n; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -8058,8 +8371,9 @@ class LookupHtlcResolutionResponse$Type extends MessageType): LookupHtlcResolutionResponse { - const message = { settled: false, offchain: false }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.settled = false; + message.offchain = false; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -8109,14 +8423,26 @@ class SubscribeCustomMessagesRequest$Type extends MessageType): SubscribeCustomMessagesRequest { - const message = {}; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); if (value !== undefined) reflectionMergePartial(this, message, value); return message; } internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: SubscribeCustomMessagesRequest): SubscribeCustomMessagesRequest { - return target ?? this.create(); + let message = target ?? this.create(), end = reader.pos + length; + while (reader.pos < end) { + let [fieldNo, wireType] = reader.tag(); + switch (fieldNo) { + default: + let u = options.readUnknownField; + if (u === "throw") + throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`); + let d = reader.skip(wireType); + if (u !== false) + (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d); + } + } + return message; } internalBinaryWrite(message: SubscribeCustomMessagesRequest, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter { let u = options.writeUnknownFields; @@ -8139,8 +8465,10 @@ class CustomMessage$Type extends MessageType { ]); } create(value?: PartialMessage): CustomMessage { - const message = { peer: new Uint8Array(0), type: 0, data: new Uint8Array(0) }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.peer = new Uint8Array(0); + message.type = 0; + message.data = new Uint8Array(0); if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -8200,8 +8528,10 @@ class SendCustomMessageRequest$Type extends MessageType): SendCustomMessageRequest { - const message = { peer: new Uint8Array(0), type: 0, data: new Uint8Array(0) }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.peer = new Uint8Array(0); + message.type = 0; + message.data = new Uint8Array(0); if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -8254,19 +8584,40 @@ export const SendCustomMessageRequest = new SendCustomMessageRequest$Type(); // @generated message type with reflection information, may provide speed optimized methods class SendCustomMessageResponse$Type extends MessageType { constructor() { - super("lnrpc.SendCustomMessageResponse", []); + super("lnrpc.SendCustomMessageResponse", [ + { no: 1, name: "status", kind: "scalar", T: 9 /*ScalarType.STRING*/ } + ]); } create(value?: PartialMessage): SendCustomMessageResponse { - const message = {}; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.status = ""; if (value !== undefined) reflectionMergePartial(this, message, value); return message; } internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: SendCustomMessageResponse): SendCustomMessageResponse { - return target ?? this.create(); + let message = target ?? this.create(), end = reader.pos + length; + while (reader.pos < end) { + let [fieldNo, wireType] = reader.tag(); + switch (fieldNo) { + case /* string status */ 1: + message.status = reader.string(); + break; + default: + let u = options.readUnknownField; + if (u === "throw") + throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`); + let d = reader.skip(wireType); + if (u !== false) + (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d); + } + } + return message; } internalBinaryWrite(message: SendCustomMessageResponse, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter { + /* string status = 1; */ + if (message.status !== "") + writer.tag(1, WireType.LengthDelimited).string(message.status); let u = options.writeUnknownFields; if (u !== false) (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer); @@ -8290,8 +8641,12 @@ class Utxo$Type extends MessageType { ]); } create(value?: PartialMessage): Utxo { - const message = { addressType: 0, address: "", amountSat: 0n, pkScript: "", confirmations: 0n }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.addressType = 0; + message.address = ""; + message.amountSat = 0n; + message.pkScript = ""; + message.confirmations = 0n; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -8372,8 +8727,13 @@ class OutputDetail$Type extends MessageType { ]); } create(value?: PartialMessage): OutputDetail { - const message = { outputType: 0, address: "", pkScript: "", outputIndex: 0n, amount: 0n, isOurAddress: false }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.outputType = 0; + message.address = ""; + message.pkScript = ""; + message.outputIndex = 0n; + message.amount = 0n; + message.isOurAddress = false; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -8453,15 +8813,26 @@ class Transaction$Type extends MessageType { { no: 6, name: "time_stamp", kind: "scalar", T: 3 /*ScalarType.INT64*/, L: 0 /*LongType.BIGINT*/ }, { no: 7, name: "total_fees", kind: "scalar", T: 3 /*ScalarType.INT64*/, L: 0 /*LongType.BIGINT*/ }, { no: 8, name: "dest_addresses", kind: "scalar", repeat: 2 /*RepeatType.UNPACKED*/, T: 9 /*ScalarType.STRING*/ }, - { no: 11, name: "output_details", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => OutputDetail }, + { no: 11, name: "output_details", kind: "message", repeat: 2 /*RepeatType.UNPACKED*/, T: () => OutputDetail }, { no: 9, name: "raw_tx_hex", kind: "scalar", T: 9 /*ScalarType.STRING*/ }, { no: 10, name: "label", kind: "scalar", T: 9 /*ScalarType.STRING*/ }, - { no: 12, name: "previous_outpoints", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => PreviousOutPoint } + { no: 12, name: "previous_outpoints", kind: "message", repeat: 2 /*RepeatType.UNPACKED*/, T: () => PreviousOutPoint } ]); } create(value?: PartialMessage): Transaction { - const message = { txHash: "", amount: 0n, numConfirmations: 0, blockHash: "", blockHeight: 0, timeStamp: 0n, totalFees: 0n, destAddresses: [], outputDetails: [], rawTxHex: "", label: "", previousOutpoints: [] }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.txHash = ""; + message.amount = 0n; + message.numConfirmations = 0; + message.blockHash = ""; + message.blockHeight = 0; + message.timeStamp = 0n; + message.totalFees = 0n; + message.destAddresses = []; + message.outputDetails = []; + message.rawTxHex = ""; + message.label = ""; + message.previousOutpoints = []; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -8492,7 +8863,7 @@ class Transaction$Type extends MessageType { case /* int64 total_fees */ 7: message.totalFees = reader.int64().toBigInt(); break; - case /* repeated string dest_addresses = 8 [deprecated = true];*/ 8: + case /* repeated string dest_addresses = 8 [deprecated = true] */ 8: message.destAddresses.push(reader.string()); break; case /* repeated lnrpc.OutputDetail output_details */ 11: @@ -8543,15 +8914,15 @@ class Transaction$Type extends MessageType { /* repeated string dest_addresses = 8 [deprecated = true]; */ for (let i = 0; i < message.destAddresses.length; i++) writer.tag(8, WireType.LengthDelimited).string(message.destAddresses[i]); - /* repeated lnrpc.OutputDetail output_details = 11; */ - for (let i = 0; i < message.outputDetails.length; i++) - OutputDetail.internalBinaryWrite(message.outputDetails[i], writer.tag(11, WireType.LengthDelimited).fork(), options).join(); /* string raw_tx_hex = 9; */ if (message.rawTxHex !== "") writer.tag(9, WireType.LengthDelimited).string(message.rawTxHex); /* string label = 10; */ if (message.label !== "") writer.tag(10, WireType.LengthDelimited).string(message.label); + /* repeated lnrpc.OutputDetail output_details = 11; */ + for (let i = 0; i < message.outputDetails.length; i++) + OutputDetail.internalBinaryWrite(message.outputDetails[i], writer.tag(11, WireType.LengthDelimited).fork(), options).join(); /* repeated lnrpc.PreviousOutPoint previous_outpoints = 12; */ for (let i = 0; i < message.previousOutpoints.length; i++) PreviousOutPoint.internalBinaryWrite(message.previousOutpoints[i], writer.tag(12, WireType.LengthDelimited).fork(), options).join(); @@ -8571,12 +8942,18 @@ class GetTransactionsRequest$Type extends MessageType { super("lnrpc.GetTransactionsRequest", [ { no: 1, name: "start_height", kind: "scalar", T: 5 /*ScalarType.INT32*/ }, { no: 2, name: "end_height", kind: "scalar", T: 5 /*ScalarType.INT32*/ }, - { no: 3, name: "account", kind: "scalar", T: 9 /*ScalarType.STRING*/ } + { no: 3, name: "account", kind: "scalar", T: 9 /*ScalarType.STRING*/ }, + { no: 4, name: "index_offset", kind: "scalar", T: 13 /*ScalarType.UINT32*/ }, + { no: 5, name: "max_transactions", kind: "scalar", T: 13 /*ScalarType.UINT32*/ } ]); } create(value?: PartialMessage): GetTransactionsRequest { - const message = { startHeight: 0, endHeight: 0, account: "" }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.startHeight = 0; + message.endHeight = 0; + message.account = ""; + message.indexOffset = 0; + message.maxTransactions = 0; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -8595,6 +8972,12 @@ class GetTransactionsRequest$Type extends MessageType { case /* string account */ 3: message.account = reader.string(); break; + case /* uint32 index_offset */ 4: + message.indexOffset = reader.uint32(); + break; + case /* uint32 max_transactions */ 5: + message.maxTransactions = reader.uint32(); + break; default: let u = options.readUnknownField; if (u === "throw") @@ -8616,6 +8999,12 @@ class GetTransactionsRequest$Type extends MessageType { /* string account = 3; */ if (message.account !== "") writer.tag(3, WireType.LengthDelimited).string(message.account); + /* uint32 index_offset = 4; */ + if (message.indexOffset !== 0) + writer.tag(4, WireType.Varint).uint32(message.indexOffset); + /* uint32 max_transactions = 5; */ + if (message.maxTransactions !== 0) + writer.tag(5, WireType.Varint).uint32(message.maxTransactions); let u = options.writeUnknownFields; if (u !== false) (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer); @@ -8630,12 +9019,16 @@ export const GetTransactionsRequest = new GetTransactionsRequest$Type(); class TransactionDetails$Type extends MessageType { constructor() { super("lnrpc.TransactionDetails", [ - { no: 1, name: "transactions", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => Transaction } + { no: 1, name: "transactions", kind: "message", repeat: 2 /*RepeatType.UNPACKED*/, T: () => Transaction }, + { no: 2, name: "last_index", kind: "scalar", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ }, + { no: 3, name: "first_index", kind: "scalar", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ } ]); } create(value?: PartialMessage): TransactionDetails { - const message = { transactions: [] }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.transactions = []; + message.lastIndex = 0n; + message.firstIndex = 0n; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -8648,6 +9041,12 @@ class TransactionDetails$Type extends MessageType { case /* repeated lnrpc.Transaction transactions */ 1: message.transactions.push(Transaction.internalBinaryRead(reader, reader.uint32(), options)); break; + case /* uint64 last_index */ 2: + message.lastIndex = reader.uint64().toBigInt(); + break; + case /* uint64 first_index */ 3: + message.firstIndex = reader.uint64().toBigInt(); + break; default: let u = options.readUnknownField; if (u === "throw") @@ -8663,6 +9062,12 @@ class TransactionDetails$Type extends MessageType { /* repeated lnrpc.Transaction transactions = 1; */ for (let i = 0; i < message.transactions.length; i++) Transaction.internalBinaryWrite(message.transactions[i], writer.tag(1, WireType.LengthDelimited).fork(), options).join(); + /* uint64 last_index = 2; */ + if (message.lastIndex !== 0n) + writer.tag(2, WireType.Varint).uint64(message.lastIndex); + /* uint64 first_index = 3; */ + if (message.firstIndex !== 0n) + writer.tag(3, WireType.Varint).uint64(message.firstIndex); let u = options.writeUnknownFields; if (u !== false) (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer); @@ -8683,8 +9088,8 @@ class FeeLimit$Type extends MessageType { ]); } create(value?: PartialMessage): FeeLimit { - const message = { limit: { oneofKind: undefined } }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.limit = { oneofKind: undefined }; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -8727,12 +9132,12 @@ class FeeLimit$Type extends MessageType { /* int64 fixed = 1; */ if (message.limit.oneofKind === "fixed") writer.tag(1, WireType.Varint).int64(message.limit.fixed); - /* int64 fixed_msat = 3; */ - if (message.limit.oneofKind === "fixedMsat") - writer.tag(3, WireType.Varint).int64(message.limit.fixedMsat); /* int64 percent = 2; */ if (message.limit.oneofKind === "percent") writer.tag(2, WireType.Varint).int64(message.limit.percent); + /* int64 fixed_msat = 3; */ + if (message.limit.oneofKind === "fixedMsat") + writer.tag(3, WireType.Varint).int64(message.limit.fixedMsat); let u = options.writeUnknownFields; if (u !== false) (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer); @@ -8766,8 +9171,22 @@ class SendRequest$Type extends MessageType { ]); } create(value?: PartialMessage): SendRequest { - const message = { dest: new Uint8Array(0), destString: "", amt: 0n, amtMsat: 0n, paymentHash: new Uint8Array(0), paymentHashString: "", paymentRequest: "", finalCltvDelta: 0, outgoingChanId: "0", lastHopPubkey: new Uint8Array(0), cltvLimit: 0, destCustomRecords: {}, allowSelfPayment: false, destFeatures: [], paymentAddr: new Uint8Array(0) }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.dest = new Uint8Array(0); + message.destString = ""; + message.amt = 0n; + message.amtMsat = 0n; + message.paymentHash = new Uint8Array(0); + message.paymentHashString = ""; + message.paymentRequest = ""; + message.finalCltvDelta = 0; + message.outgoingChanId = "0"; + message.lastHopPubkey = new Uint8Array(0); + message.cltvLimit = 0; + message.destCustomRecords = {}; + message.allowSelfPayment = false; + message.destFeatures = []; + message.paymentAddr = new Uint8Array(0); if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -8780,7 +9199,7 @@ class SendRequest$Type extends MessageType { case /* bytes dest */ 1: message.dest = reader.bytes(); break; - case /* string dest_string = 2 [deprecated = true];*/ 2: + case /* string dest_string = 2 [deprecated = true] */ 2: message.destString = reader.string(); break; case /* int64 amt */ 3: @@ -8792,7 +9211,7 @@ class SendRequest$Type extends MessageType { case /* bytes payment_hash */ 4: message.paymentHash = reader.bytes(); break; - case /* string payment_hash_string = 5 [deprecated = true];*/ 5: + case /* string payment_hash_string = 5 [deprecated = true] */ 5: message.paymentHashString = reader.string(); break; case /* string payment_request */ 6: @@ -8804,7 +9223,7 @@ class SendRequest$Type extends MessageType { case /* lnrpc.FeeLimit fee_limit */ 8: message.feeLimit = FeeLimit.internalBinaryRead(reader, reader.uint32(), options, message.feeLimit); break; - case /* uint64 outgoing_chan_id = 9 [jstype = JS_STRING];*/ 9: + case /* uint64 outgoing_chan_id = 9 [jstype = JS_STRING] */ 9: message.outgoingChanId = reader.uint64().toString(); break; case /* bytes last_hop_pubkey */ 13: @@ -8851,7 +9270,7 @@ class SendRequest$Type extends MessageType { case 2: val = reader.bytes(); break; - default: throw new globalThis.Error("unknown map entry field for field lnrpc.SendRequest.dest_custom_records"); + default: throw new globalThis.Error("unknown map entry field for lnrpc.SendRequest.dest_custom_records"); } } map[key ?? "0"] = val ?? new Uint8Array(0); @@ -8866,9 +9285,6 @@ class SendRequest$Type extends MessageType { /* int64 amt = 3; */ if (message.amt !== 0n) writer.tag(3, WireType.Varint).int64(message.amt); - /* int64 amt_msat = 12; */ - if (message.amtMsat !== 0n) - writer.tag(12, WireType.Varint).int64(message.amtMsat); /* bytes payment_hash = 4; */ if (message.paymentHash.length) writer.tag(4, WireType.LengthDelimited).bytes(message.paymentHash); @@ -8887,15 +9303,18 @@ class SendRequest$Type extends MessageType { /* uint64 outgoing_chan_id = 9 [jstype = JS_STRING]; */ if (message.outgoingChanId !== "0") writer.tag(9, WireType.Varint).uint64(message.outgoingChanId); - /* bytes last_hop_pubkey = 13; */ - if (message.lastHopPubkey.length) - writer.tag(13, WireType.LengthDelimited).bytes(message.lastHopPubkey); /* uint32 cltv_limit = 10; */ if (message.cltvLimit !== 0) writer.tag(10, WireType.Varint).uint32(message.cltvLimit); /* map dest_custom_records = 11; */ - for (let k of Object.keys(message.destCustomRecords)) + for (let k of globalThis.Object.keys(message.destCustomRecords)) writer.tag(11, WireType.LengthDelimited).fork().tag(1, WireType.Varint).uint64(k).tag(2, WireType.LengthDelimited).bytes(message.destCustomRecords[k]).join(); + /* int64 amt_msat = 12; */ + if (message.amtMsat !== 0n) + writer.tag(12, WireType.Varint).int64(message.amtMsat); + /* bytes last_hop_pubkey = 13; */ + if (message.lastHopPubkey.length) + writer.tag(13, WireType.LengthDelimited).bytes(message.lastHopPubkey); /* bool allow_self_payment = 14; */ if (message.allowSelfPayment !== false) writer.tag(14, WireType.Varint).bool(message.allowSelfPayment); @@ -8930,8 +9349,10 @@ class SendResponse$Type extends MessageType { ]); } create(value?: PartialMessage): SendResponse { - const message = { paymentError: "", paymentPreimage: new Uint8Array(0), paymentHash: new Uint8Array(0) }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.paymentError = ""; + message.paymentPreimage = new Uint8Array(0); + message.paymentHash = new Uint8Array(0); if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -8997,8 +9418,9 @@ class SendToRouteRequest$Type extends MessageType { ]); } create(value?: PartialMessage): SendToRouteRequest { - const message = { paymentHash: new Uint8Array(0), paymentHashString: "" }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.paymentHash = new Uint8Array(0); + message.paymentHashString = ""; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -9011,7 +9433,7 @@ class SendToRouteRequest$Type extends MessageType { case /* bytes payment_hash */ 1: message.paymentHash = reader.bytes(); break; - case /* string payment_hash_string = 2 [deprecated = true];*/ 2: + case /* string payment_hash_string = 2 [deprecated = true] */ 2: message.paymentHashString = reader.string(); break; case /* lnrpc.Route route */ 4: @@ -9071,8 +9493,23 @@ class ChannelAcceptRequest$Type extends MessageType { ]); } create(value?: PartialMessage): ChannelAcceptRequest { - const message = { nodePubkey: new Uint8Array(0), chainHash: new Uint8Array(0), pendingChanId: new Uint8Array(0), fundingAmt: 0n, pushAmt: 0n, dustLimit: 0n, maxValueInFlight: 0n, channelReserve: 0n, minHtlc: 0n, feePerKw: 0n, csvDelay: 0, maxAcceptedHtlcs: 0, channelFlags: 0, commitmentType: 0, wantsZeroConf: false, wantsScidAlias: false }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.nodePubkey = new Uint8Array(0); + message.chainHash = new Uint8Array(0); + message.pendingChanId = new Uint8Array(0); + message.fundingAmt = 0n; + message.pushAmt = 0n; + message.dustLimit = 0n; + message.maxValueInFlight = 0n; + message.channelReserve = 0n; + message.minHtlc = 0n; + message.feePerKw = 0n; + message.csvDelay = 0; + message.maxAcceptedHtlcs = 0; + message.channelFlags = 0; + message.commitmentType = 0; + message.wantsZeroConf = false; + message.wantsScidAlias = false; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -9218,8 +9655,18 @@ class ChannelAcceptResponse$Type extends MessageType { ]); } create(value?: PartialMessage): ChannelAcceptResponse { - const message = { accept: false, pendingChanId: new Uint8Array(0), error: "", upfrontShutdown: "", csvDelay: 0, reserveSat: 0n, inFlightMaxMsat: 0n, maxHtlcCount: 0, minHtlcIn: 0n, minAcceptDepth: 0, zeroConf: false }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.accept = false; + message.pendingChanId = new Uint8Array(0); + message.error = ""; + message.upfrontShutdown = ""; + message.csvDelay = 0; + message.reserveSat = 0n; + message.inFlightMaxMsat = 0n; + message.maxHtlcCount = 0; + message.minHtlcIn = 0n; + message.minAcceptDepth = 0; + message.zeroConf = false; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -9327,8 +9774,9 @@ class ChannelPoint$Type extends MessageType { ]); } create(value?: PartialMessage): ChannelPoint { - const message = { fundingTxid: { oneofKind: undefined }, outputIndex: 0 }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.fundingTxid = { oneofKind: undefined }; + message.outputIndex = 0; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -9394,8 +9842,10 @@ class OutPoint$Type extends MessageType { ]); } create(value?: PartialMessage): OutPoint { - const message = { txidBytes: new Uint8Array(0), txidStr: "", outputIndex: 0 }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.txidBytes = new Uint8Array(0); + message.txidStr = ""; + message.outputIndex = 0; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -9454,8 +9904,9 @@ class PreviousOutPoint$Type extends MessageType { ]); } create(value?: PartialMessage): PreviousOutPoint { - const message = { outpoint: "", isOurOutput: false }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.outpoint = ""; + message.isOurOutput = false; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -9508,8 +9959,9 @@ class LightningAddress$Type extends MessageType { ]); } create(value?: PartialMessage): LightningAddress { - const message = { pubkey: "", host: "" }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.pubkey = ""; + message.host = ""; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -9565,8 +10017,12 @@ class EstimateFeeRequest$Type extends MessageType { ]); } create(value?: PartialMessage): EstimateFeeRequest { - const message = { addrToAmount: {}, targetConf: 0, minConfs: 0, spendUnconfirmed: false, coinSelectionStrategy: 0 }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.addrToAmount = {}; + message.targetConf = 0; + message.minConfs = 0; + message.spendUnconfirmed = false; + message.coinSelectionStrategy = 0; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -9576,7 +10032,7 @@ class EstimateFeeRequest$Type extends MessageType { while (reader.pos < end) { let [fieldNo, wireType] = reader.tag(); switch (fieldNo) { - case /* map AddrToAmount = 1 [json_name = "AddrToAmount"];*/ 1: + case /* map AddrToAmount */ 1: this.binaryReadMap1(message.addrToAmount, reader, options); break; case /* int32 target_conf */ 2: @@ -9613,14 +10069,14 @@ class EstimateFeeRequest$Type extends MessageType { case 2: val = reader.int64().toBigInt(); break; - default: throw new globalThis.Error("unknown map entry field for field lnrpc.EstimateFeeRequest.AddrToAmount"); + default: throw new globalThis.Error("unknown map entry field for lnrpc.EstimateFeeRequest.AddrToAmount"); } } map[key ?? ""] = val ?? 0n; } internalBinaryWrite(message: EstimateFeeRequest, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter { - /* map AddrToAmount = 1 [json_name = "AddrToAmount"]; */ - for (let k of Object.keys(message.addrToAmount)) + /* map AddrToAmount = 1; */ + for (let k of globalThis.Object.keys(message.addrToAmount)) writer.tag(1, WireType.LengthDelimited).fork().tag(1, WireType.LengthDelimited).string(k).tag(2, WireType.Varint).int64(message.addrToAmount[k]).join(); /* int32 target_conf = 2; */ if (message.targetConf !== 0) @@ -9654,8 +10110,10 @@ class EstimateFeeResponse$Type extends MessageType { ]); } create(value?: PartialMessage): EstimateFeeResponse { - const message = { feeSat: 0n, feerateSatPerByte: 0n, satPerVbyte: 0n }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.feeSat = 0n; + message.feerateSatPerByte = 0n; + message.satPerVbyte = 0n; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -9668,7 +10126,7 @@ class EstimateFeeResponse$Type extends MessageType { case /* int64 fee_sat */ 1: message.feeSat = reader.int64().toBigInt(); break; - case /* int64 feerate_sat_per_byte = 2 [deprecated = true];*/ 2: + case /* int64 feerate_sat_per_byte = 2 [deprecated = true] */ 2: message.feerateSatPerByte = reader.int64().toBigInt(); break; case /* uint64 sat_per_vbyte */ 3: @@ -9720,8 +10178,15 @@ class SendManyRequest$Type extends MessageType { ]); } create(value?: PartialMessage): SendManyRequest { - const message = { addrToAmount: {}, targetConf: 0, satPerVbyte: 0n, satPerByte: 0n, label: "", minConfs: 0, spendUnconfirmed: false, coinSelectionStrategy: 0 }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.addrToAmount = {}; + message.targetConf = 0; + message.satPerVbyte = 0n; + message.satPerByte = 0n; + message.label = ""; + message.minConfs = 0; + message.spendUnconfirmed = false; + message.coinSelectionStrategy = 0; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -9731,7 +10196,7 @@ class SendManyRequest$Type extends MessageType { while (reader.pos < end) { let [fieldNo, wireType] = reader.tag(); switch (fieldNo) { - case /* map AddrToAmount = 1 [json_name = "AddrToAmount"];*/ 1: + case /* map AddrToAmount */ 1: this.binaryReadMap1(message.addrToAmount, reader, options); break; case /* int32 target_conf */ 3: @@ -9740,7 +10205,7 @@ class SendManyRequest$Type extends MessageType { case /* uint64 sat_per_vbyte */ 4: message.satPerVbyte = reader.uint64().toBigInt(); break; - case /* int64 sat_per_byte = 5 [deprecated = true];*/ 5: + case /* int64 sat_per_byte = 5 [deprecated = true] */ 5: message.satPerByte = reader.int64().toBigInt(); break; case /* string label */ 6: @@ -9777,14 +10242,14 @@ class SendManyRequest$Type extends MessageType { case 2: val = reader.int64().toBigInt(); break; - default: throw new globalThis.Error("unknown map entry field for field lnrpc.SendManyRequest.AddrToAmount"); + default: throw new globalThis.Error("unknown map entry field for lnrpc.SendManyRequest.AddrToAmount"); } } map[key ?? ""] = val ?? 0n; } internalBinaryWrite(message: SendManyRequest, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter { - /* map AddrToAmount = 1 [json_name = "AddrToAmount"]; */ - for (let k of Object.keys(message.addrToAmount)) + /* map AddrToAmount = 1; */ + for (let k of globalThis.Object.keys(message.addrToAmount)) writer.tag(1, WireType.LengthDelimited).fork().tag(1, WireType.LengthDelimited).string(k).tag(2, WireType.Varint).int64(message.addrToAmount[k]).join(); /* int32 target_conf = 3; */ if (message.targetConf !== 0) @@ -9825,8 +10290,8 @@ class SendManyResponse$Type extends MessageType { ]); } create(value?: PartialMessage): SendManyResponse { - const message = { txid: "" }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.txid = ""; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -9878,12 +10343,22 @@ class SendCoinsRequest$Type extends MessageType { { no: 8, name: "min_confs", kind: "scalar", T: 5 /*ScalarType.INT32*/ }, { no: 9, name: "spend_unconfirmed", kind: "scalar", T: 8 /*ScalarType.BOOL*/ }, { no: 10, name: "coin_selection_strategy", kind: "enum", T: () => ["lnrpc.CoinSelectionStrategy", CoinSelectionStrategy] }, - { no: 11, name: "outpoints", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => OutPoint } + { no: 11, name: "outpoints", kind: "message", repeat: 2 /*RepeatType.UNPACKED*/, T: () => OutPoint } ]); } create(value?: PartialMessage): SendCoinsRequest { - const message = { addr: "", amount: 0n, targetConf: 0, satPerVbyte: 0n, satPerByte: 0n, sendAll: false, label: "", minConfs: 0, spendUnconfirmed: false, coinSelectionStrategy: 0, outpoints: [] }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.addr = ""; + message.amount = 0n; + message.targetConf = 0; + message.satPerVbyte = 0n; + message.satPerByte = 0n; + message.sendAll = false; + message.label = ""; + message.minConfs = 0; + message.spendUnconfirmed = false; + message.coinSelectionStrategy = 0; + message.outpoints = []; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -9905,7 +10380,7 @@ class SendCoinsRequest$Type extends MessageType { case /* uint64 sat_per_vbyte */ 4: message.satPerVbyte = reader.uint64().toBigInt(); break; - case /* int64 sat_per_byte = 5 [deprecated = true];*/ 5: + case /* int64 sat_per_byte = 5 [deprecated = true] */ 5: message.satPerByte = reader.int64().toBigInt(); break; case /* bool send_all */ 6: @@ -9989,8 +10464,8 @@ class SendCoinsResponse$Type extends MessageType { ]); } create(value?: PartialMessage): SendCoinsResponse { - const message = { txid: "" }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.txid = ""; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -10038,8 +10513,10 @@ class ListUnspentRequest$Type extends MessageType { ]); } create(value?: PartialMessage): ListUnspentRequest { - const message = { minConfs: 0, maxConfs: 0, account: "" }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.minConfs = 0; + message.maxConfs = 0; + message.account = ""; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -10093,12 +10570,12 @@ export const ListUnspentRequest = new ListUnspentRequest$Type(); class ListUnspentResponse$Type extends MessageType { constructor() { super("lnrpc.ListUnspentResponse", [ - { no: 1, name: "utxos", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => Utxo } + { no: 1, name: "utxos", kind: "message", repeat: 2 /*RepeatType.UNPACKED*/, T: () => Utxo } ]); } create(value?: PartialMessage): ListUnspentResponse { - const message = { utxos: [] }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.utxos = []; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -10145,8 +10622,9 @@ class NewAddressRequest$Type extends MessageType { ]); } create(value?: PartialMessage): NewAddressRequest { - const message = { type: 0, account: "" }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.type = 0; + message.account = ""; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -10198,8 +10676,8 @@ class NewAddressResponse$Type extends MessageType { ]); } create(value?: PartialMessage): NewAddressResponse { - const message = { address: "" }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.address = ""; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -10246,8 +10724,9 @@ class SignMessageRequest$Type extends MessageType { ]); } create(value?: PartialMessage): SignMessageRequest { - const message = { msg: new Uint8Array(0), singleHash: false }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.msg = new Uint8Array(0); + message.singleHash = false; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -10299,8 +10778,8 @@ class SignMessageResponse$Type extends MessageType { ]); } create(value?: PartialMessage): SignMessageResponse { - const message = { signature: "" }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.signature = ""; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -10347,8 +10826,9 @@ class VerifyMessageRequest$Type extends MessageType { ]); } create(value?: PartialMessage): VerifyMessageRequest { - const message = { msg: new Uint8Array(0), signature: "" }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.msg = new Uint8Array(0); + message.signature = ""; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -10401,8 +10881,9 @@ class VerifyMessageResponse$Type extends MessageType { ]); } create(value?: PartialMessage): VerifyMessageResponse { - const message = { valid: false, pubkey: "" }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.valid = false; + message.pubkey = ""; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -10456,8 +10937,9 @@ class ConnectPeerRequest$Type extends MessageType { ]); } create(value?: PartialMessage): ConnectPeerRequest { - const message = { perm: false, timeout: 0n }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.perm = false; + message.timeout = 0n; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -10510,19 +10992,40 @@ export const ConnectPeerRequest = new ConnectPeerRequest$Type(); // @generated message type with reflection information, may provide speed optimized methods class ConnectPeerResponse$Type extends MessageType { constructor() { - super("lnrpc.ConnectPeerResponse", []); + super("lnrpc.ConnectPeerResponse", [ + { no: 1, name: "status", kind: "scalar", T: 9 /*ScalarType.STRING*/ } + ]); } create(value?: PartialMessage): ConnectPeerResponse { - const message = {}; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.status = ""; if (value !== undefined) reflectionMergePartial(this, message, value); return message; } internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: ConnectPeerResponse): ConnectPeerResponse { - return target ?? this.create(); + let message = target ?? this.create(), end = reader.pos + length; + while (reader.pos < end) { + let [fieldNo, wireType] = reader.tag(); + switch (fieldNo) { + case /* string status */ 1: + message.status = reader.string(); + break; + default: + let u = options.readUnknownField; + if (u === "throw") + throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`); + let d = reader.skip(wireType); + if (u !== false) + (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d); + } + } + return message; } internalBinaryWrite(message: ConnectPeerResponse, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter { + /* string status = 1; */ + if (message.status !== "") + writer.tag(1, WireType.LengthDelimited).string(message.status); let u = options.writeUnknownFields; if (u !== false) (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer); @@ -10541,8 +11044,8 @@ class DisconnectPeerRequest$Type extends MessageType { ]); } create(value?: PartialMessage): DisconnectPeerRequest { - const message = { pubKey: "" }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.pubKey = ""; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -10583,19 +11086,40 @@ export const DisconnectPeerRequest = new DisconnectPeerRequest$Type(); // @generated message type with reflection information, may provide speed optimized methods class DisconnectPeerResponse$Type extends MessageType { constructor() { - super("lnrpc.DisconnectPeerResponse", []); + super("lnrpc.DisconnectPeerResponse", [ + { no: 1, name: "status", kind: "scalar", T: 9 /*ScalarType.STRING*/ } + ]); } create(value?: PartialMessage): DisconnectPeerResponse { - const message = {}; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.status = ""; if (value !== undefined) reflectionMergePartial(this, message, value); return message; } internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: DisconnectPeerResponse): DisconnectPeerResponse { - return target ?? this.create(); + let message = target ?? this.create(), end = reader.pos + length; + while (reader.pos < end) { + let [fieldNo, wireType] = reader.tag(); + switch (fieldNo) { + case /* string status */ 1: + message.status = reader.string(); + break; + default: + let u = options.readUnknownField; + if (u === "throw") + throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`); + let d = reader.skip(wireType); + if (u !== false) + (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d); + } + } + return message; } internalBinaryWrite(message: DisconnectPeerResponse, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter { + /* string status = 1; */ + if (message.status !== "") + writer.tag(1, WireType.LengthDelimited).string(message.status); let u = options.writeUnknownFields; if (u !== false) (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer); @@ -10616,12 +11140,20 @@ class HTLC$Type extends MessageType { { no: 4, name: "expiration_height", kind: "scalar", T: 13 /*ScalarType.UINT32*/ }, { no: 5, name: "htlc_index", kind: "scalar", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ }, { no: 6, name: "forwarding_channel", kind: "scalar", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ }, - { no: 7, name: "forwarding_htlc_index", kind: "scalar", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ } + { no: 7, name: "forwarding_htlc_index", kind: "scalar", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ }, + { no: 8, name: "locked_in", kind: "scalar", T: 8 /*ScalarType.BOOL*/ } ]); } create(value?: PartialMessage): HTLC { - const message = { incoming: false, amount: 0n, hashLock: new Uint8Array(0), expirationHeight: 0, htlcIndex: 0n, forwardingChannel: 0n, forwardingHtlcIndex: 0n }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.incoming = false; + message.amount = 0n; + message.hashLock = new Uint8Array(0); + message.expirationHeight = 0; + message.htlcIndex = 0n; + message.forwardingChannel = 0n; + message.forwardingHtlcIndex = 0n; + message.lockedIn = false; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -10652,6 +11184,9 @@ class HTLC$Type extends MessageType { case /* uint64 forwarding_htlc_index */ 7: message.forwardingHtlcIndex = reader.uint64().toBigInt(); break; + case /* bool locked_in */ 8: + message.lockedIn = reader.bool(); + break; default: let u = options.readUnknownField; if (u === "throw") @@ -10685,6 +11220,9 @@ class HTLC$Type extends MessageType { /* uint64 forwarding_htlc_index = 7; */ if (message.forwardingHtlcIndex !== 0n) writer.tag(7, WireType.Varint).uint64(message.forwardingHtlcIndex); + /* bool locked_in = 8; */ + if (message.lockedIn !== false) + writer.tag(8, WireType.Varint).bool(message.lockedIn); let u = options.writeUnknownFields; if (u !== false) (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer); @@ -10708,8 +11246,13 @@ class ChannelConstraints$Type extends MessageType { ]); } create(value?: PartialMessage): ChannelConstraints { - const message = { csvDelay: 0, chanReserveSat: 0n, dustLimitSat: 0n, maxPendingAmtMsat: 0n, minHtlcMsat: 0n, maxAcceptedHtlcs: 0 }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.csvDelay = 0; + message.chanReserveSat = 0n; + message.dustLimitSat = 0n; + message.maxPendingAmtMsat = 0n; + message.minHtlcMsat = 0n; + message.maxAcceptedHtlcs = 0; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -10795,7 +11338,7 @@ class Channel$Type extends MessageType { { no: 12, name: "total_satoshis_sent", kind: "scalar", T: 3 /*ScalarType.INT64*/, L: 0 /*LongType.BIGINT*/ }, { no: 13, name: "total_satoshis_received", kind: "scalar", T: 3 /*ScalarType.INT64*/, L: 0 /*LongType.BIGINT*/ }, { no: 14, name: "num_updates", kind: "scalar", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ }, - { no: 15, name: "pending_htlcs", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => HTLC }, + { no: 15, name: "pending_htlcs", kind: "message", repeat: 2 /*RepeatType.UNPACKED*/, T: () => HTLC }, { no: 16, name: "csv_delay", kind: "scalar", T: 13 /*ScalarType.UINT32*/ }, { no: 17, name: "private", kind: "scalar", T: 8 /*ScalarType.BOOL*/ }, { no: 18, name: "initiator", kind: "scalar", T: 8 /*ScalarType.BOOL*/ }, @@ -10816,12 +11359,47 @@ class Channel$Type extends MessageType { { no: 33, name: "zero_conf_confirmed_scid", kind: "scalar", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ }, { no: 34, name: "peer_alias", kind: "scalar", T: 9 /*ScalarType.STRING*/ }, { no: 35, name: "peer_scid_alias", kind: "scalar", T: 4 /*ScalarType.UINT64*/ }, - { no: 36, name: "memo", kind: "scalar", T: 9 /*ScalarType.STRING*/ } + { no: 36, name: "memo", kind: "scalar", T: 9 /*ScalarType.STRING*/ }, + { no: 37, name: "custom_channel_data", kind: "scalar", T: 12 /*ScalarType.BYTES*/ } ]); } create(value?: PartialMessage): Channel { - const message = { active: false, remotePubkey: "", channelPoint: "", chanId: "0", capacity: 0n, localBalance: 0n, remoteBalance: 0n, commitFee: 0n, commitWeight: 0n, feePerKw: 0n, unsettledBalance: 0n, totalSatoshisSent: 0n, totalSatoshisReceived: 0n, numUpdates: 0n, pendingHtlcs: [], csvDelay: 0, private: false, initiator: false, chanStatusFlags: "", localChanReserveSat: 0n, remoteChanReserveSat: 0n, staticRemoteKey: false, commitmentType: 0, lifetime: 0n, uptime: 0n, closeAddress: "", pushAmountSat: 0n, thawHeight: 0, aliasScids: [], zeroConf: false, zeroConfConfirmedScid: 0n, peerAlias: "", peerScidAlias: "0", memo: "" }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.active = false; + message.remotePubkey = ""; + message.channelPoint = ""; + message.chanId = "0"; + message.capacity = 0n; + message.localBalance = 0n; + message.remoteBalance = 0n; + message.commitFee = 0n; + message.commitWeight = 0n; + message.feePerKw = 0n; + message.unsettledBalance = 0n; + message.totalSatoshisSent = 0n; + message.totalSatoshisReceived = 0n; + message.numUpdates = 0n; + message.pendingHtlcs = []; + message.csvDelay = 0; + message.private = false; + message.initiator = false; + message.chanStatusFlags = ""; + message.localChanReserveSat = 0n; + message.remoteChanReserveSat = 0n; + message.staticRemoteKey = false; + message.commitmentType = 0; + message.lifetime = 0n; + message.uptime = 0n; + message.closeAddress = ""; + message.pushAmountSat = 0n; + message.thawHeight = 0; + message.aliasScids = []; + message.zeroConf = false; + message.zeroConfConfirmedScid = 0n; + message.peerAlias = ""; + message.peerScidAlias = "0"; + message.memo = ""; + message.customChannelData = new Uint8Array(0); if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -10840,7 +11418,7 @@ class Channel$Type extends MessageType { case /* string channel_point */ 3: message.channelPoint = reader.string(); break; - case /* uint64 chan_id = 4 [jstype = JS_STRING];*/ 4: + case /* uint64 chan_id = 4 [jstype = JS_STRING] */ 4: message.chanId = reader.uint64().toString(); break; case /* int64 capacity */ 5: @@ -10876,7 +11454,7 @@ class Channel$Type extends MessageType { case /* repeated lnrpc.HTLC pending_htlcs */ 15: message.pendingHtlcs.push(HTLC.internalBinaryRead(reader, reader.uint32(), options)); break; - case /* uint32 csv_delay = 16 [deprecated = true];*/ 16: + case /* uint32 csv_delay = 16 [deprecated = true] */ 16: message.csvDelay = reader.uint32(); break; case /* bool private */ 17: @@ -10888,13 +11466,13 @@ class Channel$Type extends MessageType { case /* string chan_status_flags */ 19: message.chanStatusFlags = reader.string(); break; - case /* int64 local_chan_reserve_sat = 20 [deprecated = true];*/ 20: + case /* int64 local_chan_reserve_sat = 20 [deprecated = true] */ 20: message.localChanReserveSat = reader.int64().toBigInt(); break; - case /* int64 remote_chan_reserve_sat = 21 [deprecated = true];*/ 21: + case /* int64 remote_chan_reserve_sat = 21 [deprecated = true] */ 21: message.remoteChanReserveSat = reader.int64().toBigInt(); break; - case /* bool static_remote_key = 22 [deprecated = true];*/ 22: + case /* bool static_remote_key = 22 [deprecated = true] */ 22: message.staticRemoteKey = reader.bool(); break; case /* lnrpc.CommitmentType commitment_type */ 26: @@ -10937,12 +11515,15 @@ class Channel$Type extends MessageType { case /* string peer_alias */ 34: message.peerAlias = reader.string(); break; - case /* uint64 peer_scid_alias = 35 [jstype = JS_STRING];*/ 35: + case /* uint64 peer_scid_alias = 35 [jstype = JS_STRING] */ 35: message.peerScidAlias = reader.uint64().toString(); break; case /* string memo */ 36: message.memo = reader.string(); break; + case /* bytes custom_channel_data */ 37: + message.customChannelData = reader.bytes(); + break; default: let u = options.readUnknownField; if (u === "throw") @@ -11021,9 +11602,6 @@ class Channel$Type extends MessageType { /* bool static_remote_key = 22 [deprecated = true]; */ if (message.staticRemoteKey !== false) writer.tag(22, WireType.Varint).bool(message.staticRemoteKey); - /* lnrpc.CommitmentType commitment_type = 26; */ - if (message.commitmentType !== 0) - writer.tag(26, WireType.Varint).int32(message.commitmentType); /* int64 lifetime = 23; */ if (message.lifetime !== 0n) writer.tag(23, WireType.Varint).int64(message.lifetime); @@ -11033,6 +11611,9 @@ class Channel$Type extends MessageType { /* string close_address = 25; */ if (message.closeAddress !== "") writer.tag(25, WireType.LengthDelimited).string(message.closeAddress); + /* lnrpc.CommitmentType commitment_type = 26; */ + if (message.commitmentType !== 0) + writer.tag(26, WireType.Varint).int32(message.commitmentType); /* uint64 push_amount_sat = 27; */ if (message.pushAmountSat !== 0n) writer.tag(27, WireType.Varint).uint64(message.pushAmountSat); @@ -11067,6 +11648,9 @@ class Channel$Type extends MessageType { /* string memo = 36; */ if (message.memo !== "") writer.tag(36, WireType.LengthDelimited).string(message.memo); + /* bytes custom_channel_data = 37; */ + if (message.customChannelData.length) + writer.tag(37, WireType.LengthDelimited).bytes(message.customChannelData); let u = options.writeUnknownFields; if (u !== false) (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer); @@ -11090,8 +11674,13 @@ class ListChannelsRequest$Type extends MessageType { ]); } create(value?: PartialMessage): ListChannelsRequest { - const message = { activeOnly: false, inactiveOnly: false, publicOnly: false, privateOnly: false, peer: new Uint8Array(0), peerAliasLookup: false }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.activeOnly = false; + message.inactiveOnly = false; + message.publicOnly = false; + message.privateOnly = false; + message.peer = new Uint8Array(0); + message.peerAliasLookup = false; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -11163,12 +11752,12 @@ export const ListChannelsRequest = new ListChannelsRequest$Type(); class ListChannelsResponse$Type extends MessageType { constructor() { super("lnrpc.ListChannelsResponse", [ - { no: 11, name: "channels", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => Channel } + { no: 11, name: "channels", kind: "message", repeat: 2 /*RepeatType.UNPACKED*/, T: () => Channel } ]); } create(value?: PartialMessage): ListChannelsResponse { - const message = { channels: [] }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.channels = []; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -11215,8 +11804,9 @@ class AliasMap$Type extends MessageType { ]); } create(value?: PartialMessage): AliasMap { - const message = { baseScid: 0n, aliases: [] }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.baseScid = 0n; + message.aliases = []; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -11274,14 +11864,26 @@ class ListAliasesRequest$Type extends MessageType { super("lnrpc.ListAliasesRequest", []); } create(value?: PartialMessage): ListAliasesRequest { - const message = {}; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); if (value !== undefined) reflectionMergePartial(this, message, value); return message; } internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: ListAliasesRequest): ListAliasesRequest { - return target ?? this.create(); + let message = target ?? this.create(), end = reader.pos + length; + while (reader.pos < end) { + let [fieldNo, wireType] = reader.tag(); + switch (fieldNo) { + default: + let u = options.readUnknownField; + if (u === "throw") + throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`); + let d = reader.skip(wireType); + if (u !== false) + (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d); + } + } + return message; } internalBinaryWrite(message: ListAliasesRequest, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter { let u = options.writeUnknownFields; @@ -11298,12 +11900,12 @@ export const ListAliasesRequest = new ListAliasesRequest$Type(); class ListAliasesResponse$Type extends MessageType { constructor() { super("lnrpc.ListAliasesResponse", [ - { no: 1, name: "alias_maps", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => AliasMap } + { no: 1, name: "alias_maps", kind: "message", repeat: 2 /*RepeatType.UNPACKED*/, T: () => AliasMap } ]); } create(value?: PartialMessage): ListAliasesResponse { - const message = { aliasMaps: [] }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.aliasMaps = []; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -11357,14 +11959,30 @@ class ChannelCloseSummary$Type extends MessageType { { no: 10, name: "close_type", kind: "enum", T: () => ["lnrpc.ChannelCloseSummary.ClosureType", ChannelCloseSummary_ClosureType] }, { no: 11, name: "open_initiator", kind: "enum", T: () => ["lnrpc.Initiator", Initiator, "INITIATOR_"] }, { no: 12, name: "close_initiator", kind: "enum", T: () => ["lnrpc.Initiator", Initiator, "INITIATOR_"] }, - { no: 13, name: "resolutions", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => Resolution }, + { no: 13, name: "resolutions", kind: "message", repeat: 2 /*RepeatType.UNPACKED*/, T: () => Resolution }, { no: 14, name: "alias_scids", kind: "scalar", repeat: 1 /*RepeatType.PACKED*/, T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ }, - { no: 15, name: "zero_conf_confirmed_scid", kind: "scalar", T: 4 /*ScalarType.UINT64*/ } + { no: 15, name: "zero_conf_confirmed_scid", kind: "scalar", T: 4 /*ScalarType.UINT64*/ }, + { no: 16, name: "custom_channel_data", kind: "scalar", T: 12 /*ScalarType.BYTES*/ } ]); } create(value?: PartialMessage): ChannelCloseSummary { - const message = { channelPoint: "", chanId: "0", chainHash: "", closingTxHash: "", remotePubkey: "", capacity: 0n, closeHeight: 0, settledBalance: 0n, timeLockedBalance: 0n, closeType: 0, openInitiator: 0, closeInitiator: 0, resolutions: [], aliasScids: [], zeroConfConfirmedScid: "0" }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.channelPoint = ""; + message.chanId = "0"; + message.chainHash = ""; + message.closingTxHash = ""; + message.remotePubkey = ""; + message.capacity = 0n; + message.closeHeight = 0; + message.settledBalance = 0n; + message.timeLockedBalance = 0n; + message.closeType = 0; + message.openInitiator = 0; + message.closeInitiator = 0; + message.resolutions = []; + message.aliasScids = []; + message.zeroConfConfirmedScid = "0"; + message.customChannelData = new Uint8Array(0); if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -11377,7 +11995,7 @@ class ChannelCloseSummary$Type extends MessageType { case /* string channel_point */ 1: message.channelPoint = reader.string(); break; - case /* uint64 chan_id = 2 [jstype = JS_STRING];*/ 2: + case /* uint64 chan_id = 2 [jstype = JS_STRING] */ 2: message.chanId = reader.uint64().toString(); break; case /* string chain_hash */ 3: @@ -11420,9 +12038,12 @@ class ChannelCloseSummary$Type extends MessageType { else message.aliasScids.push(reader.uint64().toBigInt()); break; - case /* uint64 zero_conf_confirmed_scid = 15 [jstype = JS_STRING];*/ 15: + case /* uint64 zero_conf_confirmed_scid = 15 [jstype = JS_STRING] */ 15: message.zeroConfConfirmedScid = reader.uint64().toString(); break; + case /* bytes custom_channel_data */ 16: + message.customChannelData = reader.bytes(); + break; default: let u = options.readUnknownField; if (u === "throw") @@ -11484,6 +12105,9 @@ class ChannelCloseSummary$Type extends MessageType { /* uint64 zero_conf_confirmed_scid = 15 [jstype = JS_STRING]; */ if (message.zeroConfConfirmedScid !== "0") writer.tag(15, WireType.Varint).uint64(message.zeroConfConfirmedScid); + /* bytes custom_channel_data = 16; */ + if (message.customChannelData.length) + writer.tag(16, WireType.LengthDelimited).bytes(message.customChannelData); let u = options.writeUnknownFields; if (u !== false) (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer); @@ -11506,8 +12130,11 @@ class Resolution$Type extends MessageType { ]); } create(value?: PartialMessage): Resolution { - const message = { resolutionType: 0, outcome: 0, amountSat: 0n, sweepTxid: "" }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.resolutionType = 0; + message.outcome = 0; + message.amountSat = 0n; + message.sweepTxid = ""; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -11582,8 +12209,13 @@ class ClosedChannelsRequest$Type extends MessageType { ]); } create(value?: PartialMessage): ClosedChannelsRequest { - const message = { cooperative: false, localForce: false, remoteForce: false, breach: false, fundingCanceled: false, abandoned: false }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.cooperative = false; + message.localForce = false; + message.remoteForce = false; + message.breach = false; + message.fundingCanceled = false; + message.abandoned = false; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -11655,12 +12287,12 @@ export const ClosedChannelsRequest = new ClosedChannelsRequest$Type(); class ClosedChannelsResponse$Type extends MessageType { constructor() { super("lnrpc.ClosedChannelsResponse", [ - { no: 1, name: "channels", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => ChannelCloseSummary } + { no: 1, name: "channels", kind: "message", repeat: 2 /*RepeatType.UNPACKED*/, T: () => ChannelCloseSummary } ]); } create(value?: PartialMessage): ClosedChannelsResponse { - const message = { channels: [] }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.channels = []; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -11712,15 +12344,28 @@ class Peer$Type extends MessageType { { no: 9, name: "ping_time", kind: "scalar", T: 3 /*ScalarType.INT64*/, L: 0 /*LongType.BIGINT*/ }, { no: 10, name: "sync_type", kind: "enum", T: () => ["lnrpc.Peer.SyncType", Peer_SyncType] }, { no: 11, name: "features", kind: "map", K: 13 /*ScalarType.UINT32*/, V: { kind: "message", T: () => Feature } }, - { no: 12, name: "errors", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => TimestampedError }, + { no: 12, name: "errors", kind: "message", repeat: 2 /*RepeatType.UNPACKED*/, T: () => TimestampedError }, { no: 13, name: "flap_count", kind: "scalar", T: 5 /*ScalarType.INT32*/ }, { no: 14, name: "last_flap_ns", kind: "scalar", T: 3 /*ScalarType.INT64*/, L: 0 /*LongType.BIGINT*/ }, { no: 15, name: "last_ping_payload", kind: "scalar", T: 12 /*ScalarType.BYTES*/ } ]); } create(value?: PartialMessage): Peer { - const message = { pubKey: "", address: "", bytesSent: 0n, bytesRecv: 0n, satSent: 0n, satRecv: 0n, inbound: false, pingTime: 0n, syncType: 0, features: {}, errors: [], flapCount: 0, lastFlapNs: 0n, lastPingPayload: new Uint8Array(0) }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.pubKey = ""; + message.address = ""; + message.bytesSent = 0n; + message.bytesRecv = 0n; + message.satSent = 0n; + message.satRecv = 0n; + message.inbound = false; + message.pingTime = 0n; + message.syncType = 0; + message.features = {}; + message.errors = []; + message.flapCount = 0; + message.lastFlapNs = 0n; + message.lastPingPayload = new Uint8Array(0); if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -11794,7 +12439,7 @@ class Peer$Type extends MessageType { case 2: val = Feature.internalBinaryRead(reader, reader.uint32(), options); break; - default: throw new globalThis.Error("unknown map entry field for field lnrpc.Peer.features"); + default: throw new globalThis.Error("unknown map entry field for lnrpc.Peer.features"); } } map[key ?? 0] = val ?? Feature.create(); @@ -11828,7 +12473,7 @@ class Peer$Type extends MessageType { if (message.syncType !== 0) writer.tag(10, WireType.Varint).int32(message.syncType); /* map features = 11; */ - for (let k of Object.keys(message.features)) { + for (let k of globalThis.Object.keys(message.features)) { writer.tag(11, WireType.LengthDelimited).fork().tag(1, WireType.Varint).uint32(parseInt(k)); writer.tag(2, WireType.LengthDelimited).fork(); Feature.internalBinaryWrite(message.features[k as any], writer, options); @@ -11865,8 +12510,9 @@ class TimestampedError$Type extends MessageType { ]); } create(value?: PartialMessage): TimestampedError { - const message = { timestamp: 0n, error: "" }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.timestamp = 0n; + message.error = ""; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -11918,8 +12564,8 @@ class ListPeersRequest$Type extends MessageType { ]); } create(value?: PartialMessage): ListPeersRequest { - const message = { latestError: false }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.latestError = false; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -11961,12 +12607,12 @@ export const ListPeersRequest = new ListPeersRequest$Type(); class ListPeersResponse$Type extends MessageType { constructor() { super("lnrpc.ListPeersResponse", [ - { no: 1, name: "peers", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => Peer } + { no: 1, name: "peers", kind: "message", repeat: 2 /*RepeatType.UNPACKED*/, T: () => Peer } ]); } create(value?: PartialMessage): ListPeersResponse { - const message = { peers: [] }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.peers = []; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -12010,14 +12656,26 @@ class PeerEventSubscription$Type extends MessageType { super("lnrpc.PeerEventSubscription", []); } create(value?: PartialMessage): PeerEventSubscription { - const message = {}; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); if (value !== undefined) reflectionMergePartial(this, message, value); return message; } internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: PeerEventSubscription): PeerEventSubscription { - return target ?? this.create(); + let message = target ?? this.create(), end = reader.pos + length; + while (reader.pos < end) { + let [fieldNo, wireType] = reader.tag(); + switch (fieldNo) { + default: + let u = options.readUnknownField; + if (u === "throw") + throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`); + let d = reader.skip(wireType); + if (u !== false) + (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d); + } + } + return message; } internalBinaryWrite(message: PeerEventSubscription, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter { let u = options.writeUnknownFields; @@ -12039,8 +12697,9 @@ class PeerEvent$Type extends MessageType { ]); } create(value?: PartialMessage): PeerEvent { - const message = { pubKey: "", type: 0 }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.pubKey = ""; + message.type = 0; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -12090,14 +12749,26 @@ class GetInfoRequest$Type extends MessageType { super("lnrpc.GetInfoRequest", []); } create(value?: PartialMessage): GetInfoRequest { - const message = {}; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); if (value !== undefined) reflectionMergePartial(this, message, value); return message; } internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: GetInfoRequest): GetInfoRequest { - return target ?? this.create(); + let message = target ?? this.create(), end = reader.pos + length; + while (reader.pos < end) { + let [fieldNo, wireType] = reader.tag(); + switch (fieldNo) { + default: + let u = options.readUnknownField; + if (u === "throw") + throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`); + let d = reader.skip(wireType); + if (u !== false) + (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d); + } + } + return message; } internalBinaryWrite(message: GetInfoRequest, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter { let u = options.writeUnknownFields; @@ -12129,7 +12800,7 @@ class GetInfoResponse$Type extends MessageType { { no: 9, name: "synced_to_chain", kind: "scalar", T: 8 /*ScalarType.BOOL*/ }, { no: 18, name: "synced_to_graph", kind: "scalar", T: 8 /*ScalarType.BOOL*/ }, { no: 10, name: "testnet", kind: "scalar", T: 8 /*ScalarType.BOOL*/ }, - { no: 16, name: "chains", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => Chain }, + { no: 16, name: "chains", kind: "message", repeat: 2 /*RepeatType.UNPACKED*/, T: () => Chain }, { no: 12, name: "uris", kind: "scalar", repeat: 2 /*RepeatType.UNPACKED*/, T: 9 /*ScalarType.STRING*/ }, { no: 19, name: "features", kind: "map", K: 13 /*ScalarType.UINT32*/, V: { kind: "message", T: () => Feature } }, { no: 21, name: "require_htlc_interceptor", kind: "scalar", T: 8 /*ScalarType.BOOL*/ }, @@ -12137,8 +12808,27 @@ class GetInfoResponse$Type extends MessageType { ]); } create(value?: PartialMessage): GetInfoResponse { - const message = { version: "", commitHash: "", identityPubkey: "", alias: "", color: "", numPendingChannels: 0, numActiveChannels: 0, numInactiveChannels: 0, numPeers: 0, blockHeight: 0, blockHash: "", bestHeaderTimestamp: 0n, syncedToChain: false, syncedToGraph: false, testnet: false, chains: [], uris: [], features: {}, requireHtlcInterceptor: false, storeFinalHtlcResolutions: false }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.version = ""; + message.commitHash = ""; + message.identityPubkey = ""; + message.alias = ""; + message.color = ""; + message.numPendingChannels = 0; + message.numActiveChannels = 0; + message.numInactiveChannels = 0; + message.numPeers = 0; + message.blockHeight = 0; + message.blockHash = ""; + message.bestHeaderTimestamp = 0n; + message.syncedToChain = false; + message.syncedToGraph = false; + message.testnet = false; + message.chains = []; + message.uris = []; + message.features = {}; + message.requireHtlcInterceptor = false; + message.storeFinalHtlcResolutions = false; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -12190,7 +12880,7 @@ class GetInfoResponse$Type extends MessageType { case /* bool synced_to_graph */ 18: message.syncedToGraph = reader.bool(); break; - case /* bool testnet = 10 [deprecated = true];*/ 10: + case /* bool testnet = 10 [deprecated = true] */ 10: message.testnet = reader.bool(); break; case /* repeated lnrpc.Chain chains */ 16: @@ -12230,36 +12920,24 @@ class GetInfoResponse$Type extends MessageType { case 2: val = Feature.internalBinaryRead(reader, reader.uint32(), options); break; - default: throw new globalThis.Error("unknown map entry field for field lnrpc.GetInfoResponse.features"); + default: throw new globalThis.Error("unknown map entry field for lnrpc.GetInfoResponse.features"); } } map[key ?? 0] = val ?? Feature.create(); } internalBinaryWrite(message: GetInfoResponse, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter { - /* string version = 14; */ - if (message.version !== "") - writer.tag(14, WireType.LengthDelimited).string(message.version); - /* string commit_hash = 20; */ - if (message.commitHash !== "") - writer.tag(20, WireType.LengthDelimited).string(message.commitHash); /* string identity_pubkey = 1; */ if (message.identityPubkey !== "") writer.tag(1, WireType.LengthDelimited).string(message.identityPubkey); /* string alias = 2; */ if (message.alias !== "") writer.tag(2, WireType.LengthDelimited).string(message.alias); - /* string color = 17; */ - if (message.color !== "") - writer.tag(17, WireType.LengthDelimited).string(message.color); /* uint32 num_pending_channels = 3; */ if (message.numPendingChannels !== 0) writer.tag(3, WireType.Varint).uint32(message.numPendingChannels); /* uint32 num_active_channels = 4; */ if (message.numActiveChannels !== 0) writer.tag(4, WireType.Varint).uint32(message.numActiveChannels); - /* uint32 num_inactive_channels = 15; */ - if (message.numInactiveChannels !== 0) - writer.tag(15, WireType.Varint).uint32(message.numInactiveChannels); /* uint32 num_peers = 5; */ if (message.numPeers !== 0) writer.tag(5, WireType.Varint).uint32(message.numPeers); @@ -12269,31 +12947,43 @@ class GetInfoResponse$Type extends MessageType { /* string block_hash = 8; */ if (message.blockHash !== "") writer.tag(8, WireType.LengthDelimited).string(message.blockHash); - /* int64 best_header_timestamp = 13; */ - if (message.bestHeaderTimestamp !== 0n) - writer.tag(13, WireType.Varint).int64(message.bestHeaderTimestamp); /* bool synced_to_chain = 9; */ if (message.syncedToChain !== false) writer.tag(9, WireType.Varint).bool(message.syncedToChain); - /* bool synced_to_graph = 18; */ - if (message.syncedToGraph !== false) - writer.tag(18, WireType.Varint).bool(message.syncedToGraph); /* bool testnet = 10 [deprecated = true]; */ if (message.testnet !== false) writer.tag(10, WireType.Varint).bool(message.testnet); - /* repeated lnrpc.Chain chains = 16; */ - for (let i = 0; i < message.chains.length; i++) - Chain.internalBinaryWrite(message.chains[i], writer.tag(16, WireType.LengthDelimited).fork(), options).join(); /* repeated string uris = 12; */ for (let i = 0; i < message.uris.length; i++) writer.tag(12, WireType.LengthDelimited).string(message.uris[i]); + /* int64 best_header_timestamp = 13; */ + if (message.bestHeaderTimestamp !== 0n) + writer.tag(13, WireType.Varint).int64(message.bestHeaderTimestamp); + /* string version = 14; */ + if (message.version !== "") + writer.tag(14, WireType.LengthDelimited).string(message.version); + /* uint32 num_inactive_channels = 15; */ + if (message.numInactiveChannels !== 0) + writer.tag(15, WireType.Varint).uint32(message.numInactiveChannels); + /* repeated lnrpc.Chain chains = 16; */ + for (let i = 0; i < message.chains.length; i++) + Chain.internalBinaryWrite(message.chains[i], writer.tag(16, WireType.LengthDelimited).fork(), options).join(); + /* string color = 17; */ + if (message.color !== "") + writer.tag(17, WireType.LengthDelimited).string(message.color); + /* bool synced_to_graph = 18; */ + if (message.syncedToGraph !== false) + writer.tag(18, WireType.Varint).bool(message.syncedToGraph); /* map features = 19; */ - for (let k of Object.keys(message.features)) { + for (let k of globalThis.Object.keys(message.features)) { writer.tag(19, WireType.LengthDelimited).fork().tag(1, WireType.Varint).uint32(parseInt(k)); writer.tag(2, WireType.LengthDelimited).fork(); Feature.internalBinaryWrite(message.features[k as any], writer, options); writer.join().join(); } + /* string commit_hash = 20; */ + if (message.commitHash !== "") + writer.tag(20, WireType.LengthDelimited).string(message.commitHash); /* bool require_htlc_interceptor = 21; */ if (message.requireHtlcInterceptor !== false) writer.tag(21, WireType.Varint).bool(message.requireHtlcInterceptor); @@ -12316,14 +13006,26 @@ class GetDebugInfoRequest$Type extends MessageType { super("lnrpc.GetDebugInfoRequest", []); } create(value?: PartialMessage): GetDebugInfoRequest { - const message = {}; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); if (value !== undefined) reflectionMergePartial(this, message, value); return message; } internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: GetDebugInfoRequest): GetDebugInfoRequest { - return target ?? this.create(); + let message = target ?? this.create(), end = reader.pos + length; + while (reader.pos < end) { + let [fieldNo, wireType] = reader.tag(); + switch (fieldNo) { + default: + let u = options.readUnknownField; + if (u === "throw") + throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`); + let d = reader.skip(wireType); + if (u !== false) + (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d); + } + } + return message; } internalBinaryWrite(message: GetDebugInfoRequest, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter { let u = options.writeUnknownFields; @@ -12345,8 +13047,9 @@ class GetDebugInfoResponse$Type extends MessageType { ]); } create(value?: PartialMessage): GetDebugInfoResponse { - const message = { config: {}, log: [] }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.config = {}; + message.log = []; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -12384,14 +13087,14 @@ class GetDebugInfoResponse$Type extends MessageType { case 2: val = reader.string(); break; - default: throw new globalThis.Error("unknown map entry field for field lnrpc.GetDebugInfoResponse.config"); + default: throw new globalThis.Error("unknown map entry field for lnrpc.GetDebugInfoResponse.config"); } } map[key ?? ""] = val ?? ""; } internalBinaryWrite(message: GetDebugInfoResponse, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter { /* map config = 1; */ - for (let k of Object.keys(message.config)) + for (let k of globalThis.Object.keys(message.config)) writer.tag(1, WireType.LengthDelimited).fork().tag(1, WireType.LengthDelimited).string(k).tag(2, WireType.LengthDelimited).string(message.config[k]).join(); /* repeated string log = 2; */ for (let i = 0; i < message.log.length; i++) @@ -12412,14 +13115,26 @@ class GetRecoveryInfoRequest$Type extends MessageType { super("lnrpc.GetRecoveryInfoRequest", []); } create(value?: PartialMessage): GetRecoveryInfoRequest { - const message = {}; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); if (value !== undefined) reflectionMergePartial(this, message, value); return message; } internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: GetRecoveryInfoRequest): GetRecoveryInfoRequest { - return target ?? this.create(); + let message = target ?? this.create(), end = reader.pos + length; + while (reader.pos < end) { + let [fieldNo, wireType] = reader.tag(); + switch (fieldNo) { + default: + let u = options.readUnknownField; + if (u === "throw") + throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`); + let d = reader.skip(wireType); + if (u !== false) + (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d); + } + } + return message; } internalBinaryWrite(message: GetRecoveryInfoRequest, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter { let u = options.writeUnknownFields; @@ -12442,8 +13157,10 @@ class GetRecoveryInfoResponse$Type extends MessageType ]); } create(value?: PartialMessage): GetRecoveryInfoResponse { - const message = { recoveryMode: false, recoveryFinished: false, progress: 0 }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.recoveryMode = false; + message.recoveryFinished = false; + message.progress = 0; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -12502,8 +13219,9 @@ class Chain$Type extends MessageType { ]); } create(value?: PartialMessage): Chain { - const message = { chain: "", network: "" }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.chain = ""; + message.network = ""; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -12513,7 +13231,7 @@ class Chain$Type extends MessageType { while (reader.pos < end) { let [fieldNo, wireType] = reader.tag(); switch (fieldNo) { - case /* string chain = 1 [deprecated = true];*/ 1: + case /* string chain = 1 [deprecated = true] */ 1: message.chain = reader.string(); break; case /* string network */ 2: @@ -12557,8 +13275,10 @@ class ConfirmationUpdate$Type extends MessageType { ]); } create(value?: PartialMessage): ConfirmationUpdate { - const message = { blockSha: new Uint8Array(0), blockHeight: 0, numConfsLeft: 0 }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.blockSha = new Uint8Array(0); + message.blockHeight = 0; + message.numConfsLeft = 0; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -12616,8 +13336,7 @@ class ChannelOpenUpdate$Type extends MessageType { ]); } create(value?: PartialMessage): ChannelOpenUpdate { - const message = {}; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -12656,16 +13375,92 @@ class ChannelOpenUpdate$Type extends MessageType { */ export const ChannelOpenUpdate = new ChannelOpenUpdate$Type(); // @generated message type with reflection information, may provide speed optimized methods +class CloseOutput$Type extends MessageType { + constructor() { + super("lnrpc.CloseOutput", [ + { no: 1, name: "amount_sat", kind: "scalar", T: 3 /*ScalarType.INT64*/, L: 0 /*LongType.BIGINT*/ }, + { no: 2, name: "pk_script", kind: "scalar", T: 12 /*ScalarType.BYTES*/ }, + { no: 3, name: "is_local", kind: "scalar", T: 8 /*ScalarType.BOOL*/ }, + { no: 4, name: "custom_channel_data", kind: "scalar", T: 12 /*ScalarType.BYTES*/ } + ]); + } + create(value?: PartialMessage): CloseOutput { + const message = globalThis.Object.create((this.messagePrototype!)); + message.amountSat = 0n; + message.pkScript = new Uint8Array(0); + message.isLocal = false; + message.customChannelData = new Uint8Array(0); + if (value !== undefined) + reflectionMergePartial(this, message, value); + return message; + } + internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: CloseOutput): CloseOutput { + let message = target ?? this.create(), end = reader.pos + length; + while (reader.pos < end) { + let [fieldNo, wireType] = reader.tag(); + switch (fieldNo) { + case /* int64 amount_sat */ 1: + message.amountSat = reader.int64().toBigInt(); + break; + case /* bytes pk_script */ 2: + message.pkScript = reader.bytes(); + break; + case /* bool is_local */ 3: + message.isLocal = reader.bool(); + break; + case /* bytes custom_channel_data */ 4: + message.customChannelData = reader.bytes(); + break; + default: + let u = options.readUnknownField; + if (u === "throw") + throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`); + let d = reader.skip(wireType); + if (u !== false) + (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d); + } + } + return message; + } + internalBinaryWrite(message: CloseOutput, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter { + /* int64 amount_sat = 1; */ + if (message.amountSat !== 0n) + writer.tag(1, WireType.Varint).int64(message.amountSat); + /* bytes pk_script = 2; */ + if (message.pkScript.length) + writer.tag(2, WireType.LengthDelimited).bytes(message.pkScript); + /* bool is_local = 3; */ + if (message.isLocal !== false) + writer.tag(3, WireType.Varint).bool(message.isLocal); + /* bytes custom_channel_data = 4; */ + if (message.customChannelData.length) + writer.tag(4, WireType.LengthDelimited).bytes(message.customChannelData); + let u = options.writeUnknownFields; + if (u !== false) + (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer); + return writer; + } +} +/** + * @generated MessageType for protobuf message lnrpc.CloseOutput + */ +export const CloseOutput = new CloseOutput$Type(); +// @generated message type with reflection information, may provide speed optimized methods class ChannelCloseUpdate$Type extends MessageType { constructor() { super("lnrpc.ChannelCloseUpdate", [ { no: 1, name: "closing_txid", kind: "scalar", T: 12 /*ScalarType.BYTES*/ }, - { no: 2, name: "success", kind: "scalar", T: 8 /*ScalarType.BOOL*/ } + { no: 2, name: "success", kind: "scalar", T: 8 /*ScalarType.BOOL*/ }, + { no: 3, name: "local_close_output", kind: "message", T: () => CloseOutput }, + { no: 4, name: "remote_close_output", kind: "message", T: () => CloseOutput }, + { no: 5, name: "additional_outputs", kind: "message", repeat: 2 /*RepeatType.UNPACKED*/, T: () => CloseOutput } ]); } create(value?: PartialMessage): ChannelCloseUpdate { - const message = { closingTxid: new Uint8Array(0), success: false }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.closingTxid = new Uint8Array(0); + message.success = false; + message.additionalOutputs = []; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -12681,6 +13476,15 @@ class ChannelCloseUpdate$Type extends MessageType { case /* bool success */ 2: message.success = reader.bool(); break; + case /* lnrpc.CloseOutput local_close_output */ 3: + message.localCloseOutput = CloseOutput.internalBinaryRead(reader, reader.uint32(), options, message.localCloseOutput); + break; + case /* lnrpc.CloseOutput remote_close_output */ 4: + message.remoteCloseOutput = CloseOutput.internalBinaryRead(reader, reader.uint32(), options, message.remoteCloseOutput); + break; + case /* repeated lnrpc.CloseOutput additional_outputs */ 5: + message.additionalOutputs.push(CloseOutput.internalBinaryRead(reader, reader.uint32(), options)); + break; default: let u = options.readUnknownField; if (u === "throw") @@ -12699,6 +13503,15 @@ class ChannelCloseUpdate$Type extends MessageType { /* bool success = 2; */ if (message.success !== false) writer.tag(2, WireType.Varint).bool(message.success); + /* lnrpc.CloseOutput local_close_output = 3; */ + if (message.localCloseOutput) + CloseOutput.internalBinaryWrite(message.localCloseOutput, writer.tag(3, WireType.LengthDelimited).fork(), options).join(); + /* lnrpc.CloseOutput remote_close_output = 4; */ + if (message.remoteCloseOutput) + CloseOutput.internalBinaryWrite(message.remoteCloseOutput, writer.tag(4, WireType.LengthDelimited).fork(), options).join(); + /* repeated lnrpc.CloseOutput additional_outputs = 5; */ + for (let i = 0; i < message.additionalOutputs.length; i++) + CloseOutput.internalBinaryWrite(message.additionalOutputs[i], writer.tag(5, WireType.LengthDelimited).fork(), options).join(); let u = options.writeUnknownFields; if (u !== false) (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer); @@ -12724,8 +13537,14 @@ class CloseChannelRequest$Type extends MessageType { ]); } create(value?: PartialMessage): CloseChannelRequest { - const message = { force: false, targetConf: 0, satPerByte: 0n, deliveryAddress: "", satPerVbyte: 0n, maxFeePerVbyte: 0n, noWait: false }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.force = false; + message.targetConf = 0; + message.satPerByte = 0n; + message.deliveryAddress = ""; + message.satPerVbyte = 0n; + message.maxFeePerVbyte = 0n; + message.noWait = false; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -12744,7 +13563,7 @@ class CloseChannelRequest$Type extends MessageType { case /* int32 target_conf */ 3: message.targetConf = reader.int32(); break; - case /* int64 sat_per_byte = 4 [deprecated = true];*/ 4: + case /* int64 sat_per_byte = 4 [deprecated = true] */ 4: message.satPerByte = reader.int64().toBigInt(); break; case /* string delivery_address */ 5: @@ -12815,8 +13634,8 @@ class CloseStatusUpdate$Type extends MessageType { ]); } create(value?: PartialMessage): CloseStatusUpdate { - const message = { update: { oneofKind: undefined } }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.update = { oneofKind: undefined }; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -12880,12 +13699,17 @@ class PendingUpdate$Type extends MessageType { constructor() { super("lnrpc.PendingUpdate", [ { no: 1, name: "txid", kind: "scalar", T: 12 /*ScalarType.BYTES*/ }, - { no: 2, name: "output_index", kind: "scalar", T: 13 /*ScalarType.UINT32*/ } + { no: 2, name: "output_index", kind: "scalar", T: 13 /*ScalarType.UINT32*/ }, + { no: 3, name: "fee_per_vbyte", kind: "scalar", T: 3 /*ScalarType.INT64*/, L: 0 /*LongType.BIGINT*/ }, + { no: 4, name: "local_close_tx", kind: "scalar", T: 8 /*ScalarType.BOOL*/ } ]); } create(value?: PartialMessage): PendingUpdate { - const message = { txid: new Uint8Array(0), outputIndex: 0 }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.txid = new Uint8Array(0); + message.outputIndex = 0; + message.feePerVbyte = 0n; + message.localCloseTx = false; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -12901,6 +13725,12 @@ class PendingUpdate$Type extends MessageType { case /* uint32 output_index */ 2: message.outputIndex = reader.uint32(); break; + case /* int64 fee_per_vbyte */ 3: + message.feePerVbyte = reader.int64().toBigInt(); + break; + case /* bool local_close_tx */ 4: + message.localCloseTx = reader.bool(); + break; default: let u = options.readUnknownField; if (u === "throw") @@ -12919,6 +13749,12 @@ class PendingUpdate$Type extends MessageType { /* uint32 output_index = 2; */ if (message.outputIndex !== 0) writer.tag(2, WireType.Varint).uint32(message.outputIndex); + /* int64 fee_per_vbyte = 3; */ + if (message.feePerVbyte !== 0n) + writer.tag(3, WireType.Varint).int64(message.feePerVbyte); + /* bool local_close_tx = 4; */ + if (message.localCloseTx !== false) + writer.tag(4, WireType.Varint).bool(message.localCloseTx); let u = options.writeUnknownFields; if (u !== false) (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer); @@ -12932,19 +13768,40 @@ export const PendingUpdate = new PendingUpdate$Type(); // @generated message type with reflection information, may provide speed optimized methods class InstantUpdate$Type extends MessageType { constructor() { - super("lnrpc.InstantUpdate", []); + super("lnrpc.InstantUpdate", [ + { no: 1, name: "num_pending_htlcs", kind: "scalar", T: 5 /*ScalarType.INT32*/ } + ]); } create(value?: PartialMessage): InstantUpdate { - const message = {}; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.numPendingHtlcs = 0; if (value !== undefined) reflectionMergePartial(this, message, value); return message; } internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: InstantUpdate): InstantUpdate { - return target ?? this.create(); + let message = target ?? this.create(), end = reader.pos + length; + while (reader.pos < end) { + let [fieldNo, wireType] = reader.tag(); + switch (fieldNo) { + case /* int32 num_pending_htlcs */ 1: + message.numPendingHtlcs = reader.int32(); + break; + default: + let u = options.readUnknownField; + if (u === "throw") + throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`); + let d = reader.skip(wireType); + if (u !== false) + (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d); + } + } + return message; } internalBinaryWrite(message: InstantUpdate, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter { + /* int32 num_pending_htlcs = 1; */ + if (message.numPendingHtlcs !== 0) + writer.tag(1, WireType.Varint).int32(message.numPendingHtlcs); let u = options.writeUnknownFields; if (u !== false) (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer); @@ -12965,8 +13822,10 @@ class ReadyForPsbtFunding$Type extends MessageType { ]); } create(value?: PartialMessage): ReadyForPsbtFunding { - const message = { fundingAddress: "", fundingAmount: 0n, psbt: new Uint8Array(0) }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.fundingAddress = ""; + message.fundingAmount = 0n; + message.psbt = new Uint8Array(0); if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -13020,7 +13879,7 @@ export const ReadyForPsbtFunding = new ReadyForPsbtFunding$Type(); class BatchOpenChannelRequest$Type extends MessageType { constructor() { super("lnrpc.BatchOpenChannelRequest", [ - { no: 1, name: "channels", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => BatchOpenChannel }, + { no: 1, name: "channels", kind: "message", repeat: 2 /*RepeatType.UNPACKED*/, T: () => BatchOpenChannel }, { no: 2, name: "target_conf", kind: "scalar", T: 5 /*ScalarType.INT32*/ }, { no: 3, name: "sat_per_vbyte", kind: "scalar", T: 3 /*ScalarType.INT64*/, L: 0 /*LongType.BIGINT*/ }, { no: 4, name: "min_confs", kind: "scalar", T: 5 /*ScalarType.INT32*/ }, @@ -13030,8 +13889,14 @@ class BatchOpenChannelRequest$Type extends MessageType ]); } create(value?: PartialMessage): BatchOpenChannelRequest { - const message = { channels: [], targetConf: 0, satPerVbyte: 0n, minConfs: 0, spendUnconfirmed: false, label: "", coinSelectionStrategy: 0 }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.channels = []; + message.targetConf = 0; + message.satPerVbyte = 0n; + message.minConfs = 0; + message.spendUnconfirmed = false; + message.label = ""; + message.coinSelectionStrategy = 0; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -13132,8 +13997,27 @@ class BatchOpenChannel$Type extends MessageType { ]); } create(value?: PartialMessage): BatchOpenChannel { - const message = { nodePubkey: new Uint8Array(0), localFundingAmount: 0n, pushSat: 0n, private: false, minHtlcMsat: 0n, remoteCsvDelay: 0, closeAddress: "", pendingChanId: new Uint8Array(0), commitmentType: 0, remoteMaxValueInFlightMsat: 0n, remoteMaxHtlcs: 0, maxLocalCsv: 0, zeroConf: false, scidAlias: false, baseFee: 0n, feeRate: 0n, useBaseFee: false, useFeeRate: false, remoteChanReserveSat: 0n, memo: "" }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.nodePubkey = new Uint8Array(0); + message.localFundingAmount = 0n; + message.pushSat = 0n; + message.private = false; + message.minHtlcMsat = 0n; + message.remoteCsvDelay = 0; + message.closeAddress = ""; + message.pendingChanId = new Uint8Array(0); + message.commitmentType = 0; + message.remoteMaxValueInFlightMsat = 0n; + message.remoteMaxHtlcs = 0; + message.maxLocalCsv = 0; + message.zeroConf = false; + message.scidAlias = false; + message.baseFee = 0n; + message.feeRate = 0n; + message.useBaseFee = false; + message.useFeeRate = false; + message.remoteChanReserveSat = 0n; + message.memo = ""; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -13289,12 +14173,12 @@ export const BatchOpenChannel = new BatchOpenChannel$Type(); class BatchOpenChannelResponse$Type extends MessageType { constructor() { super("lnrpc.BatchOpenChannelResponse", [ - { no: 1, name: "pending_channels", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => PendingUpdate } + { no: 1, name: "pending_channels", kind: "message", repeat: 2 /*RepeatType.UNPACKED*/, T: () => PendingUpdate } ]); } create(value?: PartialMessage): BatchOpenChannelResponse { - const message = { pendingChannels: [] }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.pendingChannels = []; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -13363,12 +14247,38 @@ class OpenChannelRequest$Type extends MessageType { { no: 25, name: "remote_chan_reserve_sat", kind: "scalar", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ }, { no: 26, name: "fund_max", kind: "scalar", T: 8 /*ScalarType.BOOL*/ }, { no: 27, name: "memo", kind: "scalar", T: 9 /*ScalarType.STRING*/ }, - { no: 28, name: "outpoints", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => OutPoint } + { no: 28, name: "outpoints", kind: "message", repeat: 2 /*RepeatType.UNPACKED*/, T: () => OutPoint } ]); } create(value?: PartialMessage): OpenChannelRequest { - const message = { satPerVbyte: 0n, nodePubkey: new Uint8Array(0), nodePubkeyString: "", localFundingAmount: 0n, pushSat: 0n, targetConf: 0, satPerByte: 0n, private: false, minHtlcMsat: 0n, remoteCsvDelay: 0, minConfs: 0, spendUnconfirmed: false, closeAddress: "", remoteMaxValueInFlightMsat: 0n, remoteMaxHtlcs: 0, maxLocalCsv: 0, commitmentType: 0, zeroConf: false, scidAlias: false, baseFee: 0n, feeRate: 0n, useBaseFee: false, useFeeRate: false, remoteChanReserveSat: 0n, fundMax: false, memo: "", outpoints: [] }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.satPerVbyte = 0n; + message.nodePubkey = new Uint8Array(0); + message.nodePubkeyString = ""; + message.localFundingAmount = 0n; + message.pushSat = 0n; + message.targetConf = 0; + message.satPerByte = 0n; + message.private = false; + message.minHtlcMsat = 0n; + message.remoteCsvDelay = 0; + message.minConfs = 0; + message.spendUnconfirmed = false; + message.closeAddress = ""; + message.remoteMaxValueInFlightMsat = 0n; + message.remoteMaxHtlcs = 0; + message.maxLocalCsv = 0; + message.commitmentType = 0; + message.zeroConf = false; + message.scidAlias = false; + message.baseFee = 0n; + message.feeRate = 0n; + message.useBaseFee = false; + message.useFeeRate = false; + message.remoteChanReserveSat = 0n; + message.fundMax = false; + message.memo = ""; + message.outpoints = []; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -13384,7 +14294,7 @@ class OpenChannelRequest$Type extends MessageType { case /* bytes node_pubkey */ 2: message.nodePubkey = reader.bytes(); break; - case /* string node_pubkey_string = 3 [deprecated = true];*/ 3: + case /* string node_pubkey_string = 3 [deprecated = true] */ 3: message.nodePubkeyString = reader.string(); break; case /* int64 local_funding_amount */ 4: @@ -13396,7 +14306,7 @@ class OpenChannelRequest$Type extends MessageType { case /* int32 target_conf */ 6: message.targetConf = reader.int32(); break; - case /* int64 sat_per_byte = 7 [deprecated = true];*/ 7: + case /* int64 sat_per_byte = 7 [deprecated = true] */ 7: message.satPerByte = reader.int64().toBigInt(); break; case /* bool private */ 8: @@ -13579,8 +14489,9 @@ class OpenStatusUpdate$Type extends MessageType { ]); } create(value?: PartialMessage): OpenStatusUpdate { - const message = { update: { oneofKind: undefined }, pendingChanId: new Uint8Array(0) }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.update = { oneofKind: undefined }; + message.pendingChanId = new Uint8Array(0); if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -13629,12 +14540,12 @@ class OpenStatusUpdate$Type extends MessageType { /* lnrpc.ChannelOpenUpdate chan_open = 3; */ if (message.update.oneofKind === "chanOpen") ChannelOpenUpdate.internalBinaryWrite(message.update.chanOpen, writer.tag(3, WireType.LengthDelimited).fork(), options).join(); - /* lnrpc.ReadyForPsbtFunding psbt_fund = 5; */ - if (message.update.oneofKind === "psbtFund") - ReadyForPsbtFunding.internalBinaryWrite(message.update.psbtFund, writer.tag(5, WireType.LengthDelimited).fork(), options).join(); /* bytes pending_chan_id = 4; */ if (message.pendingChanId.length) writer.tag(4, WireType.LengthDelimited).bytes(message.pendingChanId); + /* lnrpc.ReadyForPsbtFunding psbt_fund = 5; */ + if (message.update.oneofKind === "psbtFund") + ReadyForPsbtFunding.internalBinaryWrite(message.update.psbtFund, writer.tag(5, WireType.LengthDelimited).fork(), options).join(); let u = options.writeUnknownFields; if (u !== false) (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer); @@ -13654,8 +14565,9 @@ class KeyLocator$Type extends MessageType { ]); } create(value?: PartialMessage): KeyLocator { - const message = { keyFamily: 0, keyIndex: 0 }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.keyFamily = 0; + message.keyIndex = 0; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -13708,8 +14620,8 @@ class KeyDescriptor$Type extends MessageType { ]); } create(value?: PartialMessage): KeyDescriptor { - const message = { rawKeyBytes: new Uint8Array(0) }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.rawKeyBytes = new Uint8Array(0); if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -13767,8 +14679,12 @@ class ChanPointShim$Type extends MessageType { ]); } create(value?: PartialMessage): ChanPointShim { - const message = { amt: 0n, remoteKey: new Uint8Array(0), pendingChanId: new Uint8Array(0), thawHeight: 0, musig2: false }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.amt = 0n; + message.remoteKey = new Uint8Array(0); + message.pendingChanId = new Uint8Array(0); + message.thawHeight = 0; + message.musig2 = false; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -13852,8 +14768,10 @@ class PsbtShim$Type extends MessageType { ]); } create(value?: PartialMessage): PsbtShim { - const message = { pendingChanId: new Uint8Array(0), basePsbt: new Uint8Array(0), noPublish: false }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.pendingChanId = new Uint8Array(0); + message.basePsbt = new Uint8Array(0); + message.noPublish = false; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -13912,8 +14830,8 @@ class FundingShim$Type extends MessageType { ]); } create(value?: PartialMessage): FundingShim { - const message = { shim: { oneofKind: undefined } }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.shim = { oneofKind: undefined }; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -13971,8 +14889,8 @@ class FundingShimCancel$Type extends MessageType { ]); } create(value?: PartialMessage): FundingShimCancel { - const message = { pendingChanId: new Uint8Array(0) }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.pendingChanId = new Uint8Array(0); if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -14020,8 +14938,10 @@ class FundingPsbtVerify$Type extends MessageType { ]); } create(value?: PartialMessage): FundingPsbtVerify { - const message = { fundedPsbt: new Uint8Array(0), pendingChanId: new Uint8Array(0), skipFinalize: false }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.fundedPsbt = new Uint8Array(0); + message.pendingChanId = new Uint8Array(0); + message.skipFinalize = false; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -14081,8 +15001,10 @@ class FundingPsbtFinalize$Type extends MessageType { ]); } create(value?: PartialMessage): FundingPsbtFinalize { - const message = { signedPsbt: new Uint8Array(0), pendingChanId: new Uint8Array(0), finalRawTx: new Uint8Array(0) }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.signedPsbt = new Uint8Array(0); + message.pendingChanId = new Uint8Array(0); + message.finalRawTx = new Uint8Array(0); if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -14143,8 +15065,8 @@ class FundingTransitionMsg$Type extends MessageType { ]); } create(value?: PartialMessage): FundingTransitionMsg { - const message = { trigger: { oneofKind: undefined } }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.trigger = { oneofKind: undefined }; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -14218,14 +15140,26 @@ class FundingStateStepResp$Type extends MessageType { super("lnrpc.FundingStateStepResp", []); } create(value?: PartialMessage): FundingStateStepResp { - const message = {}; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); if (value !== undefined) reflectionMergePartial(this, message, value); return message; } internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: FundingStateStepResp): FundingStateStepResp { - return target ?? this.create(); + let message = target ?? this.create(), end = reader.pos + length; + while (reader.pos < end) { + let [fieldNo, wireType] = reader.tag(); + switch (fieldNo) { + default: + let u = options.readUnknownField; + if (u === "throw") + throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`); + let d = reader.skip(wireType); + if (u !== false) + (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d); + } + } + return message; } internalBinaryWrite(message: FundingStateStepResp, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter { let u = options.writeUnknownFields; @@ -14251,8 +15185,13 @@ class PendingHTLC$Type extends MessageType { ]); } create(value?: PartialMessage): PendingHTLC { - const message = { incoming: false, amount: 0n, outpoint: "", maturityHeight: 0, blocksTilMaturity: 0, stage: 0 }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.incoming = false; + message.amount = 0n; + message.outpoint = ""; + message.maturityHeight = 0; + message.blocksTilMaturity = 0; + message.stage = 0; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -14328,8 +15267,8 @@ class PendingChannelsRequest$Type extends MessageType { ]); } create(value?: PartialMessage): PendingChannelsRequest { - const message = { includeRawTx: false }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.includeRawTx = false; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -14372,15 +15311,19 @@ class PendingChannelsResponse$Type extends MessageType constructor() { super("lnrpc.PendingChannelsResponse", [ { no: 1, name: "total_limbo_balance", kind: "scalar", T: 3 /*ScalarType.INT64*/, L: 0 /*LongType.BIGINT*/ }, - { no: 2, name: "pending_open_channels", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => PendingChannelsResponse_PendingOpenChannel }, - { no: 3, name: "pending_closing_channels", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => PendingChannelsResponse_ClosedChannel }, - { no: 4, name: "pending_force_closing_channels", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => PendingChannelsResponse_ForceClosedChannel }, - { no: 5, name: "waiting_close_channels", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => PendingChannelsResponse_WaitingCloseChannel } + { no: 2, name: "pending_open_channels", kind: "message", repeat: 2 /*RepeatType.UNPACKED*/, T: () => PendingChannelsResponse_PendingOpenChannel }, + { no: 3, name: "pending_closing_channels", kind: "message", repeat: 2 /*RepeatType.UNPACKED*/, T: () => PendingChannelsResponse_ClosedChannel }, + { no: 4, name: "pending_force_closing_channels", kind: "message", repeat: 2 /*RepeatType.UNPACKED*/, T: () => PendingChannelsResponse_ForceClosedChannel }, + { no: 5, name: "waiting_close_channels", kind: "message", repeat: 2 /*RepeatType.UNPACKED*/, T: () => PendingChannelsResponse_WaitingCloseChannel } ]); } create(value?: PartialMessage): PendingChannelsResponse { - const message = { totalLimboBalance: 0n, pendingOpenChannels: [], pendingClosingChannels: [], pendingForceClosingChannels: [], waitingCloseChannels: [] }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.totalLimboBalance = 0n; + message.pendingOpenChannels = []; + message.pendingClosingChannels = []; + message.pendingForceClosingChannels = []; + message.waitingCloseChannels = []; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -14396,7 +15339,7 @@ class PendingChannelsResponse$Type extends MessageType case /* repeated lnrpc.PendingChannelsResponse.PendingOpenChannel pending_open_channels */ 2: message.pendingOpenChannels.push(PendingChannelsResponse_PendingOpenChannel.internalBinaryRead(reader, reader.uint32(), options)); break; - case /* repeated lnrpc.PendingChannelsResponse.ClosedChannel pending_closing_channels = 3 [deprecated = true];*/ 3: + case /* repeated lnrpc.PendingChannelsResponse.ClosedChannel pending_closing_channels = 3 [deprecated = true] */ 3: message.pendingClosingChannels.push(PendingChannelsResponse_ClosedChannel.internalBinaryRead(reader, reader.uint32(), options)); break; case /* repeated lnrpc.PendingChannelsResponse.ForceClosedChannel pending_force_closing_channels */ 4: @@ -14458,12 +15401,26 @@ class PendingChannelsResponse_PendingChannel$Type extends MessageType): PendingChannelsResponse_PendingChannel { - const message = { remoteNodePub: "", channelPoint: "", capacity: 0n, localBalance: 0n, remoteBalance: 0n, localChanReserveSat: 0n, remoteChanReserveSat: 0n, initiator: 0, commitmentType: 0, numForwardingPackages: 0n, chanStatusFlags: "", private: false, memo: "" }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.remoteNodePub = ""; + message.channelPoint = ""; + message.capacity = 0n; + message.localBalance = 0n; + message.remoteBalance = 0n; + message.localChanReserveSat = 0n; + message.remoteChanReserveSat = 0n; + message.initiator = 0; + message.commitmentType = 0; + message.numForwardingPackages = 0n; + message.chanStatusFlags = ""; + message.private = false; + message.memo = ""; + message.customChannelData = new Uint8Array(0); if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -14512,6 +15469,9 @@ class PendingChannelsResponse_PendingChannel$Type extends MessageType): PendingChannelsResponse_PendingOpenChannel { - const message = { commitFee: 0n, commitWeight: 0n, feePerKw: 0n, fundingExpiryBlocks: 0 }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.commitFee = 0n; + message.commitWeight = 0n; + message.feePerKw = 0n; + message.fundingExpiryBlocks = 0; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -14626,6 +15592,9 @@ class PendingChannelsResponse_PendingOpenChannel$Type extends MessageType): PendingChannelsResponse_WaitingCloseChannel { - const message = { limboBalance: 0n, closingTxid: "", closingTxHex: "" }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.limboBalance = 0n; + message.closingTxid = ""; + message.closingTxHex = ""; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -14736,8 +15704,13 @@ class PendingChannelsResponse_Commitments$Type extends MessageType): PendingChannelsResponse_Commitments { - const message = { localTxid: "", remoteTxid: "", remotePendingTxid: "", localCommitFeeSat: 0n, remoteCommitFeeSat: 0n, remotePendingCommitFeeSat: 0n }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.localTxid = ""; + message.remoteTxid = ""; + message.remotePendingTxid = ""; + message.localCommitFeeSat = 0n; + message.remoteCommitFeeSat = 0n; + message.remotePendingCommitFeeSat = 0n; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -14814,8 +15787,8 @@ class PendingChannelsResponse_ClosedChannel$Type extends MessageType): PendingChannelsResponse_ClosedChannel { - const message = { closingTxid: "" }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.closingTxid = ""; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -14869,13 +15842,19 @@ class PendingChannelsResponse_ForceClosedChannel$Type extends MessageType PendingHTLC }, + { no: 8, name: "pending_htlcs", kind: "message", repeat: 2 /*RepeatType.UNPACKED*/, T: () => PendingHTLC }, { no: 9, name: "anchor", kind: "enum", T: () => ["lnrpc.PendingChannelsResponse.ForceClosedChannel.AnchorState", PendingChannelsResponse_ForceClosedChannel_AnchorState] } ]); } create(value?: PartialMessage): PendingChannelsResponse_ForceClosedChannel { - const message = { closingTxid: "", limboBalance: 0n, maturityHeight: 0, blocksTilMaturity: 0, recoveredBalance: 0n, pendingHtlcs: [], anchor: 0 }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.closingTxid = ""; + message.limboBalance = 0n; + message.maturityHeight = 0; + message.blocksTilMaturity = 0; + message.recoveredBalance = 0n; + message.pendingHtlcs = []; + message.anchor = 0; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -14961,14 +15940,26 @@ class ChannelEventSubscription$Type extends MessageType): ChannelEventSubscription { - const message = {}; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); if (value !== undefined) reflectionMergePartial(this, message, value); return message; } internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: ChannelEventSubscription): ChannelEventSubscription { - return target ?? this.create(); + let message = target ?? this.create(), end = reader.pos + length; + while (reader.pos < end) { + let [fieldNo, wireType] = reader.tag(); + switch (fieldNo) { + default: + let u = options.readUnknownField; + if (u === "throw") + throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`); + let d = reader.skip(wireType); + if (u !== false) + (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d); + } + } + return message; } internalBinaryWrite(message: ChannelEventSubscription, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter { let u = options.writeUnknownFields; @@ -14991,12 +15982,14 @@ class ChannelEventUpdate$Type extends MessageType { { no: 4, name: "inactive_channel", kind: "message", oneof: "channel", T: () => ChannelPoint }, { no: 6, name: "pending_open_channel", kind: "message", oneof: "channel", T: () => PendingUpdate }, { no: 7, name: "fully_resolved_channel", kind: "message", oneof: "channel", T: () => ChannelPoint }, + { no: 8, name: "channel_funding_timeout", kind: "message", oneof: "channel", T: () => ChannelPoint }, { no: 5, name: "type", kind: "enum", T: () => ["lnrpc.ChannelEventUpdate.UpdateType", ChannelEventUpdate_UpdateType] } ]); } create(value?: PartialMessage): ChannelEventUpdate { - const message = { channel: { oneofKind: undefined }, type: 0 }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.channel = { oneofKind: undefined }; + message.type = 0; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -15042,6 +16035,12 @@ class ChannelEventUpdate$Type extends MessageType { fullyResolvedChannel: ChannelPoint.internalBinaryRead(reader, reader.uint32(), options, (message.channel as any).fullyResolvedChannel) }; break; + case /* lnrpc.ChannelPoint channel_funding_timeout */ 8: + message.channel = { + oneofKind: "channelFundingTimeout", + channelFundingTimeout: ChannelPoint.internalBinaryRead(reader, reader.uint32(), options, (message.channel as any).channelFundingTimeout) + }; + break; case /* lnrpc.ChannelEventUpdate.UpdateType type */ 5: message.type = reader.int32(); break; @@ -15069,15 +16068,18 @@ class ChannelEventUpdate$Type extends MessageType { /* lnrpc.ChannelPoint inactive_channel = 4; */ if (message.channel.oneofKind === "inactiveChannel") ChannelPoint.internalBinaryWrite(message.channel.inactiveChannel, writer.tag(4, WireType.LengthDelimited).fork(), options).join(); + /* lnrpc.ChannelEventUpdate.UpdateType type = 5; */ + if (message.type !== 0) + writer.tag(5, WireType.Varint).int32(message.type); /* lnrpc.PendingUpdate pending_open_channel = 6; */ if (message.channel.oneofKind === "pendingOpenChannel") PendingUpdate.internalBinaryWrite(message.channel.pendingOpenChannel, writer.tag(6, WireType.LengthDelimited).fork(), options).join(); /* lnrpc.ChannelPoint fully_resolved_channel = 7; */ if (message.channel.oneofKind === "fullyResolvedChannel") ChannelPoint.internalBinaryWrite(message.channel.fullyResolvedChannel, writer.tag(7, WireType.LengthDelimited).fork(), options).join(); - /* lnrpc.ChannelEventUpdate.UpdateType type = 5; */ - if (message.type !== 0) - writer.tag(5, WireType.Varint).int32(message.type); + /* lnrpc.ChannelPoint channel_funding_timeout = 8; */ + if (message.channel.oneofKind === "channelFundingTimeout") + ChannelPoint.internalBinaryWrite(message.channel.channelFundingTimeout, writer.tag(8, WireType.LengthDelimited).fork(), options).join(); let u = options.writeUnknownFields; if (u !== false) (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer); @@ -15097,8 +16099,9 @@ class WalletAccountBalance$Type extends MessageType { ]); } create(value?: PartialMessage): WalletAccountBalance { - const message = { confirmedBalance: 0n, unconfirmedBalance: 0n }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.confirmedBalance = 0n; + message.unconfirmedBalance = 0n; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -15151,8 +16154,9 @@ class WalletBalanceRequest$Type extends MessageType { ]); } create(value?: PartialMessage): WalletBalanceRequest { - const message = { account: "", minConfs: 0 }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.account = ""; + message.minConfs = 0; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -15209,8 +16213,13 @@ class WalletBalanceResponse$Type extends MessageType { ]); } create(value?: PartialMessage): WalletBalanceResponse { - const message = { totalBalance: 0n, confirmedBalance: 0n, unconfirmedBalance: 0n, lockedBalance: 0n, reservedBalanceAnchorChan: 0n, accountBalance: {} }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.totalBalance = 0n; + message.confirmedBalance = 0n; + message.unconfirmedBalance = 0n; + message.lockedBalance = 0n; + message.reservedBalanceAnchorChan = 0n; + message.accountBalance = {}; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -15260,7 +16269,7 @@ class WalletBalanceResponse$Type extends MessageType { case 2: val = WalletAccountBalance.internalBinaryRead(reader, reader.uint32(), options); break; - default: throw new globalThis.Error("unknown map entry field for field lnrpc.WalletBalanceResponse.account_balance"); + default: throw new globalThis.Error("unknown map entry field for lnrpc.WalletBalanceResponse.account_balance"); } } map[key ?? ""] = val ?? WalletAccountBalance.create(); @@ -15275,19 +16284,19 @@ class WalletBalanceResponse$Type extends MessageType { /* int64 unconfirmed_balance = 3; */ if (message.unconfirmedBalance !== 0n) writer.tag(3, WireType.Varint).int64(message.unconfirmedBalance); + /* map account_balance = 4; */ + for (let k of globalThis.Object.keys(message.accountBalance)) { + writer.tag(4, WireType.LengthDelimited).fork().tag(1, WireType.LengthDelimited).string(k); + writer.tag(2, WireType.LengthDelimited).fork(); + WalletAccountBalance.internalBinaryWrite(message.accountBalance[k], writer, options); + writer.join().join(); + } /* int64 locked_balance = 5; */ if (message.lockedBalance !== 0n) writer.tag(5, WireType.Varint).int64(message.lockedBalance); /* int64 reserved_balance_anchor_chan = 6; */ if (message.reservedBalanceAnchorChan !== 0n) writer.tag(6, WireType.Varint).int64(message.reservedBalanceAnchorChan); - /* map account_balance = 4; */ - for (let k of Object.keys(message.accountBalance)) { - writer.tag(4, WireType.LengthDelimited).fork().tag(1, WireType.LengthDelimited).string(k); - writer.tag(2, WireType.LengthDelimited).fork(); - WalletAccountBalance.internalBinaryWrite(message.accountBalance[k], writer, options); - writer.join().join(); - } let u = options.writeUnknownFields; if (u !== false) (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer); @@ -15307,8 +16316,9 @@ class Amount$Type extends MessageType { ]); } create(value?: PartialMessage): Amount { - const message = { sat: 0n, msat: 0n }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.sat = 0n; + message.msat = 0n; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -15358,14 +16368,26 @@ class ChannelBalanceRequest$Type extends MessageType { super("lnrpc.ChannelBalanceRequest", []); } create(value?: PartialMessage): ChannelBalanceRequest { - const message = {}; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); if (value !== undefined) reflectionMergePartial(this, message, value); return message; } internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: ChannelBalanceRequest): ChannelBalanceRequest { - return target ?? this.create(); + let message = target ?? this.create(), end = reader.pos + length; + while (reader.pos < end) { + let [fieldNo, wireType] = reader.tag(); + switch (fieldNo) { + default: + let u = options.readUnknownField; + if (u === "throw") + throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`); + let d = reader.skip(wireType); + if (u !== false) + (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d); + } + } + return message; } internalBinaryWrite(message: ChannelBalanceRequest, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter { let u = options.writeUnknownFields; @@ -15389,12 +16411,15 @@ class ChannelBalanceResponse$Type extends MessageType { { no: 5, name: "unsettled_local_balance", kind: "message", T: () => Amount }, { no: 6, name: "unsettled_remote_balance", kind: "message", T: () => Amount }, { no: 7, name: "pending_open_local_balance", kind: "message", T: () => Amount }, - { no: 8, name: "pending_open_remote_balance", kind: "message", T: () => Amount } + { no: 8, name: "pending_open_remote_balance", kind: "message", T: () => Amount }, + { no: 9, name: "custom_channel_data", kind: "scalar", T: 12 /*ScalarType.BYTES*/ } ]); } create(value?: PartialMessage): ChannelBalanceResponse { - const message = { balance: 0n, pendingOpenBalance: 0n }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.balance = 0n; + message.pendingOpenBalance = 0n; + message.customChannelData = new Uint8Array(0); if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -15404,10 +16429,10 @@ class ChannelBalanceResponse$Type extends MessageType { while (reader.pos < end) { let [fieldNo, wireType] = reader.tag(); switch (fieldNo) { - case /* int64 balance = 1 [deprecated = true];*/ 1: + case /* int64 balance = 1 [deprecated = true] */ 1: message.balance = reader.int64().toBigInt(); break; - case /* int64 pending_open_balance = 2 [deprecated = true];*/ 2: + case /* int64 pending_open_balance = 2 [deprecated = true] */ 2: message.pendingOpenBalance = reader.int64().toBigInt(); break; case /* lnrpc.Amount local_balance */ 3: @@ -15428,6 +16453,9 @@ class ChannelBalanceResponse$Type extends MessageType { case /* lnrpc.Amount pending_open_remote_balance */ 8: message.pendingOpenRemoteBalance = Amount.internalBinaryRead(reader, reader.uint32(), options, message.pendingOpenRemoteBalance); break; + case /* bytes custom_channel_data */ 9: + message.customChannelData = reader.bytes(); + break; default: let u = options.readUnknownField; if (u === "throw") @@ -15464,6 +16492,9 @@ class ChannelBalanceResponse$Type extends MessageType { /* lnrpc.Amount pending_open_remote_balance = 8; */ if (message.pendingOpenRemoteBalance) Amount.internalBinaryWrite(message.pendingOpenRemoteBalance, writer.tag(8, WireType.LengthDelimited).fork(), options).join(); + /* bytes custom_channel_data = 9; */ + if (message.customChannelData.length) + writer.tag(9, WireType.LengthDelimited).bytes(message.customChannelData); let u = options.writeUnknownFields; if (u !== false) (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer); @@ -15484,23 +16515,39 @@ class QueryRoutesRequest$Type extends MessageType { { no: 4, name: "final_cltv_delta", kind: "scalar", T: 5 /*ScalarType.INT32*/ }, { no: 5, name: "fee_limit", kind: "message", T: () => FeeLimit }, { no: 6, name: "ignored_nodes", kind: "scalar", repeat: 2 /*RepeatType.UNPACKED*/, T: 12 /*ScalarType.BYTES*/ }, - { no: 7, name: "ignored_edges", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => EdgeLocator }, + { no: 7, name: "ignored_edges", kind: "message", repeat: 2 /*RepeatType.UNPACKED*/, T: () => EdgeLocator }, { no: 8, name: "source_pub_key", kind: "scalar", T: 9 /*ScalarType.STRING*/ }, { no: 9, name: "use_mission_control", kind: "scalar", T: 8 /*ScalarType.BOOL*/ }, - { no: 10, name: "ignored_pairs", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => NodePair }, + { no: 10, name: "ignored_pairs", kind: "message", repeat: 2 /*RepeatType.UNPACKED*/, T: () => NodePair }, { no: 11, name: "cltv_limit", kind: "scalar", T: 13 /*ScalarType.UINT32*/ }, { no: 13, name: "dest_custom_records", kind: "map", K: 4 /*ScalarType.UINT64*/, V: { kind: "scalar", T: 12 /*ScalarType.BYTES*/ } }, { no: 14, name: "outgoing_chan_id", kind: "scalar", T: 4 /*ScalarType.UINT64*/ }, { no: 15, name: "last_hop_pubkey", kind: "scalar", T: 12 /*ScalarType.BYTES*/ }, - { no: 16, name: "route_hints", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => RouteHint }, - { no: 19, name: "blinded_payment_paths", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => BlindedPaymentPath }, + { no: 16, name: "route_hints", kind: "message", repeat: 2 /*RepeatType.UNPACKED*/, T: () => RouteHint }, + { no: 19, name: "blinded_payment_paths", kind: "message", repeat: 2 /*RepeatType.UNPACKED*/, T: () => BlindedPaymentPath }, { no: 17, name: "dest_features", kind: "enum", repeat: 1 /*RepeatType.PACKED*/, T: () => ["lnrpc.FeatureBit", FeatureBit] }, { no: 18, name: "time_pref", kind: "scalar", T: 1 /*ScalarType.DOUBLE*/ } ]); } create(value?: PartialMessage): QueryRoutesRequest { - const message = { pubKey: "", amt: 0n, amtMsat: 0n, finalCltvDelta: 0, ignoredNodes: [], ignoredEdges: [], sourcePubKey: "", useMissionControl: false, ignoredPairs: [], cltvLimit: 0, destCustomRecords: {}, outgoingChanId: "0", lastHopPubkey: new Uint8Array(0), routeHints: [], blindedPaymentPaths: [], destFeatures: [], timePref: 0 }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.pubKey = ""; + message.amt = 0n; + message.amtMsat = 0n; + message.finalCltvDelta = 0; + message.ignoredNodes = []; + message.ignoredEdges = []; + message.sourcePubKey = ""; + message.useMissionControl = false; + message.ignoredPairs = []; + message.cltvLimit = 0; + message.destCustomRecords = {}; + message.outgoingChanId = "0"; + message.lastHopPubkey = new Uint8Array(0); + message.routeHints = []; + message.blindedPaymentPaths = []; + message.destFeatures = []; + message.timePref = 0; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -15528,7 +16575,7 @@ class QueryRoutesRequest$Type extends MessageType { case /* repeated bytes ignored_nodes */ 6: message.ignoredNodes.push(reader.bytes()); break; - case /* repeated lnrpc.EdgeLocator ignored_edges = 7 [deprecated = true];*/ 7: + case /* repeated lnrpc.EdgeLocator ignored_edges = 7 [deprecated = true] */ 7: message.ignoredEdges.push(EdgeLocator.internalBinaryRead(reader, reader.uint32(), options)); break; case /* string source_pub_key */ 8: @@ -15546,7 +16593,7 @@ class QueryRoutesRequest$Type extends MessageType { case /* map dest_custom_records */ 13: this.binaryReadMap13(message.destCustomRecords, reader, options); break; - case /* uint64 outgoing_chan_id = 14 [jstype = JS_STRING];*/ 14: + case /* uint64 outgoing_chan_id = 14 [jstype = JS_STRING] */ 14: message.outgoingChanId = reader.uint64().toString(); break; case /* bytes last_hop_pubkey */ 15: @@ -15590,7 +16637,7 @@ class QueryRoutesRequest$Type extends MessageType { case 2: val = reader.bytes(); break; - default: throw new globalThis.Error("unknown map entry field for field lnrpc.QueryRoutesRequest.dest_custom_records"); + default: throw new globalThis.Error("unknown map entry field for lnrpc.QueryRoutesRequest.dest_custom_records"); } } map[key ?? "0"] = val ?? new Uint8Array(0); @@ -15602,9 +16649,6 @@ class QueryRoutesRequest$Type extends MessageType { /* int64 amt = 2; */ if (message.amt !== 0n) writer.tag(2, WireType.Varint).int64(message.amt); - /* int64 amt_msat = 12; */ - if (message.amtMsat !== 0n) - writer.tag(12, WireType.Varint).int64(message.amtMsat); /* int32 final_cltv_delta = 4; */ if (message.finalCltvDelta !== 0) writer.tag(4, WireType.Varint).int32(message.finalCltvDelta); @@ -15629,8 +16673,11 @@ class QueryRoutesRequest$Type extends MessageType { /* uint32 cltv_limit = 11; */ if (message.cltvLimit !== 0) writer.tag(11, WireType.Varint).uint32(message.cltvLimit); + /* int64 amt_msat = 12; */ + if (message.amtMsat !== 0n) + writer.tag(12, WireType.Varint).int64(message.amtMsat); /* map dest_custom_records = 13; */ - for (let k of Object.keys(message.destCustomRecords)) + for (let k of globalThis.Object.keys(message.destCustomRecords)) writer.tag(13, WireType.LengthDelimited).fork().tag(1, WireType.Varint).uint64(k).tag(2, WireType.LengthDelimited).bytes(message.destCustomRecords[k]).join(); /* uint64 outgoing_chan_id = 14 [jstype = JS_STRING]; */ if (message.outgoingChanId !== "0") @@ -15641,9 +16688,6 @@ class QueryRoutesRequest$Type extends MessageType { /* repeated lnrpc.RouteHint route_hints = 16; */ for (let i = 0; i < message.routeHints.length; i++) RouteHint.internalBinaryWrite(message.routeHints[i], writer.tag(16, WireType.LengthDelimited).fork(), options).join(); - /* repeated lnrpc.BlindedPaymentPath blinded_payment_paths = 19; */ - for (let i = 0; i < message.blindedPaymentPaths.length; i++) - BlindedPaymentPath.internalBinaryWrite(message.blindedPaymentPaths[i], writer.tag(19, WireType.LengthDelimited).fork(), options).join(); /* repeated lnrpc.FeatureBit dest_features = 17; */ if (message.destFeatures.length) { writer.tag(17, WireType.LengthDelimited).fork(); @@ -15654,6 +16698,9 @@ class QueryRoutesRequest$Type extends MessageType { /* double time_pref = 18; */ if (message.timePref !== 0) writer.tag(18, WireType.Bit64).double(message.timePref); + /* repeated lnrpc.BlindedPaymentPath blinded_payment_paths = 19; */ + for (let i = 0; i < message.blindedPaymentPaths.length; i++) + BlindedPaymentPath.internalBinaryWrite(message.blindedPaymentPaths[i], writer.tag(19, WireType.LengthDelimited).fork(), options).join(); let u = options.writeUnknownFields; if (u !== false) (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer); @@ -15673,8 +16720,9 @@ class NodePair$Type extends MessageType { ]); } create(value?: PartialMessage): NodePair { - const message = { from: new Uint8Array(0), to: new Uint8Array(0) }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.from = new Uint8Array(0); + message.to = new Uint8Array(0); if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -15727,8 +16775,9 @@ class EdgeLocator$Type extends MessageType { ]); } create(value?: PartialMessage): EdgeLocator { - const message = { channelId: "0", directionReverse: false }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.channelId = "0"; + message.directionReverse = false; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -15738,7 +16787,7 @@ class EdgeLocator$Type extends MessageType { while (reader.pos < end) { let [fieldNo, wireType] = reader.tag(); switch (fieldNo) { - case /* uint64 channel_id = 1 [jstype = JS_STRING];*/ 1: + case /* uint64 channel_id = 1 [jstype = JS_STRING] */ 1: message.channelId = reader.uint64().toString(); break; case /* bool direction_reverse */ 2: @@ -15776,13 +16825,14 @@ export const EdgeLocator = new EdgeLocator$Type(); class QueryRoutesResponse$Type extends MessageType { constructor() { super("lnrpc.QueryRoutesResponse", [ - { no: 1, name: "routes", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => Route }, + { no: 1, name: "routes", kind: "message", repeat: 2 /*RepeatType.UNPACKED*/, T: () => Route }, { no: 2, name: "success_prob", kind: "scalar", T: 1 /*ScalarType.DOUBLE*/ } ]); } create(value?: PartialMessage): QueryRoutesResponse { - const message = { routes: [], successProb: 0 }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.routes = []; + message.successProb = 0; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -15849,8 +16899,21 @@ class Hop$Type extends MessageType { ]); } create(value?: PartialMessage): Hop { - const message = { chanId: "0", chanCapacity: 0n, amtToForward: 0n, fee: 0n, expiry: 0, amtToForwardMsat: 0n, feeMsat: 0n, pubKey: "", tlvPayload: false, customRecords: {}, metadata: new Uint8Array(0), blindingPoint: new Uint8Array(0), encryptedData: new Uint8Array(0), totalAmtMsat: 0n }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.chanId = "0"; + message.chanCapacity = 0n; + message.amtToForward = 0n; + message.fee = 0n; + message.expiry = 0; + message.amtToForwardMsat = 0n; + message.feeMsat = 0n; + message.pubKey = ""; + message.tlvPayload = false; + message.customRecords = {}; + message.metadata = new Uint8Array(0); + message.blindingPoint = new Uint8Array(0); + message.encryptedData = new Uint8Array(0); + message.totalAmtMsat = 0n; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -15860,16 +16923,16 @@ class Hop$Type extends MessageType { while (reader.pos < end) { let [fieldNo, wireType] = reader.tag(); switch (fieldNo) { - case /* uint64 chan_id = 1 [jstype = JS_STRING];*/ 1: + case /* uint64 chan_id = 1 [jstype = JS_STRING] */ 1: message.chanId = reader.uint64().toString(); break; - case /* int64 chan_capacity = 2 [deprecated = true];*/ 2: + case /* int64 chan_capacity = 2 [deprecated = true] */ 2: message.chanCapacity = reader.int64().toBigInt(); break; - case /* int64 amt_to_forward = 3 [deprecated = true];*/ 3: + case /* int64 amt_to_forward = 3 [deprecated = true] */ 3: message.amtToForward = reader.int64().toBigInt(); break; - case /* int64 fee = 4 [deprecated = true];*/ 4: + case /* int64 fee = 4 [deprecated = true] */ 4: message.fee = reader.int64().toBigInt(); break; case /* uint32 expiry */ 5: @@ -15884,7 +16947,7 @@ class Hop$Type extends MessageType { case /* string pub_key */ 8: message.pubKey = reader.string(); break; - case /* bool tlv_payload = 9 [deprecated = true];*/ 9: + case /* bool tlv_payload = 9 [deprecated = true] */ 9: message.tlvPayload = reader.bool(); break; case /* lnrpc.MPPRecord mpp_record */ 10: @@ -15930,7 +16993,7 @@ class Hop$Type extends MessageType { case 2: val = reader.bytes(); break; - default: throw new globalThis.Error("unknown map entry field for field lnrpc.Hop.custom_records"); + default: throw new globalThis.Error("unknown map entry field for lnrpc.Hop.custom_records"); } } map[key ?? "0"] = val ?? new Uint8Array(0); @@ -15966,12 +17029,12 @@ class Hop$Type extends MessageType { /* lnrpc.MPPRecord mpp_record = 10; */ if (message.mppRecord) MPPRecord.internalBinaryWrite(message.mppRecord, writer.tag(10, WireType.LengthDelimited).fork(), options).join(); + /* map custom_records = 11; */ + for (let k of globalThis.Object.keys(message.customRecords)) + writer.tag(11, WireType.LengthDelimited).fork().tag(1, WireType.Varint).uint64(k).tag(2, WireType.LengthDelimited).bytes(message.customRecords[k]).join(); /* lnrpc.AMPRecord amp_record = 12; */ if (message.ampRecord) AMPRecord.internalBinaryWrite(message.ampRecord, writer.tag(12, WireType.LengthDelimited).fork(), options).join(); - /* map custom_records = 11; */ - for (let k of Object.keys(message.customRecords)) - writer.tag(11, WireType.LengthDelimited).fork().tag(1, WireType.Varint).uint64(k).tag(2, WireType.LengthDelimited).bytes(message.customRecords[k]).join(); /* bytes metadata = 13; */ if (message.metadata.length) writer.tag(13, WireType.LengthDelimited).bytes(message.metadata); @@ -16003,8 +17066,9 @@ class MPPRecord$Type extends MessageType { ]); } create(value?: PartialMessage): MPPRecord { - const message = { paymentAddr: new Uint8Array(0), totalAmtMsat: 0n }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.paymentAddr = new Uint8Array(0); + message.totalAmtMsat = 0n; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -16032,12 +17096,12 @@ class MPPRecord$Type extends MessageType { return message; } internalBinaryWrite(message: MPPRecord, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter { - /* bytes payment_addr = 11; */ - if (message.paymentAddr.length) - writer.tag(11, WireType.LengthDelimited).bytes(message.paymentAddr); /* int64 total_amt_msat = 10; */ if (message.totalAmtMsat !== 0n) writer.tag(10, WireType.Varint).int64(message.totalAmtMsat); + /* bytes payment_addr = 11; */ + if (message.paymentAddr.length) + writer.tag(11, WireType.LengthDelimited).bytes(message.paymentAddr); let u = options.writeUnknownFields; if (u !== false) (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer); @@ -16058,8 +17122,10 @@ class AMPRecord$Type extends MessageType { ]); } create(value?: PartialMessage): AMPRecord { - const message = { rootShare: new Uint8Array(0), setId: new Uint8Array(0), childIndex: 0 }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.rootShare = new Uint8Array(0); + message.setId = new Uint8Array(0); + message.childIndex = 0; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -16116,14 +17182,23 @@ class Route$Type extends MessageType { { no: 1, name: "total_time_lock", kind: "scalar", T: 13 /*ScalarType.UINT32*/ }, { no: 2, name: "total_fees", kind: "scalar", T: 3 /*ScalarType.INT64*/, L: 0 /*LongType.BIGINT*/ }, { no: 3, name: "total_amt", kind: "scalar", T: 3 /*ScalarType.INT64*/, L: 0 /*LongType.BIGINT*/ }, - { no: 4, name: "hops", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => Hop }, + { no: 4, name: "hops", kind: "message", repeat: 2 /*RepeatType.UNPACKED*/, T: () => Hop }, { no: 5, name: "total_fees_msat", kind: "scalar", T: 3 /*ScalarType.INT64*/, L: 0 /*LongType.BIGINT*/ }, - { no: 6, name: "total_amt_msat", kind: "scalar", T: 3 /*ScalarType.INT64*/, L: 0 /*LongType.BIGINT*/ } + { no: 6, name: "total_amt_msat", kind: "scalar", T: 3 /*ScalarType.INT64*/, L: 0 /*LongType.BIGINT*/ }, + { no: 7, name: "first_hop_amount_msat", kind: "scalar", T: 3 /*ScalarType.INT64*/, L: 0 /*LongType.BIGINT*/ }, + { no: 8, name: "custom_channel_data", kind: "scalar", T: 12 /*ScalarType.BYTES*/ } ]); } create(value?: PartialMessage): Route { - const message = { totalTimeLock: 0, totalFees: 0n, totalAmt: 0n, hops: [], totalFeesMsat: 0n, totalAmtMsat: 0n }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.totalTimeLock = 0; + message.totalFees = 0n; + message.totalAmt = 0n; + message.hops = []; + message.totalFeesMsat = 0n; + message.totalAmtMsat = 0n; + message.firstHopAmountMsat = 0n; + message.customChannelData = new Uint8Array(0); if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -16136,10 +17211,10 @@ class Route$Type extends MessageType { case /* uint32 total_time_lock */ 1: message.totalTimeLock = reader.uint32(); break; - case /* int64 total_fees = 2 [deprecated = true];*/ 2: + case /* int64 total_fees = 2 [deprecated = true] */ 2: message.totalFees = reader.int64().toBigInt(); break; - case /* int64 total_amt = 3 [deprecated = true];*/ 3: + case /* int64 total_amt = 3 [deprecated = true] */ 3: message.totalAmt = reader.int64().toBigInt(); break; case /* repeated lnrpc.Hop hops */ 4: @@ -16151,6 +17226,12 @@ class Route$Type extends MessageType { case /* int64 total_amt_msat */ 6: message.totalAmtMsat = reader.int64().toBigInt(); break; + case /* int64 first_hop_amount_msat */ 7: + message.firstHopAmountMsat = reader.int64().toBigInt(); + break; + case /* bytes custom_channel_data */ 8: + message.customChannelData = reader.bytes(); + break; default: let u = options.readUnknownField; if (u === "throw") @@ -16181,6 +17262,12 @@ class Route$Type extends MessageType { /* int64 total_amt_msat = 6; */ if (message.totalAmtMsat !== 0n) writer.tag(6, WireType.Varint).int64(message.totalAmtMsat); + /* int64 first_hop_amount_msat = 7; */ + if (message.firstHopAmountMsat !== 0n) + writer.tag(7, WireType.Varint).int64(message.firstHopAmountMsat); + /* bytes custom_channel_data = 8; */ + if (message.customChannelData.length) + writer.tag(8, WireType.LengthDelimited).bytes(message.customChannelData); let u = options.writeUnknownFields; if (u !== false) (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer); @@ -16200,8 +17287,9 @@ class NodeInfoRequest$Type extends MessageType { ]); } create(value?: PartialMessage): NodeInfoRequest { - const message = { pubKey: "", includeChannels: false }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.pubKey = ""; + message.includeChannels = false; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -16252,12 +17340,14 @@ class NodeInfo$Type extends MessageType { { no: 1, name: "node", kind: "message", T: () => LightningNode }, { no: 2, name: "num_channels", kind: "scalar", T: 13 /*ScalarType.UINT32*/ }, { no: 3, name: "total_capacity", kind: "scalar", T: 3 /*ScalarType.INT64*/, L: 0 /*LongType.BIGINT*/ }, - { no: 4, name: "channels", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => ChannelEdge } + { no: 4, name: "channels", kind: "message", repeat: 2 /*RepeatType.UNPACKED*/, T: () => ChannelEdge } ]); } create(value?: PartialMessage): NodeInfo { - const message = { numChannels: 0, totalCapacity: 0n, channels: [] }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.numChannels = 0; + message.totalCapacity = 0n; + message.channels = []; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -16320,15 +17410,21 @@ class LightningNode$Type extends MessageType { { no: 1, name: "last_update", kind: "scalar", T: 13 /*ScalarType.UINT32*/ }, { no: 2, name: "pub_key", kind: "scalar", T: 9 /*ScalarType.STRING*/ }, { no: 3, name: "alias", kind: "scalar", T: 9 /*ScalarType.STRING*/ }, - { no: 4, name: "addresses", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => NodeAddress }, + { no: 4, name: "addresses", kind: "message", repeat: 2 /*RepeatType.UNPACKED*/, T: () => NodeAddress }, { no: 5, name: "color", kind: "scalar", T: 9 /*ScalarType.STRING*/ }, { no: 6, name: "features", kind: "map", K: 13 /*ScalarType.UINT32*/, V: { kind: "message", T: () => Feature } }, { no: 7, name: "custom_records", kind: "map", K: 4 /*ScalarType.UINT64*/, V: { kind: "scalar", T: 12 /*ScalarType.BYTES*/ } } ]); } create(value?: PartialMessage): LightningNode { - const message = { lastUpdate: 0, pubKey: "", alias: "", addresses: [], color: "", features: {}, customRecords: {} }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.lastUpdate = 0; + message.pubKey = ""; + message.alias = ""; + message.addresses = []; + message.color = ""; + message.features = {}; + message.customRecords = {}; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -16381,7 +17477,7 @@ class LightningNode$Type extends MessageType { case 2: val = Feature.internalBinaryRead(reader, reader.uint32(), options); break; - default: throw new globalThis.Error("unknown map entry field for field lnrpc.LightningNode.features"); + default: throw new globalThis.Error("unknown map entry field for lnrpc.LightningNode.features"); } } map[key ?? 0] = val ?? Feature.create(); @@ -16397,7 +17493,7 @@ class LightningNode$Type extends MessageType { case 2: val = reader.bytes(); break; - default: throw new globalThis.Error("unknown map entry field for field lnrpc.LightningNode.custom_records"); + default: throw new globalThis.Error("unknown map entry field for lnrpc.LightningNode.custom_records"); } } map[key ?? "0"] = val ?? new Uint8Array(0); @@ -16419,14 +17515,14 @@ class LightningNode$Type extends MessageType { if (message.color !== "") writer.tag(5, WireType.LengthDelimited).string(message.color); /* map features = 6; */ - for (let k of Object.keys(message.features)) { + for (let k of globalThis.Object.keys(message.features)) { writer.tag(6, WireType.LengthDelimited).fork().tag(1, WireType.Varint).uint32(parseInt(k)); writer.tag(2, WireType.LengthDelimited).fork(); Feature.internalBinaryWrite(message.features[k as any], writer, options); writer.join().join(); } /* map custom_records = 7; */ - for (let k of Object.keys(message.customRecords)) + for (let k of globalThis.Object.keys(message.customRecords)) writer.tag(7, WireType.LengthDelimited).fork().tag(1, WireType.Varint).uint64(k).tag(2, WireType.LengthDelimited).bytes(message.customRecords[k]).join(); let u = options.writeUnknownFields; if (u !== false) @@ -16447,8 +17543,9 @@ class NodeAddress$Type extends MessageType { ]); } create(value?: PartialMessage): NodeAddress { - const message = { network: "", addr: "" }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.network = ""; + message.addr = ""; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -16509,8 +17606,17 @@ class RoutingPolicy$Type extends MessageType { ]); } create(value?: PartialMessage): RoutingPolicy { - const message = { timeLockDelta: 0, minHtlc: 0n, feeBaseMsat: 0n, feeRateMilliMsat: 0n, disabled: false, maxHtlcMsat: 0n, lastUpdate: 0, customRecords: {}, inboundFeeBaseMsat: 0, inboundFeeRateMilliMsat: 0 }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.timeLockDelta = 0; + message.minHtlc = 0n; + message.feeBaseMsat = 0n; + message.feeRateMilliMsat = 0n; + message.disabled = false; + message.maxHtlcMsat = 0n; + message.lastUpdate = 0; + message.customRecords = {}; + message.inboundFeeBaseMsat = 0; + message.inboundFeeRateMilliMsat = 0; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -16572,7 +17678,7 @@ class RoutingPolicy$Type extends MessageType { case 2: val = reader.bytes(); break; - default: throw new globalThis.Error("unknown map entry field for field lnrpc.RoutingPolicy.custom_records"); + default: throw new globalThis.Error("unknown map entry field for lnrpc.RoutingPolicy.custom_records"); } } map[key ?? "0"] = val ?? new Uint8Array(0); @@ -16600,7 +17706,7 @@ class RoutingPolicy$Type extends MessageType { if (message.lastUpdate !== 0) writer.tag(7, WireType.Varint).uint32(message.lastUpdate); /* map custom_records = 8; */ - for (let k of Object.keys(message.customRecords)) + for (let k of globalThis.Object.keys(message.customRecords)) writer.tag(8, WireType.LengthDelimited).fork().tag(1, WireType.Varint).uint64(k).tag(2, WireType.LengthDelimited).bytes(message.customRecords[k]).join(); /* int32 inbound_fee_base_msat = 9; */ if (message.inboundFeeBaseMsat !== 0) @@ -16634,8 +17740,14 @@ class ChannelEdge$Type extends MessageType { ]); } create(value?: PartialMessage): ChannelEdge { - const message = { channelId: "0", chanPoint: "", lastUpdate: 0, node1Pub: "", node2Pub: "", capacity: 0n, customRecords: {} }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.channelId = "0"; + message.chanPoint = ""; + message.lastUpdate = 0; + message.node1Pub = ""; + message.node2Pub = ""; + message.capacity = 0n; + message.customRecords = {}; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -16645,13 +17757,13 @@ class ChannelEdge$Type extends MessageType { while (reader.pos < end) { let [fieldNo, wireType] = reader.tag(); switch (fieldNo) { - case /* uint64 channel_id = 1 [jstype = JS_STRING];*/ 1: + case /* uint64 channel_id = 1 [jstype = JS_STRING] */ 1: message.channelId = reader.uint64().toString(); break; case /* string chan_point */ 2: message.chanPoint = reader.string(); break; - case /* uint32 last_update = 3 [deprecated = true];*/ 3: + case /* uint32 last_update = 3 [deprecated = true] */ 3: message.lastUpdate = reader.uint32(); break; case /* string node1_pub */ 4: @@ -16694,7 +17806,7 @@ class ChannelEdge$Type extends MessageType { case 2: val = reader.bytes(); break; - default: throw new globalThis.Error("unknown map entry field for field lnrpc.ChannelEdge.custom_records"); + default: throw new globalThis.Error("unknown map entry field for lnrpc.ChannelEdge.custom_records"); } } map[key ?? "0"] = val ?? new Uint8Array(0); @@ -16725,7 +17837,7 @@ class ChannelEdge$Type extends MessageType { if (message.node2Policy) RoutingPolicy.internalBinaryWrite(message.node2Policy, writer.tag(8, WireType.LengthDelimited).fork(), options).join(); /* map custom_records = 9; */ - for (let k of Object.keys(message.customRecords)) + for (let k of globalThis.Object.keys(message.customRecords)) writer.tag(9, WireType.LengthDelimited).fork().tag(1, WireType.Varint).uint64(k).tag(2, WireType.LengthDelimited).bytes(message.customRecords[k]).join(); let u = options.writeUnknownFields; if (u !== false) @@ -16745,8 +17857,8 @@ class ChannelGraphRequest$Type extends MessageType { ]); } create(value?: PartialMessage): ChannelGraphRequest { - const message = { includeUnannounced: false }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.includeUnannounced = false; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -16788,13 +17900,14 @@ export const ChannelGraphRequest = new ChannelGraphRequest$Type(); class ChannelGraph$Type extends MessageType { constructor() { super("lnrpc.ChannelGraph", [ - { no: 1, name: "nodes", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => LightningNode }, - { no: 2, name: "edges", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => ChannelEdge } + { no: 1, name: "nodes", kind: "message", repeat: 2 /*RepeatType.UNPACKED*/, T: () => LightningNode }, + { no: 2, name: "edges", kind: "message", repeat: 2 /*RepeatType.UNPACKED*/, T: () => ChannelEdge } ]); } create(value?: PartialMessage): ChannelGraph { - const message = { nodes: [], edges: [] }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.nodes = []; + message.edges = []; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -16846,8 +17959,8 @@ class NodeMetricsRequest$Type extends MessageType { ]); } create(value?: PartialMessage): NodeMetricsRequest { - const message = { types: [] }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.types = []; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -16901,8 +18014,8 @@ class NodeMetricsResponse$Type extends MessageType { ]); } create(value?: PartialMessage): NodeMetricsResponse { - const message = { betweennessCentrality: {} }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.betweennessCentrality = {}; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -16937,14 +18050,14 @@ class NodeMetricsResponse$Type extends MessageType { case 2: val = FloatMetric.internalBinaryRead(reader, reader.uint32(), options); break; - default: throw new globalThis.Error("unknown map entry field for field lnrpc.NodeMetricsResponse.betweenness_centrality"); + default: throw new globalThis.Error("unknown map entry field for lnrpc.NodeMetricsResponse.betweenness_centrality"); } } map[key ?? ""] = val ?? FloatMetric.create(); } internalBinaryWrite(message: NodeMetricsResponse, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter { /* map betweenness_centrality = 1; */ - for (let k of Object.keys(message.betweennessCentrality)) { + for (let k of globalThis.Object.keys(message.betweennessCentrality)) { writer.tag(1, WireType.LengthDelimited).fork().tag(1, WireType.LengthDelimited).string(k); writer.tag(2, WireType.LengthDelimited).fork(); FloatMetric.internalBinaryWrite(message.betweennessCentrality[k], writer, options); @@ -16969,8 +18082,9 @@ class FloatMetric$Type extends MessageType { ]); } create(value?: PartialMessage): FloatMetric { - const message = { value: 0, normalizedValue: 0 }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.value = 0; + message.normalizedValue = 0; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -17023,8 +18137,9 @@ class ChanInfoRequest$Type extends MessageType { ]); } create(value?: PartialMessage): ChanInfoRequest { - const message = { chanId: "0", chanPoint: "" }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.chanId = "0"; + message.chanPoint = ""; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -17034,7 +18149,7 @@ class ChanInfoRequest$Type extends MessageType { while (reader.pos < end) { let [fieldNo, wireType] = reader.tag(); switch (fieldNo) { - case /* uint64 chan_id = 1 [jstype = JS_STRING];*/ 1: + case /* uint64 chan_id = 1 [jstype = JS_STRING] */ 1: message.chanId = reader.uint64().toString(); break; case /* string chan_point */ 2: @@ -17074,14 +18189,26 @@ class NetworkInfoRequest$Type extends MessageType { super("lnrpc.NetworkInfoRequest", []); } create(value?: PartialMessage): NetworkInfoRequest { - const message = {}; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); if (value !== undefined) reflectionMergePartial(this, message, value); return message; } internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: NetworkInfoRequest): NetworkInfoRequest { - return target ?? this.create(); + let message = target ?? this.create(), end = reader.pos + length; + while (reader.pos < end) { + let [fieldNo, wireType] = reader.tag(); + switch (fieldNo) { + default: + let u = options.readUnknownField; + if (u === "throw") + throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`); + let d = reader.skip(wireType); + if (u !== false) + (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d); + } + } + return message; } internalBinaryWrite(message: NetworkInfoRequest, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter { let u = options.writeUnknownFields; @@ -17112,8 +18239,18 @@ class NetworkInfo$Type extends MessageType { ]); } create(value?: PartialMessage): NetworkInfo { - const message = { graphDiameter: 0, avgOutDegree: 0, maxOutDegree: 0, numNodes: 0, numChannels: 0, totalNetworkCapacity: 0n, avgChannelSize: 0, minChannelSize: 0n, maxChannelSize: 0n, medianChannelSizeSat: 0n, numZombieChans: 0n }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.graphDiameter = 0; + message.avgOutDegree = 0; + message.maxOutDegree = 0; + message.numNodes = 0; + message.numChannels = 0; + message.totalNetworkCapacity = 0n; + message.avgChannelSize = 0; + message.minChannelSize = 0n; + message.maxChannelSize = 0n; + message.medianChannelSizeSat = 0n; + message.numZombieChans = 0n; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -17217,14 +18354,26 @@ class StopRequest$Type extends MessageType { super("lnrpc.StopRequest", []); } create(value?: PartialMessage): StopRequest { - const message = {}; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); if (value !== undefined) reflectionMergePartial(this, message, value); return message; } internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: StopRequest): StopRequest { - return target ?? this.create(); + let message = target ?? this.create(), end = reader.pos + length; + while (reader.pos < end) { + let [fieldNo, wireType] = reader.tag(); + switch (fieldNo) { + default: + let u = options.readUnknownField; + if (u === "throw") + throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`); + let d = reader.skip(wireType); + if (u !== false) + (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d); + } + } + return message; } internalBinaryWrite(message: StopRequest, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter { let u = options.writeUnknownFields; @@ -17240,19 +18389,40 @@ export const StopRequest = new StopRequest$Type(); // @generated message type with reflection information, may provide speed optimized methods class StopResponse$Type extends MessageType { constructor() { - super("lnrpc.StopResponse", []); + super("lnrpc.StopResponse", [ + { no: 1, name: "status", kind: "scalar", T: 9 /*ScalarType.STRING*/ } + ]); } create(value?: PartialMessage): StopResponse { - const message = {}; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.status = ""; if (value !== undefined) reflectionMergePartial(this, message, value); return message; } internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: StopResponse): StopResponse { - return target ?? this.create(); + let message = target ?? this.create(), end = reader.pos + length; + while (reader.pos < end) { + let [fieldNo, wireType] = reader.tag(); + switch (fieldNo) { + case /* string status */ 1: + message.status = reader.string(); + break; + default: + let u = options.readUnknownField; + if (u === "throw") + throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`); + let d = reader.skip(wireType); + if (u !== false) + (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d); + } + } + return message; } internalBinaryWrite(message: StopResponse, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter { + /* string status = 1; */ + if (message.status !== "") + writer.tag(1, WireType.LengthDelimited).string(message.status); let u = options.writeUnknownFields; if (u !== false) (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer); @@ -17269,14 +18439,26 @@ class GraphTopologySubscription$Type extends MessageType): GraphTopologySubscription { - const message = {}; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); if (value !== undefined) reflectionMergePartial(this, message, value); return message; } internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: GraphTopologySubscription): GraphTopologySubscription { - return target ?? this.create(); + let message = target ?? this.create(), end = reader.pos + length; + while (reader.pos < end) { + let [fieldNo, wireType] = reader.tag(); + switch (fieldNo) { + default: + let u = options.readUnknownField; + if (u === "throw") + throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`); + let d = reader.skip(wireType); + if (u !== false) + (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d); + } + } + return message; } internalBinaryWrite(message: GraphTopologySubscription, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter { let u = options.writeUnknownFields; @@ -17293,14 +18475,16 @@ export const GraphTopologySubscription = new GraphTopologySubscription$Type(); class GraphTopologyUpdate$Type extends MessageType { constructor() { super("lnrpc.GraphTopologyUpdate", [ - { no: 1, name: "node_updates", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => NodeUpdate }, - { no: 2, name: "channel_updates", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => ChannelEdgeUpdate }, - { no: 3, name: "closed_chans", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => ClosedChannelUpdate } + { no: 1, name: "node_updates", kind: "message", repeat: 2 /*RepeatType.UNPACKED*/, T: () => NodeUpdate }, + { no: 2, name: "channel_updates", kind: "message", repeat: 2 /*RepeatType.UNPACKED*/, T: () => ChannelEdgeUpdate }, + { no: 3, name: "closed_chans", kind: "message", repeat: 2 /*RepeatType.UNPACKED*/, T: () => ClosedChannelUpdate } ]); } create(value?: PartialMessage): GraphTopologyUpdate { - const message = { nodeUpdates: [], channelUpdates: [], closedChans: [] }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.nodeUpdates = []; + message.channelUpdates = []; + message.closedChans = []; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -17359,13 +18543,19 @@ class NodeUpdate$Type extends MessageType { { no: 3, name: "global_features", kind: "scalar", T: 12 /*ScalarType.BYTES*/ }, { no: 4, name: "alias", kind: "scalar", T: 9 /*ScalarType.STRING*/ }, { no: 5, name: "color", kind: "scalar", T: 9 /*ScalarType.STRING*/ }, - { no: 7, name: "node_addresses", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => NodeAddress }, + { no: 7, name: "node_addresses", kind: "message", repeat: 2 /*RepeatType.UNPACKED*/, T: () => NodeAddress }, { no: 6, name: "features", kind: "map", K: 13 /*ScalarType.UINT32*/, V: { kind: "message", T: () => Feature } } ]); } create(value?: PartialMessage): NodeUpdate { - const message = { addresses: [], identityKey: "", globalFeatures: new Uint8Array(0), alias: "", color: "", nodeAddresses: [], features: {} }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.addresses = []; + message.identityKey = ""; + message.globalFeatures = new Uint8Array(0); + message.alias = ""; + message.color = ""; + message.nodeAddresses = []; + message.features = {}; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -17375,13 +18565,13 @@ class NodeUpdate$Type extends MessageType { while (reader.pos < end) { let [fieldNo, wireType] = reader.tag(); switch (fieldNo) { - case /* repeated string addresses = 1 [deprecated = true];*/ 1: + case /* repeated string addresses = 1 [deprecated = true] */ 1: message.addresses.push(reader.string()); break; case /* string identity_key */ 2: message.identityKey = reader.string(); break; - case /* bytes global_features = 3 [deprecated = true];*/ 3: + case /* bytes global_features = 3 [deprecated = true] */ 3: message.globalFeatures = reader.bytes(); break; case /* string alias */ 4: @@ -17418,7 +18608,7 @@ class NodeUpdate$Type extends MessageType { case 2: val = Feature.internalBinaryRead(reader, reader.uint32(), options); break; - default: throw new globalThis.Error("unknown map entry field for field lnrpc.NodeUpdate.features"); + default: throw new globalThis.Error("unknown map entry field for lnrpc.NodeUpdate.features"); } } map[key ?? 0] = val ?? Feature.create(); @@ -17439,16 +18629,16 @@ class NodeUpdate$Type extends MessageType { /* string color = 5; */ if (message.color !== "") writer.tag(5, WireType.LengthDelimited).string(message.color); - /* repeated lnrpc.NodeAddress node_addresses = 7; */ - for (let i = 0; i < message.nodeAddresses.length; i++) - NodeAddress.internalBinaryWrite(message.nodeAddresses[i], writer.tag(7, WireType.LengthDelimited).fork(), options).join(); /* map features = 6; */ - for (let k of Object.keys(message.features)) { + for (let k of globalThis.Object.keys(message.features)) { writer.tag(6, WireType.LengthDelimited).fork().tag(1, WireType.Varint).uint32(parseInt(k)); writer.tag(2, WireType.LengthDelimited).fork(); Feature.internalBinaryWrite(message.features[k as any], writer, options); writer.join().join(); } + /* repeated lnrpc.NodeAddress node_addresses = 7; */ + for (let i = 0; i < message.nodeAddresses.length; i++) + NodeAddress.internalBinaryWrite(message.nodeAddresses[i], writer.tag(7, WireType.LengthDelimited).fork(), options).join(); let u = options.writeUnknownFields; if (u !== false) (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer); @@ -17472,8 +18662,11 @@ class ChannelEdgeUpdate$Type extends MessageType { ]); } create(value?: PartialMessage): ChannelEdgeUpdate { - const message = { chanId: "0", capacity: 0n, advertisingNode: "", connectingNode: "" }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.chanId = "0"; + message.capacity = 0n; + message.advertisingNode = ""; + message.connectingNode = ""; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -17483,7 +18676,7 @@ class ChannelEdgeUpdate$Type extends MessageType { while (reader.pos < end) { let [fieldNo, wireType] = reader.tag(); switch (fieldNo) { - case /* uint64 chan_id = 1 [jstype = JS_STRING];*/ 1: + case /* uint64 chan_id = 1 [jstype = JS_STRING] */ 1: message.chanId = reader.uint64().toString(); break; case /* lnrpc.ChannelPoint chan_point */ 2: @@ -17552,8 +18745,10 @@ class ClosedChannelUpdate$Type extends MessageType { ]); } create(value?: PartialMessage): ClosedChannelUpdate { - const message = { chanId: "0", capacity: 0n, closedHeight: 0 }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.chanId = "0"; + message.capacity = 0n; + message.closedHeight = 0; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -17563,7 +18758,7 @@ class ClosedChannelUpdate$Type extends MessageType { while (reader.pos < end) { let [fieldNo, wireType] = reader.tag(); switch (fieldNo) { - case /* uint64 chan_id = 1 [jstype = JS_STRING];*/ 1: + case /* uint64 chan_id = 1 [jstype = JS_STRING] */ 1: message.chanId = reader.uint64().toString(); break; case /* int64 capacity */ 2: @@ -17621,8 +18816,12 @@ class HopHint$Type extends MessageType { ]); } create(value?: PartialMessage): HopHint { - const message = { nodeId: "", chanId: "0", feeBaseMsat: 0, feeProportionalMillionths: 0, cltvExpiryDelta: 0 }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.nodeId = ""; + message.chanId = "0"; + message.feeBaseMsat = 0; + message.feeProportionalMillionths = 0; + message.cltvExpiryDelta = 0; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -17635,7 +18834,7 @@ class HopHint$Type extends MessageType { case /* string node_id */ 1: message.nodeId = reader.string(); break; - case /* uint64 chan_id = 2 [jstype = JS_STRING];*/ 2: + case /* uint64 chan_id = 2 [jstype = JS_STRING] */ 2: message.chanId = reader.uint64().toString(); break; case /* uint32 fee_base_msat */ 3: @@ -17692,8 +18891,8 @@ class SetID$Type extends MessageType { ]); } create(value?: PartialMessage): SetID { - const message = { setId: new Uint8Array(0) }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.setId = new Uint8Array(0); if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -17735,12 +18934,12 @@ export const SetID = new SetID$Type(); class RouteHint$Type extends MessageType { constructor() { super("lnrpc.RouteHint", [ - { no: 1, name: "hop_hints", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => HopHint } + { no: 1, name: "hop_hints", kind: "message", repeat: 2 /*RepeatType.UNPACKED*/, T: () => HopHint } ]); } create(value?: PartialMessage): RouteHint { - const message = { hopHints: [] }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.hopHints = []; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -17792,8 +18991,13 @@ class BlindedPaymentPath$Type extends MessageType { ]); } create(value?: PartialMessage): BlindedPaymentPath { - const message = { baseFeeMsat: 0n, proportionalFeeRate: 0, totalCltvDelta: 0, htlcMinMsat: 0n, htlcMaxMsat: 0n, features: [] }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.baseFeeMsat = 0n; + message.proportionalFeeRate = 0; + message.totalCltvDelta = 0; + message.htlcMinMsat = 0n; + message.htlcMaxMsat = 0n; + message.features = []; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -17881,12 +19085,14 @@ class BlindedPath$Type extends MessageType { super("lnrpc.BlindedPath", [ { no: 1, name: "introduction_node", kind: "scalar", T: 12 /*ScalarType.BYTES*/ }, { no: 2, name: "blinding_point", kind: "scalar", T: 12 /*ScalarType.BYTES*/ }, - { no: 3, name: "blinded_hops", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => BlindedHop } + { no: 3, name: "blinded_hops", kind: "message", repeat: 2 /*RepeatType.UNPACKED*/, T: () => BlindedHop } ]); } create(value?: PartialMessage): BlindedPath { - const message = { introductionNode: new Uint8Array(0), blindingPoint: new Uint8Array(0), blindedHops: [] }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.introductionNode = new Uint8Array(0); + message.blindingPoint = new Uint8Array(0); + message.blindedHops = []; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -17945,8 +19151,9 @@ class BlindedHop$Type extends MessageType { ]); } create(value?: PartialMessage): BlindedHop { - const message = { blindedNode: new Uint8Array(0), encryptedData: new Uint8Array(0) }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.blindedNode = new Uint8Array(0); + message.encryptedData = new Uint8Array(0); if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -18001,8 +19208,11 @@ class AMPInvoiceState$Type extends MessageType { ]); } create(value?: PartialMessage): AMPInvoiceState { - const message = { state: 0, settleIndex: 0n, settleTime: 0n, amtPaidMsat: 0n }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.state = 0; + message.settleIndex = 0n; + message.settleTime = 0n; + message.amtPaidMsat = 0n; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -18075,7 +19285,7 @@ class Invoice$Type extends MessageType { { no: 11, name: "expiry", kind: "scalar", T: 3 /*ScalarType.INT64*/, L: 0 /*LongType.BIGINT*/ }, { no: 12, name: "fallback_addr", kind: "scalar", T: 9 /*ScalarType.STRING*/ }, { no: 13, name: "cltv_expiry", kind: "scalar", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ }, - { no: 14, name: "route_hints", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => RouteHint }, + { no: 14, name: "route_hints", kind: "message", repeat: 2 /*RepeatType.UNPACKED*/, T: () => RouteHint }, { no: 15, name: "private", kind: "scalar", T: 8 /*ScalarType.BOOL*/ }, { no: 16, name: "add_index", kind: "scalar", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ }, { no: 17, name: "settle_index", kind: "scalar", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ }, @@ -18083,7 +19293,7 @@ class Invoice$Type extends MessageType { { no: 19, name: "amt_paid_sat", kind: "scalar", T: 3 /*ScalarType.INT64*/, L: 0 /*LongType.BIGINT*/ }, { no: 20, name: "amt_paid_msat", kind: "scalar", T: 3 /*ScalarType.INT64*/, L: 0 /*LongType.BIGINT*/ }, { no: 21, name: "state", kind: "enum", T: () => ["lnrpc.Invoice.InvoiceState", Invoice_InvoiceState] }, - { no: 22, name: "htlcs", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => InvoiceHTLC }, + { no: 22, name: "htlcs", kind: "message", repeat: 2 /*RepeatType.UNPACKED*/, T: () => InvoiceHTLC }, { no: 24, name: "features", kind: "map", K: 13 /*ScalarType.UINT32*/, V: { kind: "message", T: () => Feature } }, { no: 25, name: "is_keysend", kind: "scalar", T: 8 /*ScalarType.BOOL*/ }, { no: 26, name: "payment_addr", kind: "scalar", T: 12 /*ScalarType.BYTES*/ }, @@ -18094,8 +19304,35 @@ class Invoice$Type extends MessageType { ]); } create(value?: PartialMessage): Invoice { - const message = { memo: "", rPreimage: new Uint8Array(0), rHash: new Uint8Array(0), value: 0n, valueMsat: 0n, settled: false, creationDate: 0n, settleDate: 0n, paymentRequest: "", descriptionHash: new Uint8Array(0), expiry: 0n, fallbackAddr: "", cltvExpiry: 0n, routeHints: [], private: false, addIndex: 0n, settleIndex: 0n, amtPaid: 0n, amtPaidSat: 0n, amtPaidMsat: 0n, state: 0, htlcs: [], features: {}, isKeysend: false, paymentAddr: new Uint8Array(0), isAmp: false, ampInvoiceState: {}, isBlinded: false }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.memo = ""; + message.rPreimage = new Uint8Array(0); + message.rHash = new Uint8Array(0); + message.value = 0n; + message.valueMsat = 0n; + message.settled = false; + message.creationDate = 0n; + message.settleDate = 0n; + message.paymentRequest = ""; + message.descriptionHash = new Uint8Array(0); + message.expiry = 0n; + message.fallbackAddr = ""; + message.cltvExpiry = 0n; + message.routeHints = []; + message.private = false; + message.addIndex = 0n; + message.settleIndex = 0n; + message.amtPaid = 0n; + message.amtPaidSat = 0n; + message.amtPaidMsat = 0n; + message.state = 0; + message.htlcs = []; + message.features = {}; + message.isKeysend = false; + message.paymentAddr = new Uint8Array(0); + message.isAmp = false; + message.ampInvoiceState = {}; + message.isBlinded = false; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -18120,7 +19357,7 @@ class Invoice$Type extends MessageType { case /* int64 value_msat */ 23: message.valueMsat = reader.int64().toBigInt(); break; - case /* bool settled = 6 [deprecated = true];*/ 6: + case /* bool settled = 6 [deprecated = true] */ 6: message.settled = reader.bool(); break; case /* int64 creation_date */ 7: @@ -18156,7 +19393,7 @@ class Invoice$Type extends MessageType { case /* uint64 settle_index */ 17: message.settleIndex = reader.uint64().toBigInt(); break; - case /* int64 amt_paid = 18 [deprecated = true];*/ 18: + case /* int64 amt_paid = 18 [deprecated = true] */ 18: message.amtPaid = reader.int64().toBigInt(); break; case /* int64 amt_paid_sat */ 19: @@ -18214,7 +19451,7 @@ class Invoice$Type extends MessageType { case 2: val = Feature.internalBinaryRead(reader, reader.uint32(), options); break; - default: throw new globalThis.Error("unknown map entry field for field lnrpc.Invoice.features"); + default: throw new globalThis.Error("unknown map entry field for lnrpc.Invoice.features"); } } map[key ?? 0] = val ?? Feature.create(); @@ -18230,7 +19467,7 @@ class Invoice$Type extends MessageType { case 2: val = AMPInvoiceState.internalBinaryRead(reader, reader.uint32(), options); break; - default: throw new globalThis.Error("unknown map entry field for field lnrpc.Invoice.amp_invoice_state"); + default: throw new globalThis.Error("unknown map entry field for lnrpc.Invoice.amp_invoice_state"); } } map[key ?? ""] = val ?? AMPInvoiceState.create(); @@ -18248,9 +19485,6 @@ class Invoice$Type extends MessageType { /* int64 value = 5; */ if (message.value !== 0n) writer.tag(5, WireType.Varint).int64(message.value); - /* int64 value_msat = 23; */ - if (message.valueMsat !== 0n) - writer.tag(23, WireType.Varint).int64(message.valueMsat); /* bool settled = 6 [deprecated = true]; */ if (message.settled !== false) writer.tag(6, WireType.Varint).bool(message.settled); @@ -18302,8 +19536,11 @@ class Invoice$Type extends MessageType { /* repeated lnrpc.InvoiceHTLC htlcs = 22; */ for (let i = 0; i < message.htlcs.length; i++) InvoiceHTLC.internalBinaryWrite(message.htlcs[i], writer.tag(22, WireType.LengthDelimited).fork(), options).join(); + /* int64 value_msat = 23; */ + if (message.valueMsat !== 0n) + writer.tag(23, WireType.Varint).int64(message.valueMsat); /* map features = 24; */ - for (let k of Object.keys(message.features)) { + for (let k of globalThis.Object.keys(message.features)) { writer.tag(24, WireType.LengthDelimited).fork().tag(1, WireType.Varint).uint32(parseInt(k)); writer.tag(2, WireType.LengthDelimited).fork(); Feature.internalBinaryWrite(message.features[k as any], writer, options); @@ -18319,7 +19556,7 @@ class Invoice$Type extends MessageType { if (message.isAmp !== false) writer.tag(27, WireType.Varint).bool(message.isAmp); /* map amp_invoice_state = 28; */ - for (let k of Object.keys(message.ampInvoiceState)) { + for (let k of globalThis.Object.keys(message.ampInvoiceState)) { writer.tag(28, WireType.LengthDelimited).fork().tag(1, WireType.LengthDelimited).string(k); writer.tag(2, WireType.LengthDelimited).fork(); AMPInvoiceState.internalBinaryWrite(message.ampInvoiceState[k], writer, options); @@ -18352,8 +19589,8 @@ class BlindedPathConfig$Type extends MessageType { ]); } create(value?: PartialMessage): BlindedPathConfig { - const message = { nodeOmissionList: [] }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.nodeOmissionList = []; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -18423,12 +19660,23 @@ class InvoiceHTLC$Type extends MessageType { { no: 8, name: "state", kind: "enum", T: () => ["lnrpc.InvoiceHTLCState", InvoiceHTLCState] }, { no: 9, name: "custom_records", kind: "map", K: 4 /*ScalarType.UINT64*/, V: { kind: "scalar", T: 12 /*ScalarType.BYTES*/ } }, { no: 10, name: "mpp_total_amt_msat", kind: "scalar", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ }, - { no: 11, name: "amp", kind: "message", T: () => AMP } + { no: 11, name: "amp", kind: "message", T: () => AMP }, + { no: 12, name: "custom_channel_data", kind: "scalar", T: 12 /*ScalarType.BYTES*/ } ]); } create(value?: PartialMessage): InvoiceHTLC { - const message = { chanId: "0", htlcIndex: 0n, amtMsat: 0n, acceptHeight: 0, acceptTime: 0n, resolveTime: 0n, expiryHeight: 0, state: 0, customRecords: {}, mppTotalAmtMsat: 0n }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.chanId = "0"; + message.htlcIndex = 0n; + message.amtMsat = 0n; + message.acceptHeight = 0; + message.acceptTime = 0n; + message.resolveTime = 0n; + message.expiryHeight = 0; + message.state = 0; + message.customRecords = {}; + message.mppTotalAmtMsat = 0n; + message.customChannelData = new Uint8Array(0); if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -18438,7 +19686,7 @@ class InvoiceHTLC$Type extends MessageType { while (reader.pos < end) { let [fieldNo, wireType] = reader.tag(); switch (fieldNo) { - case /* uint64 chan_id = 1 [jstype = JS_STRING];*/ 1: + case /* uint64 chan_id = 1 [jstype = JS_STRING] */ 1: message.chanId = reader.uint64().toString(); break; case /* uint64 htlc_index */ 2: @@ -18471,6 +19719,9 @@ class InvoiceHTLC$Type extends MessageType { case /* lnrpc.AMP amp */ 11: message.amp = AMP.internalBinaryRead(reader, reader.uint32(), options, message.amp); break; + case /* bytes custom_channel_data */ 12: + message.customChannelData = reader.bytes(); + break; default: let u = options.readUnknownField; if (u === "throw") @@ -18493,7 +19744,7 @@ class InvoiceHTLC$Type extends MessageType { case 2: val = reader.bytes(); break; - default: throw new globalThis.Error("unknown map entry field for field lnrpc.InvoiceHTLC.custom_records"); + default: throw new globalThis.Error("unknown map entry field for lnrpc.InvoiceHTLC.custom_records"); } } map[key ?? "0"] = val ?? new Uint8Array(0); @@ -18524,7 +19775,7 @@ class InvoiceHTLC$Type extends MessageType { if (message.state !== 0) writer.tag(8, WireType.Varint).int32(message.state); /* map custom_records = 9; */ - for (let k of Object.keys(message.customRecords)) + for (let k of globalThis.Object.keys(message.customRecords)) writer.tag(9, WireType.LengthDelimited).fork().tag(1, WireType.Varint).uint64(k).tag(2, WireType.LengthDelimited).bytes(message.customRecords[k]).join(); /* uint64 mpp_total_amt_msat = 10; */ if (message.mppTotalAmtMsat !== 0n) @@ -18532,6 +19783,9 @@ class InvoiceHTLC$Type extends MessageType { /* lnrpc.AMP amp = 11; */ if (message.amp) AMP.internalBinaryWrite(message.amp, writer.tag(11, WireType.LengthDelimited).fork(), options).join(); + /* bytes custom_channel_data = 12; */ + if (message.customChannelData.length) + writer.tag(12, WireType.LengthDelimited).bytes(message.customChannelData); let u = options.writeUnknownFields; if (u !== false) (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer); @@ -18554,8 +19808,12 @@ class AMP$Type extends MessageType { ]); } create(value?: PartialMessage): AMP { - const message = { rootShare: new Uint8Array(0), setId: new Uint8Array(0), childIndex: 0, hash: new Uint8Array(0), preimage: new Uint8Array(0) }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.rootShare = new Uint8Array(0); + message.setId = new Uint8Array(0); + message.childIndex = 0; + message.hash = new Uint8Array(0); + message.preimage = new Uint8Array(0); if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -18628,8 +19886,11 @@ class AddInvoiceResponse$Type extends MessageType { ]); } create(value?: PartialMessage): AddInvoiceResponse { - const message = { rHash: new Uint8Array(0), paymentRequest: "", addIndex: 0n, paymentAddr: new Uint8Array(0) }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.rHash = new Uint8Array(0); + message.paymentRequest = ""; + message.addIndex = 0n; + message.paymentAddr = new Uint8Array(0); if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -18694,8 +19955,9 @@ class PaymentHash$Type extends MessageType { ]); } create(value?: PartialMessage): PaymentHash { - const message = { rHashStr: "", rHash: new Uint8Array(0) }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.rHashStr = ""; + message.rHash = new Uint8Array(0); if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -18705,7 +19967,7 @@ class PaymentHash$Type extends MessageType { while (reader.pos < end) { let [fieldNo, wireType] = reader.tag(); switch (fieldNo) { - case /* string r_hash_str = 1 [deprecated = true];*/ 1: + case /* string r_hash_str = 1 [deprecated = true] */ 1: message.rHashStr = reader.string(); break; case /* bytes r_hash */ 2: @@ -18752,8 +20014,13 @@ class ListInvoiceRequest$Type extends MessageType { ]); } create(value?: PartialMessage): ListInvoiceRequest { - const message = { pendingOnly: false, indexOffset: 0n, numMaxInvoices: 0n, reversed: false, creationDateStart: 0n, creationDateEnd: 0n }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.pendingOnly = false; + message.indexOffset = 0n; + message.numMaxInvoices = 0n; + message.reversed = false; + message.creationDateStart = 0n; + message.creationDateEnd = 0n; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -18825,14 +20092,16 @@ export const ListInvoiceRequest = new ListInvoiceRequest$Type(); class ListInvoiceResponse$Type extends MessageType { constructor() { super("lnrpc.ListInvoiceResponse", [ - { no: 1, name: "invoices", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => Invoice }, + { no: 1, name: "invoices", kind: "message", repeat: 2 /*RepeatType.UNPACKED*/, T: () => Invoice }, { no: 2, name: "last_index_offset", kind: "scalar", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ }, { no: 3, name: "first_index_offset", kind: "scalar", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ } ]); } create(value?: PartialMessage): ListInvoiceResponse { - const message = { invoices: [], lastIndexOffset: 0n, firstIndexOffset: 0n }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.invoices = []; + message.lastIndexOffset = 0n; + message.firstIndexOffset = 0n; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -18891,8 +20160,9 @@ class InvoiceSubscription$Type extends MessageType { ]); } create(value?: PartialMessage): InvoiceSubscription { - const message = { addIndex: 0n, settleIndex: 0n }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.addIndex = 0n; + message.settleIndex = 0n; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -18952,14 +20222,30 @@ class Payment$Type extends MessageType { { no: 11, name: "fee_sat", kind: "scalar", T: 3 /*ScalarType.INT64*/, L: 0 /*LongType.BIGINT*/ }, { no: 12, name: "fee_msat", kind: "scalar", T: 3 /*ScalarType.INT64*/, L: 0 /*LongType.BIGINT*/ }, { no: 13, name: "creation_time_ns", kind: "scalar", T: 3 /*ScalarType.INT64*/, L: 0 /*LongType.BIGINT*/ }, - { no: 14, name: "htlcs", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => HTLCAttempt }, + { no: 14, name: "htlcs", kind: "message", repeat: 2 /*RepeatType.UNPACKED*/, T: () => HTLCAttempt }, { no: 15, name: "payment_index", kind: "scalar", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ }, - { no: 16, name: "failure_reason", kind: "enum", T: () => ["lnrpc.PaymentFailureReason", PaymentFailureReason] } + { no: 16, name: "failure_reason", kind: "enum", T: () => ["lnrpc.PaymentFailureReason", PaymentFailureReason] }, + { no: 17, name: "first_hop_custom_records", kind: "map", K: 4 /*ScalarType.UINT64*/, V: { kind: "scalar", T: 12 /*ScalarType.BYTES*/ } } ]); } create(value?: PartialMessage): Payment { - const message = { paymentHash: "", value: 0n, creationDate: 0n, fee: 0n, paymentPreimage: "", valueSat: 0n, valueMsat: 0n, paymentRequest: "", status: 0, feeSat: 0n, feeMsat: 0n, creationTimeNs: 0n, htlcs: [], paymentIndex: 0n, failureReason: 0 }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.paymentHash = ""; + message.value = 0n; + message.creationDate = 0n; + message.fee = 0n; + message.paymentPreimage = ""; + message.valueSat = 0n; + message.valueMsat = 0n; + message.paymentRequest = ""; + message.status = 0; + message.feeSat = 0n; + message.feeMsat = 0n; + message.creationTimeNs = 0n; + message.htlcs = []; + message.paymentIndex = 0n; + message.failureReason = 0; + message.firstHopCustomRecords = {}; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -18972,13 +20258,13 @@ class Payment$Type extends MessageType { case /* string payment_hash */ 1: message.paymentHash = reader.string(); break; - case /* int64 value = 2 [deprecated = true];*/ 2: + case /* int64 value = 2 [deprecated = true] */ 2: message.value = reader.int64().toBigInt(); break; - case /* int64 creation_date = 3 [deprecated = true];*/ 3: + case /* int64 creation_date = 3 [deprecated = true] */ 3: message.creationDate = reader.int64().toBigInt(); break; - case /* int64 fee = 5 [deprecated = true];*/ 5: + case /* int64 fee = 5 [deprecated = true] */ 5: message.fee = reader.int64().toBigInt(); break; case /* string payment_preimage */ 6: @@ -19014,6 +20300,9 @@ class Payment$Type extends MessageType { case /* lnrpc.PaymentFailureReason failure_reason */ 16: message.failureReason = reader.int32(); break; + case /* map first_hop_custom_records */ 17: + this.binaryReadMap17(message.firstHopCustomRecords, reader, options); + break; default: let u = options.readUnknownField; if (u === "throw") @@ -19025,6 +20314,22 @@ class Payment$Type extends MessageType { } return message; } + private binaryReadMap17(map: Payment["firstHopCustomRecords"], reader: IBinaryReader, options: BinaryReadOptions): void { + let len = reader.uint32(), end = reader.pos + len, key: keyof Payment["firstHopCustomRecords"] | undefined, val: Payment["firstHopCustomRecords"][any] | undefined; + while (reader.pos < end) { + let [fieldNo, wireType] = reader.tag(); + switch (fieldNo) { + case 1: + key = reader.uint64().toString(); + break; + case 2: + val = reader.bytes(); + break; + default: throw new globalThis.Error("unknown map entry field for lnrpc.Payment.first_hop_custom_records"); + } + } + map[key ?? "0"] = val ?? new Uint8Array(0); + } internalBinaryWrite(message: Payment, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter { /* string payment_hash = 1; */ if (message.paymentHash !== "") @@ -19071,6 +20376,9 @@ class Payment$Type extends MessageType { /* lnrpc.PaymentFailureReason failure_reason = 16; */ if (message.failureReason !== 0) writer.tag(16, WireType.Varint).int32(message.failureReason); + /* map first_hop_custom_records = 17; */ + for (let k of globalThis.Object.keys(message.firstHopCustomRecords)) + writer.tag(17, WireType.LengthDelimited).fork().tag(1, WireType.Varint).uint64(k).tag(2, WireType.LengthDelimited).bytes(message.firstHopCustomRecords[k]).join(); let u = options.writeUnknownFields; if (u !== false) (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer); @@ -19095,8 +20403,12 @@ class HTLCAttempt$Type extends MessageType { ]); } create(value?: PartialMessage): HTLCAttempt { - const message = { attemptId: 0n, status: 0, attemptTimeNs: 0n, resolveTimeNs: 0n, preimage: new Uint8Array(0) }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.attemptId = 0n; + message.status = 0; + message.attemptTimeNs = 0n; + message.resolveTimeNs = 0n; + message.preimage = new Uint8Array(0); if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -19139,9 +20451,6 @@ class HTLCAttempt$Type extends MessageType { return message; } internalBinaryWrite(message: HTLCAttempt, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter { - /* uint64 attempt_id = 7; */ - if (message.attemptId !== 0n) - writer.tag(7, WireType.Varint).uint64(message.attemptId); /* lnrpc.HTLCAttempt.HTLCStatus status = 1; */ if (message.status !== 0) writer.tag(1, WireType.Varint).int32(message.status); @@ -19160,6 +20469,9 @@ class HTLCAttempt$Type extends MessageType { /* bytes preimage = 6; */ if (message.preimage.length) writer.tag(6, WireType.LengthDelimited).bytes(message.preimage); + /* uint64 attempt_id = 7; */ + if (message.attemptId !== 0n) + writer.tag(7, WireType.Varint).uint64(message.attemptId); let u = options.writeUnknownFields; if (u !== false) (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer); @@ -19184,8 +20496,14 @@ class ListPaymentsRequest$Type extends MessageType { ]); } create(value?: PartialMessage): ListPaymentsRequest { - const message = { includeIncomplete: false, indexOffset: 0n, maxPayments: 0n, reversed: false, countTotalPayments: false, creationDateStart: 0n, creationDateEnd: 0n }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.includeIncomplete = false; + message.indexOffset = 0n; + message.maxPayments = 0n; + message.reversed = false; + message.countTotalPayments = false; + message.creationDateStart = 0n; + message.creationDateEnd = 0n; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -19263,15 +20581,18 @@ export const ListPaymentsRequest = new ListPaymentsRequest$Type(); class ListPaymentsResponse$Type extends MessageType { constructor() { super("lnrpc.ListPaymentsResponse", [ - { no: 1, name: "payments", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => Payment }, + { no: 1, name: "payments", kind: "message", repeat: 2 /*RepeatType.UNPACKED*/, T: () => Payment }, { no: 2, name: "first_index_offset", kind: "scalar", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ }, { no: 3, name: "last_index_offset", kind: "scalar", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ }, { no: 4, name: "total_num_payments", kind: "scalar", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ } ]); } create(value?: PartialMessage): ListPaymentsResponse { - const message = { payments: [], firstIndexOffset: 0n, lastIndexOffset: 0n, totalNumPayments: 0n }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.payments = []; + message.firstIndexOffset = 0n; + message.lastIndexOffset = 0n; + message.totalNumPayments = 0n; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -19336,8 +20657,9 @@ class DeletePaymentRequest$Type extends MessageType { ]); } create(value?: PartialMessage): DeletePaymentRequest { - const message = { paymentHash: new Uint8Array(0), failedHtlcsOnly: false }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.paymentHash = new Uint8Array(0); + message.failedHtlcsOnly = false; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -19391,8 +20713,10 @@ class DeleteAllPaymentsRequest$Type extends MessageType): DeleteAllPaymentsRequest { - const message = { failedPaymentsOnly: false, failedHtlcsOnly: false, allPayments: false }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.failedPaymentsOnly = false; + message.failedHtlcsOnly = false; + message.allPayments = false; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -19445,19 +20769,40 @@ export const DeleteAllPaymentsRequest = new DeleteAllPaymentsRequest$Type(); // @generated message type with reflection information, may provide speed optimized methods class DeletePaymentResponse$Type extends MessageType { constructor() { - super("lnrpc.DeletePaymentResponse", []); + super("lnrpc.DeletePaymentResponse", [ + { no: 1, name: "status", kind: "scalar", T: 9 /*ScalarType.STRING*/ } + ]); } create(value?: PartialMessage): DeletePaymentResponse { - const message = {}; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.status = ""; if (value !== undefined) reflectionMergePartial(this, message, value); return message; } internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: DeletePaymentResponse): DeletePaymentResponse { - return target ?? this.create(); + let message = target ?? this.create(), end = reader.pos + length; + while (reader.pos < end) { + let [fieldNo, wireType] = reader.tag(); + switch (fieldNo) { + case /* string status */ 1: + message.status = reader.string(); + break; + default: + let u = options.readUnknownField; + if (u === "throw") + throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`); + let d = reader.skip(wireType); + if (u !== false) + (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d); + } + } + return message; } internalBinaryWrite(message: DeletePaymentResponse, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter { + /* string status = 1; */ + if (message.status !== "") + writer.tag(1, WireType.LengthDelimited).string(message.status); let u = options.writeUnknownFields; if (u !== false) (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer); @@ -19471,19 +20816,40 @@ export const DeletePaymentResponse = new DeletePaymentResponse$Type(); // @generated message type with reflection information, may provide speed optimized methods class DeleteAllPaymentsResponse$Type extends MessageType { constructor() { - super("lnrpc.DeleteAllPaymentsResponse", []); + super("lnrpc.DeleteAllPaymentsResponse", [ + { no: 1, name: "status", kind: "scalar", T: 9 /*ScalarType.STRING*/ } + ]); } create(value?: PartialMessage): DeleteAllPaymentsResponse { - const message = {}; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.status = ""; if (value !== undefined) reflectionMergePartial(this, message, value); return message; } internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: DeleteAllPaymentsResponse): DeleteAllPaymentsResponse { - return target ?? this.create(); + let message = target ?? this.create(), end = reader.pos + length; + while (reader.pos < end) { + let [fieldNo, wireType] = reader.tag(); + switch (fieldNo) { + case /* string status */ 1: + message.status = reader.string(); + break; + default: + let u = options.readUnknownField; + if (u === "throw") + throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`); + let d = reader.skip(wireType); + if (u !== false) + (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d); + } + } + return message; } internalBinaryWrite(message: DeleteAllPaymentsResponse, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter { + /* string status = 1; */ + if (message.status !== "") + writer.tag(1, WireType.LengthDelimited).string(message.status); let u = options.writeUnknownFields; if (u !== false) (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer); @@ -19504,8 +20870,9 @@ class AbandonChannelRequest$Type extends MessageType { ]); } create(value?: PartialMessage): AbandonChannelRequest { - const message = { pendingFundingShimOnly: false, iKnowWhatIAmDoing: false }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.pendingFundingShimOnly = false; + message.iKnowWhatIAmDoing = false; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -19558,19 +20925,40 @@ export const AbandonChannelRequest = new AbandonChannelRequest$Type(); // @generated message type with reflection information, may provide speed optimized methods class AbandonChannelResponse$Type extends MessageType { constructor() { - super("lnrpc.AbandonChannelResponse", []); + super("lnrpc.AbandonChannelResponse", [ + { no: 1, name: "status", kind: "scalar", T: 9 /*ScalarType.STRING*/ } + ]); } create(value?: PartialMessage): AbandonChannelResponse { - const message = {}; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.status = ""; if (value !== undefined) reflectionMergePartial(this, message, value); return message; } internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: AbandonChannelResponse): AbandonChannelResponse { - return target ?? this.create(); + let message = target ?? this.create(), end = reader.pos + length; + while (reader.pos < end) { + let [fieldNo, wireType] = reader.tag(); + switch (fieldNo) { + case /* string status */ 1: + message.status = reader.string(); + break; + default: + let u = options.readUnknownField; + if (u === "throw") + throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`); + let d = reader.skip(wireType); + if (u !== false) + (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d); + } + } + return message; } internalBinaryWrite(message: AbandonChannelResponse, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter { + /* string status = 1; */ + if (message.status !== "") + writer.tag(1, WireType.LengthDelimited).string(message.status); let u = options.writeUnknownFields; if (u !== false) (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer); @@ -19590,8 +20978,9 @@ class DebugLevelRequest$Type extends MessageType { ]); } create(value?: PartialMessage): DebugLevelRequest { - const message = { show: false, levelSpec: "" }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.show = false; + message.levelSpec = ""; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -19643,8 +21032,8 @@ class DebugLevelResponse$Type extends MessageType { ]); } create(value?: PartialMessage): DebugLevelResponse { - const message = { subSystems: "" }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.subSystems = ""; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -19690,8 +21079,8 @@ class PayReqString$Type extends MessageType { ]); } create(value?: PartialMessage): PayReqString { - const message = { payReq: "" }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.payReq = ""; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -19742,16 +21131,29 @@ class PayReq$Type extends MessageType { { no: 7, name: "description_hash", kind: "scalar", T: 9 /*ScalarType.STRING*/ }, { no: 8, name: "fallback_addr", kind: "scalar", T: 9 /*ScalarType.STRING*/ }, { no: 9, name: "cltv_expiry", kind: "scalar", T: 3 /*ScalarType.INT64*/, L: 0 /*LongType.BIGINT*/ }, - { no: 10, name: "route_hints", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => RouteHint }, + { no: 10, name: "route_hints", kind: "message", repeat: 2 /*RepeatType.UNPACKED*/, T: () => RouteHint }, { no: 11, name: "payment_addr", kind: "scalar", T: 12 /*ScalarType.BYTES*/ }, { no: 12, name: "num_msat", kind: "scalar", T: 3 /*ScalarType.INT64*/, L: 0 /*LongType.BIGINT*/ }, { no: 13, name: "features", kind: "map", K: 13 /*ScalarType.UINT32*/, V: { kind: "message", T: () => Feature } }, - { no: 14, name: "blinded_paths", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => BlindedPaymentPath } + { no: 14, name: "blinded_paths", kind: "message", repeat: 2 /*RepeatType.UNPACKED*/, T: () => BlindedPaymentPath } ]); } create(value?: PartialMessage): PayReq { - const message = { destination: "", paymentHash: "", numSatoshis: 0n, timestamp: 0n, expiry: 0n, description: "", descriptionHash: "", fallbackAddr: "", cltvExpiry: 0n, routeHints: [], paymentAddr: new Uint8Array(0), numMsat: 0n, features: {}, blindedPaths: [] }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.destination = ""; + message.paymentHash = ""; + message.numSatoshis = 0n; + message.timestamp = 0n; + message.expiry = 0n; + message.description = ""; + message.descriptionHash = ""; + message.fallbackAddr = ""; + message.cltvExpiry = 0n; + message.routeHints = []; + message.paymentAddr = new Uint8Array(0); + message.numMsat = 0n; + message.features = {}; + message.blindedPaths = []; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -19825,7 +21227,7 @@ class PayReq$Type extends MessageType { case 2: val = Feature.internalBinaryRead(reader, reader.uint32(), options); break; - default: throw new globalThis.Error("unknown map entry field for field lnrpc.PayReq.features"); + default: throw new globalThis.Error("unknown map entry field for lnrpc.PayReq.features"); } } map[key ?? 0] = val ?? Feature.create(); @@ -19868,7 +21270,7 @@ class PayReq$Type extends MessageType { if (message.numMsat !== 0n) writer.tag(12, WireType.Varint).int64(message.numMsat); /* map features = 13; */ - for (let k of Object.keys(message.features)) { + for (let k of globalThis.Object.keys(message.features)) { writer.tag(13, WireType.LengthDelimited).fork().tag(1, WireType.Varint).uint32(parseInt(k)); writer.tag(2, WireType.LengthDelimited).fork(); Feature.internalBinaryWrite(message.features[k as any], writer, options); @@ -19897,8 +21299,10 @@ class Feature$Type extends MessageType { ]); } create(value?: PartialMessage): Feature { - const message = { name: "", isRequired: false, isKnown: false }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.name = ""; + message.isRequired = false; + message.isKnown = false; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -19954,14 +21358,26 @@ class FeeReportRequest$Type extends MessageType { super("lnrpc.FeeReportRequest", []); } create(value?: PartialMessage): FeeReportRequest { - const message = {}; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); if (value !== undefined) reflectionMergePartial(this, message, value); return message; } internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: FeeReportRequest): FeeReportRequest { - return target ?? this.create(); + let message = target ?? this.create(), end = reader.pos + length; + while (reader.pos < end) { + let [fieldNo, wireType] = reader.tag(); + switch (fieldNo) { + default: + let u = options.readUnknownField; + if (u === "throw") + throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`); + let d = reader.skip(wireType); + if (u !== false) + (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d); + } + } + return message; } internalBinaryWrite(message: FeeReportRequest, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter { let u = options.writeUnknownFields; @@ -19988,8 +21404,14 @@ class ChannelFeeReport$Type extends MessageType { ]); } create(value?: PartialMessage): ChannelFeeReport { - const message = { chanId: "0", channelPoint: "", baseFeeMsat: 0n, feePerMil: 0n, feeRate: 0, inboundBaseFeeMsat: 0, inboundFeePerMil: 0 }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.chanId = "0"; + message.channelPoint = ""; + message.baseFeeMsat = 0n; + message.feePerMil = 0n; + message.feeRate = 0; + message.inboundBaseFeeMsat = 0; + message.inboundFeePerMil = 0; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -19999,7 +21421,7 @@ class ChannelFeeReport$Type extends MessageType { while (reader.pos < end) { let [fieldNo, wireType] = reader.tag(); switch (fieldNo) { - case /* uint64 chan_id = 5 [jstype = JS_STRING];*/ 5: + case /* uint64 chan_id = 5 [jstype = JS_STRING] */ 5: message.chanId = reader.uint64().toString(); break; case /* string channel_point */ 1: @@ -20032,9 +21454,6 @@ class ChannelFeeReport$Type extends MessageType { return message; } internalBinaryWrite(message: ChannelFeeReport, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter { - /* uint64 chan_id = 5 [jstype = JS_STRING]; */ - if (message.chanId !== "0") - writer.tag(5, WireType.Varint).uint64(message.chanId); /* string channel_point = 1; */ if (message.channelPoint !== "") writer.tag(1, WireType.LengthDelimited).string(message.channelPoint); @@ -20047,6 +21466,9 @@ class ChannelFeeReport$Type extends MessageType { /* double fee_rate = 4; */ if (message.feeRate !== 0) writer.tag(4, WireType.Bit64).double(message.feeRate); + /* uint64 chan_id = 5 [jstype = JS_STRING]; */ + if (message.chanId !== "0") + writer.tag(5, WireType.Varint).uint64(message.chanId); /* int32 inbound_base_fee_msat = 6; */ if (message.inboundBaseFeeMsat !== 0) writer.tag(6, WireType.Varint).int32(message.inboundBaseFeeMsat); @@ -20067,15 +21489,18 @@ export const ChannelFeeReport = new ChannelFeeReport$Type(); class FeeReportResponse$Type extends MessageType { constructor() { super("lnrpc.FeeReportResponse", [ - { no: 1, name: "channel_fees", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => ChannelFeeReport }, + { no: 1, name: "channel_fees", kind: "message", repeat: 2 /*RepeatType.UNPACKED*/, T: () => ChannelFeeReport }, { no: 2, name: "day_fee_sum", kind: "scalar", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ }, { no: 3, name: "week_fee_sum", kind: "scalar", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ }, { no: 4, name: "month_fee_sum", kind: "scalar", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ } ]); } create(value?: PartialMessage): FeeReportResponse { - const message = { channelFees: [], dayFeeSum: 0n, weekFeeSum: 0n, monthFeeSum: 0n }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.channelFees = []; + message.dayFeeSum = 0n; + message.weekFeeSum = 0n; + message.monthFeeSum = 0n; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -20140,8 +21565,9 @@ class InboundFee$Type extends MessageType { ]); } create(value?: PartialMessage): InboundFee { - const message = { baseFeeMsat: 0, feeRatePpm: 0 }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.baseFeeMsat = 0; + message.feeRatePpm = 0; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -20198,12 +21624,21 @@ class PolicyUpdateRequest$Type extends MessageType { { no: 6, name: "max_htlc_msat", kind: "scalar", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ }, { no: 7, name: "min_htlc_msat", kind: "scalar", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ }, { no: 8, name: "min_htlc_msat_specified", kind: "scalar", T: 8 /*ScalarType.BOOL*/ }, - { no: 10, name: "inbound_fee", kind: "message", T: () => InboundFee } + { no: 10, name: "inbound_fee", kind: "message", T: () => InboundFee }, + { no: 11, name: "create_missing_edge", kind: "scalar", T: 8 /*ScalarType.BOOL*/ } ]); } create(value?: PartialMessage): PolicyUpdateRequest { - const message = { scope: { oneofKind: undefined }, baseFeeMsat: 0n, feeRate: 0, feeRatePpm: 0, timeLockDelta: 0, maxHtlcMsat: 0n, minHtlcMsat: 0n, minHtlcMsatSpecified: false }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.scope = { oneofKind: undefined }; + message.baseFeeMsat = 0n; + message.feeRate = 0; + message.feeRatePpm = 0; + message.timeLockDelta = 0; + message.maxHtlcMsat = 0n; + message.minHtlcMsat = 0n; + message.minHtlcMsatSpecified = false; + message.createMissingEdge = false; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -20249,6 +21684,9 @@ class PolicyUpdateRequest$Type extends MessageType { case /* lnrpc.InboundFee inbound_fee */ 10: message.inboundFee = InboundFee.internalBinaryRead(reader, reader.uint32(), options, message.inboundFee); break; + case /* bool create_missing_edge */ 11: + message.createMissingEdge = reader.bool(); + break; default: let u = options.readUnknownField; if (u === "throw") @@ -20273,9 +21711,6 @@ class PolicyUpdateRequest$Type extends MessageType { /* double fee_rate = 4; */ if (message.feeRate !== 0) writer.tag(4, WireType.Bit64).double(message.feeRate); - /* uint32 fee_rate_ppm = 9; */ - if (message.feeRatePpm !== 0) - writer.tag(9, WireType.Varint).uint32(message.feeRatePpm); /* uint32 time_lock_delta = 5; */ if (message.timeLockDelta !== 0) writer.tag(5, WireType.Varint).uint32(message.timeLockDelta); @@ -20288,9 +21723,15 @@ class PolicyUpdateRequest$Type extends MessageType { /* bool min_htlc_msat_specified = 8; */ if (message.minHtlcMsatSpecified !== false) writer.tag(8, WireType.Varint).bool(message.minHtlcMsatSpecified); + /* uint32 fee_rate_ppm = 9; */ + if (message.feeRatePpm !== 0) + writer.tag(9, WireType.Varint).uint32(message.feeRatePpm); /* lnrpc.InboundFee inbound_fee = 10; */ if (message.inboundFee) InboundFee.internalBinaryWrite(message.inboundFee, writer.tag(10, WireType.LengthDelimited).fork(), options).join(); + /* bool create_missing_edge = 11; */ + if (message.createMissingEdge !== false) + writer.tag(11, WireType.Varint).bool(message.createMissingEdge); let u = options.writeUnknownFields; if (u !== false) (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer); @@ -20311,8 +21752,9 @@ class FailedUpdate$Type extends MessageType { ]); } create(value?: PartialMessage): FailedUpdate { - const message = { reason: 0, updateError: "" }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.reason = 0; + message.updateError = ""; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -20366,12 +21808,12 @@ export const FailedUpdate = new FailedUpdate$Type(); class PolicyUpdateResponse$Type extends MessageType { constructor() { super("lnrpc.PolicyUpdateResponse", [ - { no: 1, name: "failed_updates", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => FailedUpdate } + { no: 1, name: "failed_updates", kind: "message", repeat: 2 /*RepeatType.UNPACKED*/, T: () => FailedUpdate } ]); } create(value?: PartialMessage): PolicyUpdateResponse { - const message = { failedUpdates: [] }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.failedUpdates = []; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -20421,8 +21863,12 @@ class ForwardingHistoryRequest$Type extends MessageType): ForwardingHistoryRequest { - const message = { startTime: 0n, endTime: 0n, indexOffset: 0, numMaxEvents: 0, peerAliasLookup: false }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.startTime = 0n; + message.endTime = 0n; + message.indexOffset = 0; + message.numMaxEvents = 0; + message.peerAliasLookup = false; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -20499,12 +21945,25 @@ class ForwardingEvent$Type extends MessageType { { no: 10, name: "amt_out_msat", kind: "scalar", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ }, { no: 11, name: "timestamp_ns", kind: "scalar", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ }, { no: 12, name: "peer_alias_in", kind: "scalar", T: 9 /*ScalarType.STRING*/ }, - { no: 13, name: "peer_alias_out", kind: "scalar", T: 9 /*ScalarType.STRING*/ } + { no: 13, name: "peer_alias_out", kind: "scalar", T: 9 /*ScalarType.STRING*/ }, + { no: 14, name: "incoming_htlc_id", kind: "scalar", opt: true, T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ }, + { no: 15, name: "outgoing_htlc_id", kind: "scalar", opt: true, T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ } ]); } create(value?: PartialMessage): ForwardingEvent { - const message = { timestamp: 0n, chanIdIn: "0", chanIdOut: "0", amtIn: 0n, amtOut: 0n, fee: 0n, feeMsat: 0n, amtInMsat: 0n, amtOutMsat: 0n, timestampNs: 0n, peerAliasIn: "", peerAliasOut: "" }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.timestamp = 0n; + message.chanIdIn = "0"; + message.chanIdOut = "0"; + message.amtIn = 0n; + message.amtOut = 0n; + message.fee = 0n; + message.feeMsat = 0n; + message.amtInMsat = 0n; + message.amtOutMsat = 0n; + message.timestampNs = 0n; + message.peerAliasIn = ""; + message.peerAliasOut = ""; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -20514,13 +21973,13 @@ class ForwardingEvent$Type extends MessageType { while (reader.pos < end) { let [fieldNo, wireType] = reader.tag(); switch (fieldNo) { - case /* uint64 timestamp = 1 [deprecated = true];*/ 1: + case /* uint64 timestamp = 1 [deprecated = true] */ 1: message.timestamp = reader.uint64().toBigInt(); break; - case /* uint64 chan_id_in = 2 [jstype = JS_STRING];*/ 2: + case /* uint64 chan_id_in = 2 [jstype = JS_STRING] */ 2: message.chanIdIn = reader.uint64().toString(); break; - case /* uint64 chan_id_out = 4 [jstype = JS_STRING];*/ 4: + case /* uint64 chan_id_out = 4 [jstype = JS_STRING] */ 4: message.chanIdOut = reader.uint64().toString(); break; case /* uint64 amt_in */ 5: @@ -20550,6 +22009,12 @@ class ForwardingEvent$Type extends MessageType { case /* string peer_alias_out */ 13: message.peerAliasOut = reader.string(); break; + case /* optional uint64 incoming_htlc_id */ 14: + message.incomingHtlcId = reader.uint64().toBigInt(); + break; + case /* optional uint64 outgoing_htlc_id */ 15: + message.outgoingHtlcId = reader.uint64().toBigInt(); + break; default: let u = options.readUnknownField; if (u === "throw") @@ -20598,6 +22063,12 @@ class ForwardingEvent$Type extends MessageType { /* string peer_alias_out = 13; */ if (message.peerAliasOut !== "") writer.tag(13, WireType.LengthDelimited).string(message.peerAliasOut); + /* optional uint64 incoming_htlc_id = 14; */ + if (message.incomingHtlcId !== undefined) + writer.tag(14, WireType.Varint).uint64(message.incomingHtlcId); + /* optional uint64 outgoing_htlc_id = 15; */ + if (message.outgoingHtlcId !== undefined) + writer.tag(15, WireType.Varint).uint64(message.outgoingHtlcId); let u = options.writeUnknownFields; if (u !== false) (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer); @@ -20612,13 +22083,14 @@ export const ForwardingEvent = new ForwardingEvent$Type(); class ForwardingHistoryResponse$Type extends MessageType { constructor() { super("lnrpc.ForwardingHistoryResponse", [ - { no: 1, name: "forwarding_events", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => ForwardingEvent }, + { no: 1, name: "forwarding_events", kind: "message", repeat: 2 /*RepeatType.UNPACKED*/, T: () => ForwardingEvent }, { no: 2, name: "last_offset_index", kind: "scalar", T: 13 /*ScalarType.UINT32*/ } ]); } create(value?: PartialMessage): ForwardingHistoryResponse { - const message = { forwardingEvents: [], lastOffsetIndex: 0 }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.forwardingEvents = []; + message.lastOffsetIndex = 0; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -20670,8 +22142,7 @@ class ExportChannelBackupRequest$Type extends MessageType): ExportChannelBackupRequest { - const message = {}; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -20718,8 +22189,8 @@ class ChannelBackup$Type extends MessageType { ]); } create(value?: PartialMessage): ChannelBackup { - const message = { chanBackup: new Uint8Array(0) }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.chanBackup = new Uint8Array(0); if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -20767,13 +22238,14 @@ export const ChannelBackup = new ChannelBackup$Type(); class MultiChanBackup$Type extends MessageType { constructor() { super("lnrpc.MultiChanBackup", [ - { no: 1, name: "chan_points", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => ChannelPoint }, + { no: 1, name: "chan_points", kind: "message", repeat: 2 /*RepeatType.UNPACKED*/, T: () => ChannelPoint }, { no: 2, name: "multi_chan_backup", kind: "scalar", T: 12 /*ScalarType.BYTES*/ } ]); } create(value?: PartialMessage): MultiChanBackup { - const message = { chanPoints: [], multiChanBackup: new Uint8Array(0) }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.chanPoints = []; + message.multiChanBackup = new Uint8Array(0); if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -20823,14 +22295,26 @@ class ChanBackupExportRequest$Type extends MessageType super("lnrpc.ChanBackupExportRequest", []); } create(value?: PartialMessage): ChanBackupExportRequest { - const message = {}; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); if (value !== undefined) reflectionMergePartial(this, message, value); return message; } internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: ChanBackupExportRequest): ChanBackupExportRequest { - return target ?? this.create(); + let message = target ?? this.create(), end = reader.pos + length; + while (reader.pos < end) { + let [fieldNo, wireType] = reader.tag(); + switch (fieldNo) { + default: + let u = options.readUnknownField; + if (u === "throw") + throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`); + let d = reader.skip(wireType); + if (u !== false) + (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d); + } + } + return message; } internalBinaryWrite(message: ChanBackupExportRequest, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter { let u = options.writeUnknownFields; @@ -20852,8 +22336,7 @@ class ChanBackupSnapshot$Type extends MessageType { ]); } create(value?: PartialMessage): ChanBackupSnapshot { - const message = {}; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -20901,12 +22384,12 @@ export const ChanBackupSnapshot = new ChanBackupSnapshot$Type(); class ChannelBackups$Type extends MessageType { constructor() { super("lnrpc.ChannelBackups", [ - { no: 1, name: "chan_backups", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => ChannelBackup } + { no: 1, name: "chan_backups", kind: "message", repeat: 2 /*RepeatType.UNPACKED*/, T: () => ChannelBackup } ]); } create(value?: PartialMessage): ChannelBackups { - const message = { chanBackups: [] }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.chanBackups = []; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -20953,8 +22436,8 @@ class RestoreChanBackupRequest$Type extends MessageType): RestoreChanBackupRequest { - const message = { backup: { oneofKind: undefined } }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.backup = { oneofKind: undefined }; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -21007,19 +22490,40 @@ export const RestoreChanBackupRequest = new RestoreChanBackupRequest$Type(); // @generated message type with reflection information, may provide speed optimized methods class RestoreBackupResponse$Type extends MessageType { constructor() { - super("lnrpc.RestoreBackupResponse", []); + super("lnrpc.RestoreBackupResponse", [ + { no: 1, name: "num_restored", kind: "scalar", T: 13 /*ScalarType.UINT32*/ } + ]); } create(value?: PartialMessage): RestoreBackupResponse { - const message = {}; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.numRestored = 0; if (value !== undefined) reflectionMergePartial(this, message, value); return message; } internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: RestoreBackupResponse): RestoreBackupResponse { - return target ?? this.create(); + let message = target ?? this.create(), end = reader.pos + length; + while (reader.pos < end) { + let [fieldNo, wireType] = reader.tag(); + switch (fieldNo) { + case /* uint32 num_restored */ 1: + message.numRestored = reader.uint32(); + break; + default: + let u = options.readUnknownField; + if (u === "throw") + throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`); + let d = reader.skip(wireType); + if (u !== false) + (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d); + } + } + return message; } internalBinaryWrite(message: RestoreBackupResponse, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter { + /* uint32 num_restored = 1; */ + if (message.numRestored !== 0) + writer.tag(1, WireType.Varint).uint32(message.numRestored); let u = options.writeUnknownFields; if (u !== false) (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer); @@ -21036,14 +22540,26 @@ class ChannelBackupSubscription$Type extends MessageType): ChannelBackupSubscription { - const message = {}; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); if (value !== undefined) reflectionMergePartial(this, message, value); return message; } internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: ChannelBackupSubscription): ChannelBackupSubscription { - return target ?? this.create(); + let message = target ?? this.create(), end = reader.pos + length; + while (reader.pos < end) { + let [fieldNo, wireType] = reader.tag(); + switch (fieldNo) { + default: + let u = options.readUnknownField; + if (u === "throw") + throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`); + let d = reader.skip(wireType); + if (u !== false) + (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d); + } + } + return message; } internalBinaryWrite(message: ChannelBackupSubscription, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter { let u = options.writeUnknownFields; @@ -21059,19 +22575,40 @@ export const ChannelBackupSubscription = new ChannelBackupSubscription$Type(); // @generated message type with reflection information, may provide speed optimized methods class VerifyChanBackupResponse$Type extends MessageType { constructor() { - super("lnrpc.VerifyChanBackupResponse", []); + super("lnrpc.VerifyChanBackupResponse", [ + { no: 1, name: "chan_points", kind: "scalar", repeat: 2 /*RepeatType.UNPACKED*/, T: 9 /*ScalarType.STRING*/ } + ]); } create(value?: PartialMessage): VerifyChanBackupResponse { - const message = {}; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.chanPoints = []; if (value !== undefined) reflectionMergePartial(this, message, value); return message; } internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: VerifyChanBackupResponse): VerifyChanBackupResponse { - return target ?? this.create(); + let message = target ?? this.create(), end = reader.pos + length; + while (reader.pos < end) { + let [fieldNo, wireType] = reader.tag(); + switch (fieldNo) { + case /* repeated string chan_points */ 1: + message.chanPoints.push(reader.string()); + break; + default: + let u = options.readUnknownField; + if (u === "throw") + throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`); + let d = reader.skip(wireType); + if (u !== false) + (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d); + } + } + return message; } internalBinaryWrite(message: VerifyChanBackupResponse, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter { + /* repeated string chan_points = 1; */ + for (let i = 0; i < message.chanPoints.length; i++) + writer.tag(1, WireType.LengthDelimited).string(message.chanPoints[i]); let u = options.writeUnknownFields; if (u !== false) (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer); @@ -21091,8 +22628,9 @@ class MacaroonPermission$Type extends MessageType { ]); } create(value?: PartialMessage): MacaroonPermission { - const message = { entity: "", action: "" }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.entity = ""; + message.action = ""; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -21140,14 +22678,16 @@ export const MacaroonPermission = new MacaroonPermission$Type(); class BakeMacaroonRequest$Type extends MessageType { constructor() { super("lnrpc.BakeMacaroonRequest", [ - { no: 1, name: "permissions", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => MacaroonPermission }, + { no: 1, name: "permissions", kind: "message", repeat: 2 /*RepeatType.UNPACKED*/, T: () => MacaroonPermission }, { no: 2, name: "root_key_id", kind: "scalar", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ }, { no: 3, name: "allow_external_permissions", kind: "scalar", T: 8 /*ScalarType.BOOL*/ } ]); } create(value?: PartialMessage): BakeMacaroonRequest { - const message = { permissions: [], rootKeyId: 0n, allowExternalPermissions: false }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.permissions = []; + message.rootKeyId = 0n; + message.allowExternalPermissions = false; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -21205,8 +22745,8 @@ class BakeMacaroonResponse$Type extends MessageType { ]); } create(value?: PartialMessage): BakeMacaroonResponse { - const message = { macaroon: "" }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.macaroon = ""; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -21250,14 +22790,26 @@ class ListMacaroonIDsRequest$Type extends MessageType { super("lnrpc.ListMacaroonIDsRequest", []); } create(value?: PartialMessage): ListMacaroonIDsRequest { - const message = {}; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); if (value !== undefined) reflectionMergePartial(this, message, value); return message; } internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: ListMacaroonIDsRequest): ListMacaroonIDsRequest { - return target ?? this.create(); + let message = target ?? this.create(), end = reader.pos + length; + while (reader.pos < end) { + let [fieldNo, wireType] = reader.tag(); + switch (fieldNo) { + default: + let u = options.readUnknownField; + if (u === "throw") + throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`); + let d = reader.skip(wireType); + if (u !== false) + (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d); + } + } + return message; } internalBinaryWrite(message: ListMacaroonIDsRequest, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter { let u = options.writeUnknownFields; @@ -21278,8 +22830,8 @@ class ListMacaroonIDsResponse$Type extends MessageType ]); } create(value?: PartialMessage): ListMacaroonIDsResponse { - const message = { rootKeyIds: [] }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.rootKeyIds = []; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -21333,8 +22885,8 @@ class DeleteMacaroonIDRequest$Type extends MessageType ]); } create(value?: PartialMessage): DeleteMacaroonIDRequest { - const message = { rootKeyId: 0n }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.rootKeyId = 0n; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -21380,8 +22932,8 @@ class DeleteMacaroonIDResponse$Type extends MessageType): DeleteMacaroonIDResponse { - const message = { deleted: false }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.deleted = false; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -21423,12 +22975,12 @@ export const DeleteMacaroonIDResponse = new DeleteMacaroonIDResponse$Type(); class MacaroonPermissionList$Type extends MessageType { constructor() { super("lnrpc.MacaroonPermissionList", [ - { no: 1, name: "permissions", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => MacaroonPermission } + { no: 1, name: "permissions", kind: "message", repeat: 2 /*RepeatType.UNPACKED*/, T: () => MacaroonPermission } ]); } create(value?: PartialMessage): MacaroonPermissionList { - const message = { permissions: [] }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.permissions = []; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -21472,14 +23024,26 @@ class ListPermissionsRequest$Type extends MessageType { super("lnrpc.ListPermissionsRequest", []); } create(value?: PartialMessage): ListPermissionsRequest { - const message = {}; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); if (value !== undefined) reflectionMergePartial(this, message, value); return message; } internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: ListPermissionsRequest): ListPermissionsRequest { - return target ?? this.create(); + let message = target ?? this.create(), end = reader.pos + length; + while (reader.pos < end) { + let [fieldNo, wireType] = reader.tag(); + switch (fieldNo) { + default: + let u = options.readUnknownField; + if (u === "throw") + throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`); + let d = reader.skip(wireType); + if (u !== false) + (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d); + } + } + return message; } internalBinaryWrite(message: ListPermissionsRequest, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter { let u = options.writeUnknownFields; @@ -21500,8 +23064,8 @@ class ListPermissionsResponse$Type extends MessageType ]); } create(value?: PartialMessage): ListPermissionsResponse { - const message = { methodPermissions: {} }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.methodPermissions = {}; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -21536,14 +23100,14 @@ class ListPermissionsResponse$Type extends MessageType case 2: val = MacaroonPermissionList.internalBinaryRead(reader, reader.uint32(), options); break; - default: throw new globalThis.Error("unknown map entry field for field lnrpc.ListPermissionsResponse.method_permissions"); + default: throw new globalThis.Error("unknown map entry field for lnrpc.ListPermissionsResponse.method_permissions"); } } map[key ?? ""] = val ?? MacaroonPermissionList.create(); } internalBinaryWrite(message: ListPermissionsResponse, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter { /* map method_permissions = 1; */ - for (let k of Object.keys(message.methodPermissions)) { + for (let k of globalThis.Object.keys(message.methodPermissions)) { writer.tag(1, WireType.LengthDelimited).fork().tag(1, WireType.LengthDelimited).string(k); writer.tag(2, WireType.LengthDelimited).fork(); MacaroonPermissionList.internalBinaryWrite(message.methodPermissions[k], writer, options); @@ -21574,8 +23138,14 @@ class Failure$Type extends MessageType { ]); } create(value?: PartialMessage): Failure { - const message = { code: 0, htlcMsat: 0n, onionSha256: new Uint8Array(0), cltvExpiry: 0, flags: 0, failureSourceIndex: 0, height: 0 }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.code = 0; + message.htlcMsat = 0n; + message.onionSha256 = new Uint8Array(0); + message.cltvExpiry = 0; + message.flags = 0; + message.failureSourceIndex = 0; + message.height = 0; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -21674,8 +23244,19 @@ class ChannelUpdate$Type extends MessageType { ]); } create(value?: PartialMessage): ChannelUpdate { - const message = { signature: new Uint8Array(0), chainHash: new Uint8Array(0), chanId: "0", timestamp: 0, messageFlags: 0, channelFlags: 0, timeLockDelta: 0, htlcMinimumMsat: 0n, baseFee: 0, feeRate: 0, htlcMaximumMsat: 0n, extraOpaqueData: new Uint8Array(0) }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.signature = new Uint8Array(0); + message.chainHash = new Uint8Array(0); + message.chanId = "0"; + message.timestamp = 0; + message.messageFlags = 0; + message.channelFlags = 0; + message.timeLockDelta = 0; + message.htlcMinimumMsat = 0n; + message.baseFee = 0; + message.feeRate = 0; + message.htlcMaximumMsat = 0n; + message.extraOpaqueData = new Uint8Array(0); if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -21691,7 +23272,7 @@ class ChannelUpdate$Type extends MessageType { case /* bytes chain_hash */ 2: message.chainHash = reader.bytes(); break; - case /* uint64 chan_id = 3 [jstype = JS_STRING];*/ 3: + case /* uint64 chan_id = 3 [jstype = JS_STRING] */ 3: message.chanId = reader.uint64().toString(); break; case /* uint32 timestamp */ 4: @@ -21745,9 +23326,6 @@ class ChannelUpdate$Type extends MessageType { /* uint32 timestamp = 4; */ if (message.timestamp !== 0) writer.tag(4, WireType.Varint).uint32(message.timestamp); - /* uint32 message_flags = 10; */ - if (message.messageFlags !== 0) - writer.tag(10, WireType.Varint).uint32(message.messageFlags); /* uint32 channel_flags = 5; */ if (message.channelFlags !== 0) writer.tag(5, WireType.Varint).uint32(message.channelFlags); @@ -21763,6 +23341,9 @@ class ChannelUpdate$Type extends MessageType { /* uint32 fee_rate = 9; */ if (message.feeRate !== 0) writer.tag(9, WireType.Varint).uint32(message.feeRate); + /* uint32 message_flags = 10; */ + if (message.messageFlags !== 0) + writer.tag(10, WireType.Varint).uint32(message.messageFlags); /* uint64 htlc_maximum_msat = 11; */ if (message.htlcMaximumMsat !== 0n) writer.tag(11, WireType.Varint).uint64(message.htlcMaximumMsat); @@ -21785,12 +23366,14 @@ class MacaroonId$Type extends MessageType { super("lnrpc.MacaroonId", [ { no: 1, name: "nonce", kind: "scalar", T: 12 /*ScalarType.BYTES*/ }, { no: 2, name: "storageId", kind: "scalar", T: 12 /*ScalarType.BYTES*/ }, - { no: 3, name: "ops", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => Op } + { no: 3, name: "ops", kind: "message", repeat: 2 /*RepeatType.UNPACKED*/, T: () => Op } ]); } create(value?: PartialMessage): MacaroonId { - const message = { nonce: new Uint8Array(0), storageId: new Uint8Array(0), ops: [] }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.nonce = new Uint8Array(0); + message.storageId = new Uint8Array(0); + message.ops = []; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -21849,8 +23432,9 @@ class Op$Type extends MessageType { ]); } create(value?: PartialMessage): Op { - const message = { entity: "", actions: [] }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.entity = ""; + message.actions = []; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -21899,13 +23483,15 @@ class CheckMacPermRequest$Type extends MessageType { constructor() { super("lnrpc.CheckMacPermRequest", [ { no: 1, name: "macaroon", kind: "scalar", T: 12 /*ScalarType.BYTES*/ }, - { no: 2, name: "permissions", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => MacaroonPermission }, + { no: 2, name: "permissions", kind: "message", repeat: 2 /*RepeatType.UNPACKED*/, T: () => MacaroonPermission }, { no: 3, name: "fullMethod", kind: "scalar", T: 9 /*ScalarType.STRING*/ } ]); } create(value?: PartialMessage): CheckMacPermRequest { - const message = { macaroon: new Uint8Array(0), permissions: [], fullMethod: "" }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.macaroon = new Uint8Array(0); + message.permissions = []; + message.fullMethod = ""; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -21963,8 +23549,8 @@ class CheckMacPermResponse$Type extends MessageType { ]); } create(value?: PartialMessage): CheckMacPermResponse { - const message = { valid: false }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.valid = false; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -22013,12 +23599,18 @@ class RPCMiddlewareRequest$Type extends MessageType { { no: 5, name: "request", kind: "message", oneof: "interceptType", T: () => RPCMessage }, { no: 6, name: "response", kind: "message", oneof: "interceptType", T: () => RPCMessage }, { no: 8, name: "reg_complete", kind: "scalar", oneof: "interceptType", T: 8 /*ScalarType.BOOL*/ }, - { no: 7, name: "msg_id", kind: "scalar", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ } + { no: 7, name: "msg_id", kind: "scalar", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ }, + { no: 9, name: "metadata_pairs", kind: "map", K: 9 /*ScalarType.STRING*/, V: { kind: "message", T: () => MetadataValues } } ]); } create(value?: PartialMessage): RPCMiddlewareRequest { - const message = { requestId: 0n, rawMacaroon: new Uint8Array(0), customCaveatCondition: "", interceptType: { oneofKind: undefined }, msgId: 0n }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.requestId = 0n; + message.rawMacaroon = new Uint8Array(0); + message.customCaveatCondition = ""; + message.interceptType = { oneofKind: undefined }; + message.msgId = 0n; + message.metadataPairs = {}; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -22064,6 +23656,9 @@ class RPCMiddlewareRequest$Type extends MessageType { case /* uint64 msg_id */ 7: message.msgId = reader.uint64().toBigInt(); break; + case /* map metadata_pairs */ 9: + this.binaryReadMap9(message.metadataPairs, reader, options); + break; default: let u = options.readUnknownField; if (u === "throw") @@ -22075,6 +23670,22 @@ class RPCMiddlewareRequest$Type extends MessageType { } return message; } + private binaryReadMap9(map: RPCMiddlewareRequest["metadataPairs"], reader: IBinaryReader, options: BinaryReadOptions): void { + let len = reader.uint32(), end = reader.pos + len, key: keyof RPCMiddlewareRequest["metadataPairs"] | undefined, val: RPCMiddlewareRequest["metadataPairs"][any] | undefined; + while (reader.pos < end) { + let [fieldNo, wireType] = reader.tag(); + switch (fieldNo) { + case 1: + key = reader.string(); + break; + case 2: + val = MetadataValues.internalBinaryRead(reader, reader.uint32(), options); + break; + default: throw new globalThis.Error("unknown map entry field for lnrpc.RPCMiddlewareRequest.metadata_pairs"); + } + } + map[key ?? ""] = val ?? MetadataValues.create(); + } internalBinaryWrite(message: RPCMiddlewareRequest, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter { /* uint64 request_id = 1; */ if (message.requestId !== 0n) @@ -22094,12 +23705,19 @@ class RPCMiddlewareRequest$Type extends MessageType { /* lnrpc.RPCMessage response = 6; */ if (message.interceptType.oneofKind === "response") RPCMessage.internalBinaryWrite(message.interceptType.response, writer.tag(6, WireType.LengthDelimited).fork(), options).join(); - /* bool reg_complete = 8; */ - if (message.interceptType.oneofKind === "regComplete") - writer.tag(8, WireType.Varint).bool(message.interceptType.regComplete); /* uint64 msg_id = 7; */ if (message.msgId !== 0n) writer.tag(7, WireType.Varint).uint64(message.msgId); + /* bool reg_complete = 8; */ + if (message.interceptType.oneofKind === "regComplete") + writer.tag(8, WireType.Varint).bool(message.interceptType.regComplete); + /* map metadata_pairs = 9; */ + for (let k of globalThis.Object.keys(message.metadataPairs)) { + writer.tag(9, WireType.LengthDelimited).fork().tag(1, WireType.LengthDelimited).string(k); + writer.tag(2, WireType.LengthDelimited).fork(); + MetadataValues.internalBinaryWrite(message.metadataPairs[k], writer, options); + writer.join().join(); + } let u = options.writeUnknownFields; if (u !== false) (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer); @@ -22111,6 +23729,53 @@ class RPCMiddlewareRequest$Type extends MessageType { */ export const RPCMiddlewareRequest = new RPCMiddlewareRequest$Type(); // @generated message type with reflection information, may provide speed optimized methods +class MetadataValues$Type extends MessageType { + constructor() { + super("lnrpc.MetadataValues", [ + { no: 1, name: "values", kind: "scalar", repeat: 2 /*RepeatType.UNPACKED*/, T: 9 /*ScalarType.STRING*/ } + ]); + } + create(value?: PartialMessage): MetadataValues { + const message = globalThis.Object.create((this.messagePrototype!)); + message.values = []; + if (value !== undefined) + reflectionMergePartial(this, message, value); + return message; + } + internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: MetadataValues): MetadataValues { + let message = target ?? this.create(), end = reader.pos + length; + while (reader.pos < end) { + let [fieldNo, wireType] = reader.tag(); + switch (fieldNo) { + case /* repeated string values */ 1: + message.values.push(reader.string()); + break; + default: + let u = options.readUnknownField; + if (u === "throw") + throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`); + let d = reader.skip(wireType); + if (u !== false) + (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d); + } + } + return message; + } + internalBinaryWrite(message: MetadataValues, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter { + /* repeated string values = 1; */ + for (let i = 0; i < message.values.length; i++) + writer.tag(1, WireType.LengthDelimited).string(message.values[i]); + let u = options.writeUnknownFields; + if (u !== false) + (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer); + return writer; + } +} +/** + * @generated MessageType for protobuf message lnrpc.MetadataValues + */ +export const MetadataValues = new MetadataValues$Type(); +// @generated message type with reflection information, may provide speed optimized methods class StreamAuth$Type extends MessageType { constructor() { super("lnrpc.StreamAuth", [ @@ -22118,8 +23783,8 @@ class StreamAuth$Type extends MessageType { ]); } create(value?: PartialMessage): StreamAuth { - const message = { methodFullUri: "" }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.methodFullUri = ""; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -22169,8 +23834,12 @@ class RPCMessage$Type extends MessageType { ]); } create(value?: PartialMessage): RPCMessage { - const message = { methodFullUri: "", streamRpc: false, typeName: "", serialized: new Uint8Array(0), isError: false }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.methodFullUri = ""; + message.streamRpc = false; + message.typeName = ""; + message.serialized = new Uint8Array(0); + message.isError = false; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -22242,8 +23911,9 @@ class RPCMiddlewareResponse$Type extends MessageType { ]); } create(value?: PartialMessage): RPCMiddlewareResponse { - const message = { refMsgId: 0n, middlewareMessage: { oneofKind: undefined } }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.refMsgId = 0n; + message.middlewareMessage = { oneofKind: undefined }; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -22309,8 +23979,10 @@ class MiddlewareRegistration$Type extends MessageType { ]); } create(value?: PartialMessage): MiddlewareRegistration { - const message = { middlewareName: "", customMacaroonCaveatName: "", readOnlyMode: false }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.middlewareName = ""; + message.customMacaroonCaveatName = ""; + message.readOnlyMode = false; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -22370,8 +24042,10 @@ class InterceptFeedback$Type extends MessageType { ]); } create(value?: PartialMessage): InterceptFeedback { - const message = { error: "", replaceResponse: false, replacementSerialized: new Uint8Array(0) }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.error = ""; + message.replaceResponse = false; + message.replacementSerialized = new Uint8Array(0); if (value !== undefined) reflectionMergePartial(this, message, value); return message; diff --git a/proto/lnd/router.client.ts b/proto/lnd/router.client.ts index 27722e38..b4fb0b18 100644 --- a/proto/lnd/router.client.ts +++ b/proto/lnd/router.client.ts @@ -1,9 +1,13 @@ -// @generated by protobuf-ts 2.8.1 +// @generated by protobuf-ts 2.11.1 // @generated from protobuf file "router.proto" (package "routerrpc", syntax proto3) // tslint:disable import type { RpcTransport } from "@protobuf-ts/runtime-rpc"; import type { ServiceInfo } from "@protobuf-ts/runtime-rpc"; import { Router } from "./router.js"; +import type { DeleteAliasesResponse } from "./router.js"; +import type { DeleteAliasesRequest } from "./router.js"; +import type { AddAliasesResponse } from "./router.js"; +import type { AddAliasesRequest } from "./router.js"; import type { UpdateChanStatusResponse } from "./router.js"; import type { UpdateChanStatusRequest } from "./router.js"; import type { ForwardHtlcInterceptRequest } from "./router.js"; @@ -39,6 +43,23 @@ import type { Payment } from "./lightning.js"; import type { SendPaymentRequest } from "./router.js"; import type { ServerStreamingCall } from "@protobuf-ts/runtime-rpc"; import type { RpcOptions } from "@protobuf-ts/runtime-rpc"; +// +// Comments in this file will be directly parsed into the API +// Documentation as descriptions of the associated method, message, or field. +// These descriptions should go right above the definition of the object, and +// can be in either block or // comment format. +// +// An RPC method can be matched to an lncli command by placing a line in the +// beginning of the description in exactly the following format: +// lncli: `methodname` +// +// Failure to specify the exact name of the command will cause documentation +// generation to fail. +// +// More information on how exactly the gRPC documentation is generated from +// this proto file can be found here: +// https://github.com/lightninglabs/lightning-api + /** * Router is a service that offers advanced interaction with the router * subsystem of the daemon. @@ -50,17 +71,20 @@ export interface IRouterClient { * * SendPaymentV2 attempts to route a payment described by the passed * PaymentRequest to the final destination. The call returns a stream of - * payment updates. + * payment updates. When using this RPC, make sure to set a fee limit, as the + * default routing fee limit is 0 sats. Without a non-zero fee limit only + * routes without fees will be attempted which often fails with + * FAILURE_REASON_NO_ROUTE. * - * @generated from protobuf rpc: SendPaymentV2(routerrpc.SendPaymentRequest) returns (stream lnrpc.Payment); + * @generated from protobuf rpc: SendPaymentV2 */ sendPaymentV2(input: SendPaymentRequest, options?: RpcOptions): ServerStreamingCall; /** - * + * lncli: `trackpayment` * TrackPaymentV2 returns an update stream for the payment identified by the * payment hash. * - * @generated from protobuf rpc: TrackPaymentV2(routerrpc.TrackPaymentRequest) returns (stream lnrpc.Payment); + * @generated from protobuf rpc: TrackPaymentV2 */ trackPaymentV2(input: TrackPaymentRequest, options?: RpcOptions): ServerStreamingCall; /** @@ -72,7 +96,7 @@ export interface IRouterClient { * payment attempt make sure to subscribe to this method before initiating any * payments. * - * @generated from protobuf rpc: TrackPayments(routerrpc.TrackPaymentsRequest) returns (stream lnrpc.Payment); + * @generated from protobuf rpc: TrackPayments */ trackPayments(input: TrackPaymentsRequest, options?: RpcOptions): ServerStreamingCall; /** @@ -80,7 +104,7 @@ export interface IRouterClient { * EstimateRouteFee allows callers to obtain a lower bound w.r.t how much it * may cost to send an HTLC to the target end destination. * - * @generated from protobuf rpc: EstimateRouteFee(routerrpc.RouteFeeRequest) returns (routerrpc.RouteFeeResponse); + * @generated from protobuf rpc: EstimateRouteFee */ estimateRouteFee(input: RouteFeeRequest, options?: RpcOptions): UnaryCall; /** @@ -92,7 +116,7 @@ export interface IRouterClient { * SendToRouteV2 in that it doesn't return the full HTLC information. * * @deprecated - * @generated from protobuf rpc: SendToRoute(routerrpc.SendToRouteRequest) returns (routerrpc.SendToRouteResponse); + * @generated from protobuf rpc: SendToRoute */ sendToRoute(input: SendToRouteRequest, options?: RpcOptions): UnaryCall; /** @@ -102,65 +126,71 @@ export interface IRouterClient { * route manually. This can be used for things like rebalancing, and atomic * swaps. * - * @generated from protobuf rpc: SendToRouteV2(routerrpc.SendToRouteRequest) returns (lnrpc.HTLCAttempt); + * @generated from protobuf rpc: SendToRouteV2 */ sendToRouteV2(input: SendToRouteRequest, options?: RpcOptions): UnaryCall; /** - * + * lncli: `resetmc` * ResetMissionControl clears all mission control state and starts with a clean * slate. * - * @generated from protobuf rpc: ResetMissionControl(routerrpc.ResetMissionControlRequest) returns (routerrpc.ResetMissionControlResponse); + * @generated from protobuf rpc: ResetMissionControl */ resetMissionControl(input: ResetMissionControlRequest, options?: RpcOptions): UnaryCall; /** - * + * lncli: `querymc` * QueryMissionControl exposes the internal mission control state to callers. * It is a development feature. * - * @generated from protobuf rpc: QueryMissionControl(routerrpc.QueryMissionControlRequest) returns (routerrpc.QueryMissionControlResponse); + * @generated from protobuf rpc: QueryMissionControl */ queryMissionControl(input: QueryMissionControlRequest, options?: RpcOptions): UnaryCall; /** - * + * lncli: `importmc` * XImportMissionControl is an experimental API that imports the state provided * to the internal mission control's state, using all results which are more * recent than our existing values. These values will only be imported * in-memory, and will not be persisted across restarts. * - * @generated from protobuf rpc: XImportMissionControl(routerrpc.XImportMissionControlRequest) returns (routerrpc.XImportMissionControlResponse); + * @generated from protobuf rpc: XImportMissionControl */ xImportMissionControl(input: XImportMissionControlRequest, options?: RpcOptions): UnaryCall; /** - * + * lncli: `getmccfg` * GetMissionControlConfig returns mission control's current config. * - * @generated from protobuf rpc: GetMissionControlConfig(routerrpc.GetMissionControlConfigRequest) returns (routerrpc.GetMissionControlConfigResponse); + * @generated from protobuf rpc: GetMissionControlConfig */ getMissionControlConfig(input: GetMissionControlConfigRequest, options?: RpcOptions): UnaryCall; /** - * + * lncli: `setmccfg` * SetMissionControlConfig will set mission control's config, if the config * provided is valid. * - * @generated from protobuf rpc: SetMissionControlConfig(routerrpc.SetMissionControlConfigRequest) returns (routerrpc.SetMissionControlConfigResponse); + * @generated from protobuf rpc: SetMissionControlConfig */ setMissionControlConfig(input: SetMissionControlConfigRequest, options?: RpcOptions): UnaryCall; /** + * lncli: `queryprob` + * Deprecated. QueryProbability returns the current success probability + * estimate for a given node pair and amount. The call returns a zero success + * probability if no channel is available or if the amount violates min/max + * HTLC constraints. * - * QueryProbability returns the current success probability estimate for a - * given node pair and amount. - * - * @generated from protobuf rpc: QueryProbability(routerrpc.QueryProbabilityRequest) returns (routerrpc.QueryProbabilityResponse); + * @generated from protobuf rpc: QueryProbability */ queryProbability(input: QueryProbabilityRequest, options?: RpcOptions): UnaryCall; /** - * + * lncli: `buildroute` * BuildRoute builds a fully specified route based on a list of hop public * keys. It retrieves the relevant channel policies from the graph in order to * calculate the correct fees and time locks. + * Note that LND will use its default final_cltv_delta if no value is supplied. + * Make sure to add the correct final_cltv_delta depending on the invoice + * restriction. Moreover the caller has to make sure to provide the + * payment_addr if the route is paying an invoice which signaled it. * - * @generated from protobuf rpc: BuildRoute(routerrpc.BuildRouteRequest) returns (routerrpc.BuildRouteResponse); + * @generated from protobuf rpc: BuildRoute */ buildRoute(input: BuildRouteRequest, options?: RpcOptions): UnaryCall; /** @@ -168,7 +198,7 @@ export interface IRouterClient { * SubscribeHtlcEvents creates a uni-directional stream from the server to * the client which delivers a stream of htlc events. * - * @generated from protobuf rpc: SubscribeHtlcEvents(routerrpc.SubscribeHtlcEventsRequest) returns (stream routerrpc.HtlcEvent); + * @generated from protobuf rpc: SubscribeHtlcEvents */ subscribeHtlcEvents(input: SubscribeHtlcEventsRequest, options?: RpcOptions): ServerStreamingCall; /** @@ -178,7 +208,7 @@ export interface IRouterClient { * returns a stream of payment status updates. * * @deprecated - * @generated from protobuf rpc: SendPayment(routerrpc.SendPaymentRequest) returns (stream routerrpc.PaymentStatus); + * @generated from protobuf rpc: SendPayment */ sendPayment(input: SendPaymentRequest, options?: RpcOptions): ServerStreamingCall; /** @@ -187,7 +217,7 @@ export interface IRouterClient { * the payment identified by the payment hash. * * @deprecated - * @generated from protobuf rpc: TrackPayment(routerrpc.TrackPaymentRequest) returns (stream routerrpc.PaymentStatus); + * @generated from protobuf rpc: TrackPayment */ trackPayment(input: TrackPaymentRequest, options?: RpcOptions): ServerStreamingCall; /** @@ -198,20 +228,59 @@ export interface IRouterClient { * In case of interception, the htlc can be either settled, cancelled or * resumed later by using the ResolveHoldForward endpoint. * - * @generated from protobuf rpc: HtlcInterceptor(stream routerrpc.ForwardHtlcInterceptResponse) returns (stream routerrpc.ForwardHtlcInterceptRequest); + * @generated from protobuf rpc: HtlcInterceptor */ htlcInterceptor(options?: RpcOptions): DuplexStreamingCall; /** - * + * lncli: `updatechanstatus` * UpdateChanStatus attempts to manually set the state of a channel * (enabled, disabled, or auto). A manual "disable" request will cause the * channel to stay disabled until a subsequent manual request of either * "enable" or "auto". * - * @generated from protobuf rpc: UpdateChanStatus(routerrpc.UpdateChanStatusRequest) returns (routerrpc.UpdateChanStatusResponse); + * @generated from protobuf rpc: UpdateChanStatus */ updateChanStatus(input: UpdateChanStatusRequest, options?: RpcOptions): UnaryCall; + /** + * + * XAddLocalChanAliases is an experimental API that creates a set of new + * channel SCID alias mappings. The final total set of aliases in the manager + * after the add operation is returned. This is only a locally stored alias, + * and will not be communicated to the channel peer via any message. Therefore, + * routing over such an alias will only work if the peer also calls this same + * RPC on their end. If an alias already exists, an error is returned + * + * @generated from protobuf rpc: XAddLocalChanAliases + */ + xAddLocalChanAliases(input: AddAliasesRequest, options?: RpcOptions): UnaryCall; + /** + * + * XDeleteLocalChanAliases is an experimental API that deletes a set of alias + * mappings. The final total set of aliases in the manager after the delete + * operation is returned. The deletion will not be communicated to the channel + * peer via any message. + * + * @generated from protobuf rpc: XDeleteLocalChanAliases + */ + xDeleteLocalChanAliases(input: DeleteAliasesRequest, options?: RpcOptions): UnaryCall; } +// +// Comments in this file will be directly parsed into the API +// Documentation as descriptions of the associated method, message, or field. +// These descriptions should go right above the definition of the object, and +// can be in either block or // comment format. +// +// An RPC method can be matched to an lncli command by placing a line in the +// beginning of the description in exactly the following format: +// lncli: `methodname` +// +// Failure to specify the exact name of the command will cause documentation +// generation to fail. +// +// More information on how exactly the gRPC documentation is generated from +// this proto file can be found here: +// https://github.com/lightninglabs/lightning-api + /** * Router is a service that offers advanced interaction with the router * subsystem of the daemon. @@ -228,20 +297,23 @@ export class RouterClient implements IRouterClient, ServiceInfo { * * SendPaymentV2 attempts to route a payment described by the passed * PaymentRequest to the final destination. The call returns a stream of - * payment updates. + * payment updates. When using this RPC, make sure to set a fee limit, as the + * default routing fee limit is 0 sats. Without a non-zero fee limit only + * routes without fees will be attempted which often fails with + * FAILURE_REASON_NO_ROUTE. * - * @generated from protobuf rpc: SendPaymentV2(routerrpc.SendPaymentRequest) returns (stream lnrpc.Payment); + * @generated from protobuf rpc: SendPaymentV2 */ sendPaymentV2(input: SendPaymentRequest, options?: RpcOptions): ServerStreamingCall { const method = this.methods[0], opt = this._transport.mergeOptions(options); return stackIntercept("serverStreaming", this._transport, method, opt, input); } /** - * + * lncli: `trackpayment` * TrackPaymentV2 returns an update stream for the payment identified by the * payment hash. * - * @generated from protobuf rpc: TrackPaymentV2(routerrpc.TrackPaymentRequest) returns (stream lnrpc.Payment); + * @generated from protobuf rpc: TrackPaymentV2 */ trackPaymentV2(input: TrackPaymentRequest, options?: RpcOptions): ServerStreamingCall { const method = this.methods[1], opt = this._transport.mergeOptions(options); @@ -256,7 +328,7 @@ export class RouterClient implements IRouterClient, ServiceInfo { * payment attempt make sure to subscribe to this method before initiating any * payments. * - * @generated from protobuf rpc: TrackPayments(routerrpc.TrackPaymentsRequest) returns (stream lnrpc.Payment); + * @generated from protobuf rpc: TrackPayments */ trackPayments(input: TrackPaymentsRequest, options?: RpcOptions): ServerStreamingCall { const method = this.methods[2], opt = this._transport.mergeOptions(options); @@ -267,7 +339,7 @@ export class RouterClient implements IRouterClient, ServiceInfo { * EstimateRouteFee allows callers to obtain a lower bound w.r.t how much it * may cost to send an HTLC to the target end destination. * - * @generated from protobuf rpc: EstimateRouteFee(routerrpc.RouteFeeRequest) returns (routerrpc.RouteFeeResponse); + * @generated from protobuf rpc: EstimateRouteFee */ estimateRouteFee(input: RouteFeeRequest, options?: RpcOptions): UnaryCall { const method = this.methods[3], opt = this._transport.mergeOptions(options); @@ -282,7 +354,7 @@ export class RouterClient implements IRouterClient, ServiceInfo { * SendToRouteV2 in that it doesn't return the full HTLC information. * * @deprecated - * @generated from protobuf rpc: SendToRoute(routerrpc.SendToRouteRequest) returns (routerrpc.SendToRouteResponse); + * @generated from protobuf rpc: SendToRoute */ sendToRoute(input: SendToRouteRequest, options?: RpcOptions): UnaryCall { const method = this.methods[4], opt = this._transport.mergeOptions(options); @@ -295,86 +367,92 @@ export class RouterClient implements IRouterClient, ServiceInfo { * route manually. This can be used for things like rebalancing, and atomic * swaps. * - * @generated from protobuf rpc: SendToRouteV2(routerrpc.SendToRouteRequest) returns (lnrpc.HTLCAttempt); + * @generated from protobuf rpc: SendToRouteV2 */ sendToRouteV2(input: SendToRouteRequest, options?: RpcOptions): UnaryCall { const method = this.methods[5], opt = this._transport.mergeOptions(options); return stackIntercept("unary", this._transport, method, opt, input); } /** - * + * lncli: `resetmc` * ResetMissionControl clears all mission control state and starts with a clean * slate. * - * @generated from protobuf rpc: ResetMissionControl(routerrpc.ResetMissionControlRequest) returns (routerrpc.ResetMissionControlResponse); + * @generated from protobuf rpc: ResetMissionControl */ resetMissionControl(input: ResetMissionControlRequest, options?: RpcOptions): UnaryCall { const method = this.methods[6], opt = this._transport.mergeOptions(options); return stackIntercept("unary", this._transport, method, opt, input); } /** - * + * lncli: `querymc` * QueryMissionControl exposes the internal mission control state to callers. * It is a development feature. * - * @generated from protobuf rpc: QueryMissionControl(routerrpc.QueryMissionControlRequest) returns (routerrpc.QueryMissionControlResponse); + * @generated from protobuf rpc: QueryMissionControl */ queryMissionControl(input: QueryMissionControlRequest, options?: RpcOptions): UnaryCall { const method = this.methods[7], opt = this._transport.mergeOptions(options); return stackIntercept("unary", this._transport, method, opt, input); } /** - * + * lncli: `importmc` * XImportMissionControl is an experimental API that imports the state provided * to the internal mission control's state, using all results which are more * recent than our existing values. These values will only be imported * in-memory, and will not be persisted across restarts. * - * @generated from protobuf rpc: XImportMissionControl(routerrpc.XImportMissionControlRequest) returns (routerrpc.XImportMissionControlResponse); + * @generated from protobuf rpc: XImportMissionControl */ xImportMissionControl(input: XImportMissionControlRequest, options?: RpcOptions): UnaryCall { const method = this.methods[8], opt = this._transport.mergeOptions(options); return stackIntercept("unary", this._transport, method, opt, input); } /** - * + * lncli: `getmccfg` * GetMissionControlConfig returns mission control's current config. * - * @generated from protobuf rpc: GetMissionControlConfig(routerrpc.GetMissionControlConfigRequest) returns (routerrpc.GetMissionControlConfigResponse); + * @generated from protobuf rpc: GetMissionControlConfig */ getMissionControlConfig(input: GetMissionControlConfigRequest, options?: RpcOptions): UnaryCall { const method = this.methods[9], opt = this._transport.mergeOptions(options); return stackIntercept("unary", this._transport, method, opt, input); } /** - * + * lncli: `setmccfg` * SetMissionControlConfig will set mission control's config, if the config * provided is valid. * - * @generated from protobuf rpc: SetMissionControlConfig(routerrpc.SetMissionControlConfigRequest) returns (routerrpc.SetMissionControlConfigResponse); + * @generated from protobuf rpc: SetMissionControlConfig */ setMissionControlConfig(input: SetMissionControlConfigRequest, options?: RpcOptions): UnaryCall { const method = this.methods[10], opt = this._transport.mergeOptions(options); return stackIntercept("unary", this._transport, method, opt, input); } /** + * lncli: `queryprob` + * Deprecated. QueryProbability returns the current success probability + * estimate for a given node pair and amount. The call returns a zero success + * probability if no channel is available or if the amount violates min/max + * HTLC constraints. * - * QueryProbability returns the current success probability estimate for a - * given node pair and amount. - * - * @generated from protobuf rpc: QueryProbability(routerrpc.QueryProbabilityRequest) returns (routerrpc.QueryProbabilityResponse); + * @generated from protobuf rpc: QueryProbability */ queryProbability(input: QueryProbabilityRequest, options?: RpcOptions): UnaryCall { const method = this.methods[11], opt = this._transport.mergeOptions(options); return stackIntercept("unary", this._transport, method, opt, input); } /** - * + * lncli: `buildroute` * BuildRoute builds a fully specified route based on a list of hop public * keys. It retrieves the relevant channel policies from the graph in order to * calculate the correct fees and time locks. + * Note that LND will use its default final_cltv_delta if no value is supplied. + * Make sure to add the correct final_cltv_delta depending on the invoice + * restriction. Moreover the caller has to make sure to provide the + * payment_addr if the route is paying an invoice which signaled it. * - * @generated from protobuf rpc: BuildRoute(routerrpc.BuildRouteRequest) returns (routerrpc.BuildRouteResponse); + * @generated from protobuf rpc: BuildRoute */ buildRoute(input: BuildRouteRequest, options?: RpcOptions): UnaryCall { const method = this.methods[12], opt = this._transport.mergeOptions(options); @@ -385,7 +463,7 @@ export class RouterClient implements IRouterClient, ServiceInfo { * SubscribeHtlcEvents creates a uni-directional stream from the server to * the client which delivers a stream of htlc events. * - * @generated from protobuf rpc: SubscribeHtlcEvents(routerrpc.SubscribeHtlcEventsRequest) returns (stream routerrpc.HtlcEvent); + * @generated from protobuf rpc: SubscribeHtlcEvents */ subscribeHtlcEvents(input: SubscribeHtlcEventsRequest, options?: RpcOptions): ServerStreamingCall { const method = this.methods[13], opt = this._transport.mergeOptions(options); @@ -398,7 +476,7 @@ export class RouterClient implements IRouterClient, ServiceInfo { * returns a stream of payment status updates. * * @deprecated - * @generated from protobuf rpc: SendPayment(routerrpc.SendPaymentRequest) returns (stream routerrpc.PaymentStatus); + * @generated from protobuf rpc: SendPayment */ sendPayment(input: SendPaymentRequest, options?: RpcOptions): ServerStreamingCall { const method = this.methods[14], opt = this._transport.mergeOptions(options); @@ -410,7 +488,7 @@ export class RouterClient implements IRouterClient, ServiceInfo { * the payment identified by the payment hash. * * @deprecated - * @generated from protobuf rpc: TrackPayment(routerrpc.TrackPaymentRequest) returns (stream routerrpc.PaymentStatus); + * @generated from protobuf rpc: TrackPayment */ trackPayment(input: TrackPaymentRequest, options?: RpcOptions): ServerStreamingCall { const method = this.methods[15], opt = this._transport.mergeOptions(options); @@ -424,23 +502,51 @@ export class RouterClient implements IRouterClient, ServiceInfo { * In case of interception, the htlc can be either settled, cancelled or * resumed later by using the ResolveHoldForward endpoint. * - * @generated from protobuf rpc: HtlcInterceptor(stream routerrpc.ForwardHtlcInterceptResponse) returns (stream routerrpc.ForwardHtlcInterceptRequest); + * @generated from protobuf rpc: HtlcInterceptor */ htlcInterceptor(options?: RpcOptions): DuplexStreamingCall { const method = this.methods[16], opt = this._transport.mergeOptions(options); return stackIntercept("duplex", this._transport, method, opt); } /** - * + * lncli: `updatechanstatus` * UpdateChanStatus attempts to manually set the state of a channel * (enabled, disabled, or auto). A manual "disable" request will cause the * channel to stay disabled until a subsequent manual request of either * "enable" or "auto". * - * @generated from protobuf rpc: UpdateChanStatus(routerrpc.UpdateChanStatusRequest) returns (routerrpc.UpdateChanStatusResponse); + * @generated from protobuf rpc: UpdateChanStatus */ updateChanStatus(input: UpdateChanStatusRequest, options?: RpcOptions): UnaryCall { const method = this.methods[17], opt = this._transport.mergeOptions(options); return stackIntercept("unary", this._transport, method, opt, input); } + /** + * + * XAddLocalChanAliases is an experimental API that creates a set of new + * channel SCID alias mappings. The final total set of aliases in the manager + * after the add operation is returned. This is only a locally stored alias, + * and will not be communicated to the channel peer via any message. Therefore, + * routing over such an alias will only work if the peer also calls this same + * RPC on their end. If an alias already exists, an error is returned + * + * @generated from protobuf rpc: XAddLocalChanAliases + */ + xAddLocalChanAliases(input: AddAliasesRequest, options?: RpcOptions): UnaryCall { + const method = this.methods[18], opt = this._transport.mergeOptions(options); + return stackIntercept("unary", this._transport, method, opt, input); + } + /** + * + * XDeleteLocalChanAliases is an experimental API that deletes a set of alias + * mappings. The final total set of aliases in the manager after the delete + * operation is returned. The deletion will not be communicated to the channel + * peer via any message. + * + * @generated from protobuf rpc: XDeleteLocalChanAliases + */ + xDeleteLocalChanAliases(input: DeleteAliasesRequest, options?: RpcOptions): UnaryCall { + const method = this.methods[19], opt = this._transport.mergeOptions(options); + return stackIntercept("unary", this._transport, method, opt, input); + } } diff --git a/proto/lnd/router.ts b/proto/lnd/router.ts index edb624cd..07dd2006 100644 --- a/proto/lnd/router.ts +++ b/proto/lnd/router.ts @@ -1,4 +1,4 @@ -// @generated by protobuf-ts 2.8.1 +// @generated by protobuf-ts 2.11.1 // @generated from protobuf file "router.proto" (package "routerrpc", syntax proto3) // tslint:disable import { Payment } from "./lightning.js"; @@ -11,13 +11,14 @@ import { UnknownFieldHandler } from "@protobuf-ts/runtime"; import { WireType } from "@protobuf-ts/runtime"; import type { PartialMessage } from "@protobuf-ts/runtime"; import { reflectionMergePartial } from "@protobuf-ts/runtime"; -import { MESSAGE_TYPE } from "@protobuf-ts/runtime"; import { MessageType } from "@protobuf-ts/runtime"; +import { AliasMap } from "./lightning.js"; import { ChannelPoint } from "./lightning.js"; import { HTLCAttempt } from "./lightning.js"; import { Failure_FailureCode } from "./lightning.js"; import { Failure } from "./lightning.js"; import { Route } from "./lightning.js"; +import { PaymentFailureReason } from "./lightning.js"; import { FeatureBit } from "./lightning.js"; import { RouteHint } from "./lightning.js"; /** @@ -27,7 +28,7 @@ export interface SendPaymentRequest { /** * The identity pubkey of the payment recipient * - * @generated from protobuf field: bytes dest = 1; + * @generated from protobuf field: bytes dest = 1 */ dest: Uint8Array; /** @@ -36,22 +37,13 @@ export interface SendPaymentRequest { * * The fields amt and amt_msat are mutually exclusive. * - * @generated from protobuf field: int64 amt = 2; + * @generated from protobuf field: int64 amt = 2 */ amt: bigint; - /** - * - * Number of millisatoshis to send. - * - * The fields amt and amt_msat are mutually exclusive. - * - * @generated from protobuf field: int64 amt_msat = 12; - */ - amtMsat: bigint; /** * The hash to use within the payment's HTLC * - * @generated from protobuf field: bytes payment_hash = 3; + * @generated from protobuf field: bytes payment_hash = 3 */ paymentHash: Uint8Array; /** @@ -59,15 +51,9 @@ export interface SendPaymentRequest { * The CLTV delta from the current height that should be used to set the * timelock for the final hop. * - * @generated from protobuf field: int32 final_cltv_delta = 4; + * @generated from protobuf field: int32 final_cltv_delta = 4 */ finalCltvDelta: number; - /** - * An optional payment addr to be included within the last hop of the route. - * - * @generated from protobuf field: bytes payment_addr = 20; - */ - paymentAddr: Uint8Array; /** * * A bare-bones invoice for a payment within the Lightning Network. With the @@ -76,17 +62,18 @@ export interface SendPaymentRequest { * that case it is required to set the amt field as well. If no payment request * is specified, the following fields are required: dest, amt and payment_hash. * - * @generated from protobuf field: string payment_request = 5; + * @generated from protobuf field: string payment_request = 5 */ paymentRequest: string; /** * - * An upper limit on the amount of time we should spend when attempting to - * fulfill the payment. This is expressed in seconds. If we cannot make a - * successful payment within this time frame, an error will be returned. - * This field must be non-zero. + * An optional limit, expressed in seconds, on the time to wait before + * attempting the first HTLC. Once HTLCs are in flight, the payment will + * not be aborted until the HTLCs are either settled or failed. If the field + * is not set or is explicitly set to zero, the default value of 60 seconds + * will be applied. * - * @generated from protobuf field: int32 timeout_seconds = 6; + * @generated from protobuf field: int32 timeout_seconds = 6 */ timeoutSeconds: number; /** @@ -98,22 +85,9 @@ export interface SendPaymentRequest { * * The fields fee_limit_sat and fee_limit_msat are mutually exclusive. * - * @generated from protobuf field: int64 fee_limit_sat = 7; + * @generated from protobuf field: int64 fee_limit_sat = 7 */ feeLimitSat: bigint; - /** - * - * The maximum number of millisatoshis that will be paid as a fee of the - * payment. If this field is left to the default value of 0, only zero-fee - * routes will be considered. This usually means single hop routes connecting - * directly to the destination. To send the payment without a fee limit, use - * max int here. - * - * The fields fee_limit_sat and fee_limit_msat are mutually exclusive. - * - * @generated from protobuf field: int64 fee_limit_msat = 13; - */ - feeLimitMsat: bigint; /** * * Deprecated, use outgoing_chan_ids. The channel id of the channel that must @@ -121,38 +95,23 @@ export interface SendPaymentRequest { * outgoing_chan_ids are set). * * @deprecated - * @generated from protobuf field: uint64 outgoing_chan_id = 8 [deprecated = true, jstype = JS_STRING]; + * @generated from protobuf field: uint64 outgoing_chan_id = 8 [jstype = JS_STRING, deprecated = true] */ outgoingChanId: string; /** * - * The channel ids of the channels are allowed for the first hop. If empty, - * any channel may be used. - * - * @generated from protobuf field: repeated uint64 outgoing_chan_ids = 19; - */ - outgoingChanIds: bigint[]; - /** - * - * The pubkey of the last hop of the route. If empty, any hop may be used. - * - * @generated from protobuf field: bytes last_hop_pubkey = 14; - */ - lastHopPubkey: Uint8Array; - /** - * - * An optional maximum total time lock for the route. This should not exceed - * lnd's `--max-cltv-expiry` setting. If zero, then the value of + * An optional maximum total time lock for the route. This should not + * exceed lnd's `--max-cltv-expiry` setting. If zero, then the value of * `--max-cltv-expiry` is enforced. * - * @generated from protobuf field: int32 cltv_limit = 9; + * @generated from protobuf field: int32 cltv_limit = 9 */ cltvLimit: number; /** * * Optional route hints to reach the destination through private channels. * - * @generated from protobuf field: repeated lnrpc.RouteHint route_hints = 10; + * @generated from protobuf field: repeated lnrpc.RouteHint route_hints = 10 */ routeHints: RouteHint[]; /** @@ -163,15 +122,44 @@ export interface SendPaymentRequest { * required to be in the custom range >= 65536. When using REST, the values * must be encoded as base64. * - * @generated from protobuf field: map dest_custom_records = 11; + * @generated from protobuf field: map dest_custom_records = 11 */ destCustomRecords: { [key: string]: Uint8Array; }; + /** + * + * Number of millisatoshis to send. + * + * The fields amt and amt_msat are mutually exclusive. + * + * @generated from protobuf field: int64 amt_msat = 12 + */ + amtMsat: bigint; + /** + * + * The maximum number of millisatoshis that will be paid as a fee of the + * payment. If this field is left to the default value of 0, only zero-fee + * routes will be considered. This usually means single hop routes connecting + * directly to the destination. To send the payment without a fee limit, use + * max int here. + * + * The fields fee_limit_sat and fee_limit_msat are mutually exclusive. + * + * @generated from protobuf field: int64 fee_limit_msat = 13 + */ + feeLimitMsat: bigint; + /** + * + * The pubkey of the last hop of the route. If empty, any hop may be used. + * + * @generated from protobuf field: bytes last_hop_pubkey = 14 + */ + lastHopPubkey: Uint8Array; /** * If set, circular payments to self are permitted. * - * @generated from protobuf field: bool allow_self_payment = 15; + * @generated from protobuf field: bool allow_self_payment = 15 */ allowSelfPayment: boolean; /** @@ -182,7 +170,7 @@ export interface SendPaymentRequest { * the router will try to load destination features from the graph as a * fallback. * - * @generated from protobuf field: repeated lnrpc.FeatureBit dest_features = 16; + * @generated from protobuf field: repeated lnrpc.FeatureBit dest_features = 16 */ destFeatures: FeatureBit[]; /** @@ -190,7 +178,7 @@ export interface SendPaymentRequest { * The maximum number of partial payments that may be use to complete the full * amount. * - * @generated from protobuf field: uint32 max_parts = 17; + * @generated from protobuf field: uint32 max_parts = 17 */ maxParts: number; /** @@ -198,9 +186,25 @@ export interface SendPaymentRequest { * If set, only the final payment update is streamed back. Intermediate updates * that show which htlcs are still in flight are suppressed. * - * @generated from protobuf field: bool no_inflight_updates = 18; + * @generated from protobuf field: bool no_inflight_updates = 18 */ noInflightUpdates: boolean; + /** + * + * The channel ids of the channels are allowed for the first hop. If empty, + * any channel may be used. + * + * @generated from protobuf field: repeated uint64 outgoing_chan_ids = 19 + */ + outgoingChanIds: bigint[]; + /** + * + * An optional payment addr to be included within the last hop of the route. + * This is also called payment secret in specifications (e.g. BOLT 11). + * + * @generated from protobuf field: bytes payment_addr = 20 + */ + paymentAddr: Uint8Array; /** * * The largest payment split that should be attempted when making a payment if @@ -208,14 +212,14 @@ export interface SendPaymentRequest { * split more aggressively, vs only when it thinks it needs to. Note that this * value is in milli-satoshis. * - * @generated from protobuf field: uint64 max_shard_size_msat = 21; + * @generated from protobuf field: uint64 max_shard_size_msat = 21 */ maxShardSizeMsat: bigint; /** * * If set, an AMP-payment will be attempted. * - * @generated from protobuf field: bool amp = 22; + * @generated from protobuf field: bool amp = 22 */ amp: boolean; /** @@ -223,9 +227,33 @@ export interface SendPaymentRequest { * The time preference for this payment. Set to -1 to optimize for fees * only, to 1 to optimize for reliability only or a value inbetween for a mix. * - * @generated from protobuf field: double time_pref = 23; + * @generated from protobuf field: double time_pref = 23 */ timePref: number; + /** + * + * If set, the payment loop can be interrupted by manually canceling the + * payment context, even before the payment timeout is reached. Note that the + * payment may still succeed after cancellation, as in-flight attempts can + * still settle afterwards. Canceling will only prevent further attempts from + * being sent. + * + * @generated from protobuf field: bool cancelable = 24 + */ + cancelable: boolean; + /** + * + * An optional field that can be used to pass an arbitrary set of TLV records + * to the first hop peer of this payment. This can be used to pass application + * specific data during the payment attempt. Record types are required to be in + * the custom range >= 65536. When using REST, the values must be encoded as + * base64. + * + * @generated from protobuf field: map first_hop_custom_records = 25 + */ + firstHopCustomRecords: { + [key: string]: Uint8Array; + }; } /** * @generated from protobuf message routerrpc.TrackPaymentRequest @@ -234,7 +262,7 @@ export interface TrackPaymentRequest { /** * The hash of the payment to look up. * - * @generated from protobuf field: bytes payment_hash = 1; + * @generated from protobuf field: bytes payment_hash = 1 */ paymentHash: Uint8Array; /** @@ -242,7 +270,7 @@ export interface TrackPaymentRequest { * If set, only the final payment update is streamed back. Intermediate updates * that show which htlcs are still in flight are suppressed. * - * @generated from protobuf field: bool no_inflight_updates = 2; + * @generated from protobuf field: bool no_inflight_updates = 2 */ noInflightUpdates: boolean; } @@ -255,7 +283,7 @@ export interface TrackPaymentsRequest { * If set, only the final payment updates are streamed back. Intermediate * updates that show which htlcs are still in flight are suppressed. * - * @generated from protobuf field: bool no_inflight_updates = 1; + * @generated from protobuf field: bool no_inflight_updates = 1 */ noInflightUpdates: boolean; } @@ -265,18 +293,47 @@ export interface TrackPaymentsRequest { export interface RouteFeeRequest { /** * - * The destination once wishes to obtain a routing fee quote to. + * The destination one wishes to obtain a routing fee quote to. If set, this + * parameter requires the amt_sat parameter also to be set. This parameter + * combination triggers a graph based routing fee estimation as opposed to a + * payment probe based estimate in case a payment request is provided. The + * graph based estimation is an algorithm that is executed on the in memory + * graph. Hence its runtime is significantly shorter than a payment probe + * estimation that sends out actual payments to the network. * - * @generated from protobuf field: bytes dest = 1; + * @generated from protobuf field: bytes dest = 1 */ dest: Uint8Array; /** * - * The amount one wishes to send to the target destination. + * The amount one wishes to send to the target destination. It is only to be + * used in combination with the dest parameter. * - * @generated from protobuf field: int64 amt_sat = 2; + * @generated from protobuf field: int64 amt_sat = 2 */ amtSat: bigint; + /** + * + * A payment request of the target node that the route fee request is intended + * for. Its parameters are input to probe payments that estimate routing fees. + * The timeout parameter can be specified to set a maximum time on the probing + * attempt. Cannot be used in combination with dest and amt_sat. + * + * @generated from protobuf field: string payment_request = 3 + */ + paymentRequest: string; + /** + * + * A user preference of how long a probe payment should maximally be allowed to + * take, denoted in seconds. The probing payment loop is aborted if this + * timeout is reached. Note that the probing process itself can take longer + * than the timeout if the HTLC becomes delayed or stuck. Canceling the context + * of this call will not cancel the payment loop, the duration is only + * controlled by the timeout parameter. + * + * @generated from protobuf field: uint32 timeout = 4 + */ + timeout: number; } /** * @generated from protobuf message routerrpc.RouteFeeResponse @@ -287,7 +344,7 @@ export interface RouteFeeResponse { * A lower bound of the estimated fee to the target destination within the * network, expressed in milli-satoshis. * - * @generated from protobuf field: int64 routing_fee_msat = 1; + * @generated from protobuf field: int64 routing_fee_msat = 1 */ routingFeeMsat: bigint; /** @@ -296,9 +353,17 @@ export interface RouteFeeResponse { * will still need to factor in the final CLTV delta of the last hop into this * value. * - * @generated from protobuf field: int64 time_lock_delay = 2; + * @generated from protobuf field: int64 time_lock_delay = 2 */ timeLockDelay: bigint; + /** + * + * An indication whether a probing payment succeeded or whether and why it + * failed. FAILURE_REASON_NONE indicates success. + * + * @generated from protobuf field: lnrpc.PaymentFailureReason failure_reason = 5 + */ + failureReason: PaymentFailureReason; } /** * @generated from protobuf message routerrpc.SendToRouteRequest @@ -307,13 +372,13 @@ export interface SendToRouteRequest { /** * The payment hash to use for the HTLC. * - * @generated from protobuf field: bytes payment_hash = 1; + * @generated from protobuf field: bytes payment_hash = 1 */ paymentHash: Uint8Array; /** * Route that should be used to attempt to complete the payment. * - * @generated from protobuf field: lnrpc.Route route = 2; + * @generated from protobuf field: lnrpc.Route route = 2 */ route?: Route; /** @@ -323,9 +388,22 @@ export interface SendToRouteRequest { * failed unless a terminal error is occurred, such as payment timeout, no * routes, incorrect payment details, or insufficient funds. * - * @generated from protobuf field: bool skip_temp_err = 3; + * @generated from protobuf field: bool skip_temp_err = 3 */ skipTempErr: boolean; + /** + * + * An optional field that can be used to pass an arbitrary set of TLV records + * to the first hop peer of this payment. This can be used to pass application + * specific data during the payment attempt. Record types are required to be in + * the custom range >= 65536. When using REST, the values must be encoded as + * base64. + * + * @generated from protobuf field: map first_hop_custom_records = 4 + */ + firstHopCustomRecords: { + [key: string]: Uint8Array; + }; } /** * @generated from protobuf message routerrpc.SendToRouteResponse @@ -334,13 +412,13 @@ export interface SendToRouteResponse { /** * The preimage obtained by making the payment. * - * @generated from protobuf field: bytes preimage = 1; + * @generated from protobuf field: bytes preimage = 1 */ preimage: Uint8Array; /** * The failure message in case the payment failed. * - * @generated from protobuf field: lnrpc.Failure failure = 2; + * @generated from protobuf field: lnrpc.Failure failure = 2 */ failure?: Failure; } @@ -368,7 +446,7 @@ export interface QueryMissionControlResponse { /** * Node pair-level mission control state. * - * @generated from protobuf field: repeated routerrpc.PairHistory pairs = 2; + * @generated from protobuf field: repeated routerrpc.PairHistory pairs = 2 */ pairs: PairHistory[]; } @@ -379,7 +457,7 @@ export interface XImportMissionControlRequest { /** * Node pair-level mission control state to be imported. * - * @generated from protobuf field: repeated routerrpc.PairHistory pairs = 1; + * @generated from protobuf field: repeated routerrpc.PairHistory pairs = 1 */ pairs: PairHistory[]; /** @@ -387,7 +465,7 @@ export interface XImportMissionControlRequest { * override the failure pair is imported before the success pair and both * still clamp existing failure/success amounts. * - * @generated from protobuf field: bool force = 2; + * @generated from protobuf field: bool force = 2 */ force: boolean; } @@ -405,17 +483,17 @@ export interface PairHistory { /** * The source node pubkey of the pair. * - * @generated from protobuf field: bytes node_from = 1; + * @generated from protobuf field: bytes node_from = 1 */ nodeFrom: Uint8Array; /** * The destination node pubkey of the pair. * - * @generated from protobuf field: bytes node_to = 2; + * @generated from protobuf field: bytes node_to = 2 */ nodeTo: Uint8Array; /** - * @generated from protobuf field: routerrpc.PairData history = 7; + * @generated from protobuf field: routerrpc.PairData history = 7 */ history?: PairData; } @@ -426,7 +504,7 @@ export interface PairData { /** * Time of last failure. * - * @generated from protobuf field: int64 fail_time = 1; + * @generated from protobuf field: int64 fail_time = 1 */ failTime: bigint; /** @@ -434,7 +512,7 @@ export interface PairData { * Lowest amount that failed to forward rounded to whole sats. This may be * set to zero if the failure is independent of amount. * - * @generated from protobuf field: int64 fail_amt_sat = 2; + * @generated from protobuf field: int64 fail_amt_sat = 2 */ failAmtSat: bigint; /** @@ -442,25 +520,25 @@ export interface PairData { * Lowest amount that failed to forward in millisats. This may be * set to zero if the failure is independent of amount. * - * @generated from protobuf field: int64 fail_amt_msat = 4; + * @generated from protobuf field: int64 fail_amt_msat = 4 */ failAmtMsat: bigint; /** * Time of last success. * - * @generated from protobuf field: int64 success_time = 5; + * @generated from protobuf field: int64 success_time = 5 */ successTime: bigint; /** * Highest amount that we could successfully forward rounded to whole sats. * - * @generated from protobuf field: int64 success_amt_sat = 6; + * @generated from protobuf field: int64 success_amt_sat = 6 */ successAmtSat: bigint; /** * Highest amount that we could successfully forward in millisats. * - * @generated from protobuf field: int64 success_amt_msat = 7; + * @generated from protobuf field: int64 success_amt_msat = 7 */ successAmtMsat: bigint; } @@ -477,7 +555,7 @@ export interface GetMissionControlConfigResponse { * * Mission control's currently active config. * - * @generated from protobuf field: routerrpc.MissionControlConfig config = 1; + * @generated from protobuf field: routerrpc.MissionControlConfig config = 1 */ config?: MissionControlConfig; } @@ -490,7 +568,7 @@ export interface SetMissionControlConfigRequest { * The config to set for mission control. Note that all values *must* be set, * because the full config will be applied. * - * @generated from protobuf field: routerrpc.MissionControlConfig config = 1; + * @generated from protobuf field: routerrpc.MissionControlConfig config = 1 */ config?: MissionControlConfig; } @@ -503,6 +581,141 @@ export interface SetMissionControlConfigResponse { * @generated from protobuf message routerrpc.MissionControlConfig */ export interface MissionControlConfig { + /** + * + * Deprecated, use AprioriParameters. The amount of time mission control will + * take to restore a penalized node or channel back to 50% success probability, + * expressed in seconds. Setting this value to a higher value will penalize + * failures for longer, making mission control less likely to route through + * nodes and channels that we have previously recorded failures for. + * + * @deprecated + * @generated from protobuf field: uint64 half_life_seconds = 1 [deprecated = true] + */ + halfLifeSeconds: bigint; + /** + * + * Deprecated, use AprioriParameters. The probability of success mission + * control should assign to hop in a route where it has no other information + * available. Higher values will make mission control more willing to try hops + * that we have no information about, lower values will discourage trying these + * hops. + * + * @deprecated + * @generated from protobuf field: float hop_probability = 2 [deprecated = true] + */ + hopProbability: number; + /** + * + * Deprecated, use AprioriParameters. The importance that mission control + * should place on historical results, expressed as a value in [0;1]. Setting + * this value to 1 will ignore all historical payments and just use the hop + * probability to assess the probability of success for each hop. A zero value + * ignores hop probability completely and relies entirely on historical + * results, unless none are available. + * + * @deprecated + * @generated from protobuf field: float weight = 3 [deprecated = true] + */ + weight: number; + /** + * + * The maximum number of payment results that mission control will store. + * + * @generated from protobuf field: uint32 maximum_payment_results = 4 + */ + maximumPaymentResults: number; + /** + * + * The minimum time that must have passed since the previously recorded failure + * before we raise the failure amount. + * + * @generated from protobuf field: uint64 minimum_failure_relax_interval = 5 + */ + minimumFailureRelaxInterval: bigint; + /** + * + * ProbabilityModel defines which probability estimator should be used in + * pathfinding. Note that the bimodal estimator is experimental. + * + * @generated from protobuf field: routerrpc.MissionControlConfig.ProbabilityModel model = 6 + */ + model: MissionControlConfig_ProbabilityModel; + /** + * + * EstimatorConfig is populated dependent on the estimator type. + * + * @generated from protobuf oneof: EstimatorConfig + */ + estimatorConfig: { + oneofKind: "apriori"; + /** + * @generated from protobuf field: routerrpc.AprioriParameters apriori = 7 + */ + apriori: AprioriParameters; + } | { + oneofKind: "bimodal"; + /** + * @generated from protobuf field: routerrpc.BimodalParameters bimodal = 8 + */ + bimodal: BimodalParameters; + } | { + oneofKind: undefined; + }; +} +/** + * @generated from protobuf enum routerrpc.MissionControlConfig.ProbabilityModel + */ +export enum MissionControlConfig_ProbabilityModel { + /** + * @generated from protobuf enum value: APRIORI = 0; + */ + APRIORI = 0, + /** + * @generated from protobuf enum value: BIMODAL = 1; + */ + BIMODAL = 1 +} +/** + * @generated from protobuf message routerrpc.BimodalParameters + */ +export interface BimodalParameters { + /** + * + * NodeWeight defines how strongly other previous forwardings on channels of a + * router should be taken into account when computing a channel's probability + * to route. The allowed values are in the range [0, 1], where a value of 0 + * means that only direct information about a channel is taken into account. + * + * @generated from protobuf field: double node_weight = 1 + */ + nodeWeight: number; + /** + * + * ScaleMsat describes the scale over which channels statistically have some + * liquidity left. The value determines how quickly the bimodal distribution + * drops off from the edges of a channel. A larger value (compared to typical + * channel capacities) means that the drop off is slow and that channel + * balances are distributed more uniformly. A small value leads to the + * assumption of very unbalanced channels. + * + * @generated from protobuf field: uint64 scale_msat = 2 + */ + scaleMsat: bigint; + /** + * + * DecayTime describes the information decay of knowledge about previous + * successes and failures in channels. The smaller the decay time, the quicker + * we forget about past forwardings. + * + * @generated from protobuf field: uint64 decay_time = 3 + */ + decayTime: bigint; +} +/** + * @generated from protobuf message routerrpc.AprioriParameters + */ +export interface AprioriParameters { /** * * The amount of time mission control will take to restore a penalized node @@ -511,7 +724,7 @@ export interface MissionControlConfig { * mission control less likely to route through nodes and channels that we * have previously recorded failures for. * - * @generated from protobuf field: uint64 half_life_seconds = 1; + * @generated from protobuf field: uint64 half_life_seconds = 1 */ halfLifeSeconds: bigint; /** @@ -521,7 +734,7 @@ export interface MissionControlConfig { * control more willing to try hops that we have no information about, lower * values will discourage trying these hops. * - * @generated from protobuf field: float hop_probability = 2; + * @generated from protobuf field: double hop_probability = 2 */ hopProbability: number; /** @@ -533,24 +746,19 @@ export interface MissionControlConfig { * completely and relies entirely on historical results, unless none are * available. * - * @generated from protobuf field: float weight = 3; + * @generated from protobuf field: double weight = 3 */ weight: number; /** * - * The maximum number of payment results that mission control will store. + * The fraction of a channel's capacity that we consider to have liquidity. For + * amounts that come close to or exceed the fraction, an additional penalty is + * applied. A value of 1.0 disables the capacity factor. Allowed values are in + * [0.75, 1.0]. * - * @generated from protobuf field: uint32 maximum_payment_results = 4; + * @generated from protobuf field: double capacity_fraction = 4 */ - maximumPaymentResults: number; - /** - * - * The minimum time that must have passed since the previously recorded failure - * before we raise the failure amount. - * - * @generated from protobuf field: uint64 minimum_failure_relax_interval = 5; - */ - minimumFailureRelaxInterval: bigint; + capacityFraction: number; } /** * @generated from protobuf message routerrpc.QueryProbabilityRequest @@ -559,19 +767,19 @@ export interface QueryProbabilityRequest { /** * The source node pubkey of the pair. * - * @generated from protobuf field: bytes from_node = 1; + * @generated from protobuf field: bytes from_node = 1 */ fromNode: Uint8Array; /** * The destination node pubkey of the pair. * - * @generated from protobuf field: bytes to_node = 2; + * @generated from protobuf field: bytes to_node = 2 */ toNode: Uint8Array; /** * The amount for which to calculate a probability. * - * @generated from protobuf field: int64 amt_msat = 3; + * @generated from protobuf field: int64 amt_msat = 3 */ amtMsat: bigint; } @@ -582,13 +790,13 @@ export interface QueryProbabilityResponse { /** * The success probability for the requested pair. * - * @generated from protobuf field: double probability = 1; + * @generated from protobuf field: double probability = 1 */ probability: number; /** * The historical data for the requested pair. * - * @generated from protobuf field: routerrpc.PairData history = 2; + * @generated from protobuf field: routerrpc.PairData history = 2 */ history?: PairData; } @@ -601,7 +809,7 @@ export interface BuildRouteRequest { * The amount to send expressed in msat. If set to zero, the minimum routable * amount is used. * - * @generated from protobuf field: int64 amt_msat = 1; + * @generated from protobuf field: int64 amt_msat = 1 */ amtMsat: bigint; /** @@ -609,7 +817,7 @@ export interface BuildRouteRequest { * CLTV delta from the current height that should be used for the timelock * of the final hop * - * @generated from protobuf field: int32 final_cltv_delta = 2; + * @generated from protobuf field: int32 final_cltv_delta = 2 */ finalCltvDelta: number; /** @@ -617,7 +825,7 @@ export interface BuildRouteRequest { * The channel id of the channel that must be taken to the first hop. If zero, * any channel may be used. * - * @generated from protobuf field: uint64 outgoing_chan_id = 3 [jstype = JS_STRING]; + * @generated from protobuf field: uint64 outgoing_chan_id = 3 [jstype = JS_STRING] */ outgoingChanId: string; /** @@ -625,15 +833,30 @@ export interface BuildRouteRequest { * A list of hops that defines the route. This does not include the source hop * pubkey. * - * @generated from protobuf field: repeated bytes hop_pubkeys = 4; + * @generated from protobuf field: repeated bytes hop_pubkeys = 4 */ hopPubkeys: Uint8Array[]; /** - * An optional payment addr to be included within the last hop of the route. * - * @generated from protobuf field: bytes payment_addr = 5; + * An optional payment addr to be included within the last hop of the route. + * This is also called payment secret in specifications (e.g. BOLT 11). + * + * @generated from protobuf field: bytes payment_addr = 5 */ paymentAddr: Uint8Array; + /** + * + * An optional field that can be used to pass an arbitrary set of TLV records + * to the first hop peer of this payment. This can be used to pass application + * specific data during the payment attempt. Record types are required to be in + * the custom range >= 65536. When using REST, the values must be encoded as + * base64. + * + * @generated from protobuf field: map first_hop_custom_records = 6 + */ + firstHopCustomRecords: { + [key: string]: Uint8Array; + }; } /** * @generated from protobuf message routerrpc.BuildRouteResponse @@ -643,7 +866,7 @@ export interface BuildRouteResponse { * * Fully specified route that can be used to execute the payment. * - * @generated from protobuf field: lnrpc.Route route = 1; + * @generated from protobuf field: lnrpc.Route route = 1 */ route?: Route; } @@ -669,7 +892,7 @@ export interface HtlcEvent { * The short channel id that the incoming htlc arrived at our node on. This * value is zero for sends. * - * @generated from protobuf field: uint64 incoming_channel_id = 1; + * @generated from protobuf field: uint64 incoming_channel_id = 1 */ incomingChannelId: bigint; /** @@ -677,7 +900,7 @@ export interface HtlcEvent { * The short channel id that the outgoing htlc left our node on. This value * is zero for receives. * - * @generated from protobuf field: uint64 outgoing_channel_id = 2; + * @generated from protobuf field: uint64 outgoing_channel_id = 2 */ outgoingChannelId: bigint; /** @@ -685,7 +908,7 @@ export interface HtlcEvent { * Incoming id is the index of the incoming htlc in the incoming channel. * This value is zero for sends. * - * @generated from protobuf field: uint64 incoming_htlc_id = 3; + * @generated from protobuf field: uint64 incoming_htlc_id = 3 */ incomingHtlcId: bigint; /** @@ -693,14 +916,14 @@ export interface HtlcEvent { * Outgoing id is the index of the outgoing htlc in the outgoing channel. * This value is zero for receives. * - * @generated from protobuf field: uint64 outgoing_htlc_id = 4; + * @generated from protobuf field: uint64 outgoing_htlc_id = 4 */ outgoingHtlcId: bigint; /** * * The time in unix nanoseconds that the event occurred. * - * @generated from protobuf field: uint64 timestamp_ns = 5; + * @generated from protobuf field: uint64 timestamp_ns = 5 */ timestampNs: bigint; /** @@ -708,7 +931,7 @@ export interface HtlcEvent { * The event type indicates whether the htlc was part of a send, receive or * forward. * - * @generated from protobuf field: routerrpc.HtlcEvent.EventType event_type = 6; + * @generated from protobuf field: routerrpc.HtlcEvent.EventType event_type = 6 */ eventType: HtlcEvent_EventType; /** @@ -717,37 +940,37 @@ export interface HtlcEvent { event: { oneofKind: "forwardEvent"; /** - * @generated from protobuf field: routerrpc.ForwardEvent forward_event = 7; + * @generated from protobuf field: routerrpc.ForwardEvent forward_event = 7 */ forwardEvent: ForwardEvent; } | { oneofKind: "forwardFailEvent"; /** - * @generated from protobuf field: routerrpc.ForwardFailEvent forward_fail_event = 8; + * @generated from protobuf field: routerrpc.ForwardFailEvent forward_fail_event = 8 */ forwardFailEvent: ForwardFailEvent; } | { oneofKind: "settleEvent"; /** - * @generated from protobuf field: routerrpc.SettleEvent settle_event = 9; + * @generated from protobuf field: routerrpc.SettleEvent settle_event = 9 */ settleEvent: SettleEvent; } | { oneofKind: "linkFailEvent"; /** - * @generated from protobuf field: routerrpc.LinkFailEvent link_fail_event = 10; + * @generated from protobuf field: routerrpc.LinkFailEvent link_fail_event = 10 */ linkFailEvent: LinkFailEvent; } | { oneofKind: "subscribedEvent"; /** - * @generated from protobuf field: routerrpc.SubscribedEvent subscribed_event = 11; + * @generated from protobuf field: routerrpc.SubscribedEvent subscribed_event = 11 */ subscribedEvent: SubscribedEvent; } | { oneofKind: "finalHtlcEvent"; /** - * @generated from protobuf field: routerrpc.FinalHtlcEvent final_htlc_event = 12; + * @generated from protobuf field: routerrpc.FinalHtlcEvent final_htlc_event = 12 */ finalHtlcEvent: FinalHtlcEvent; } | { @@ -782,25 +1005,25 @@ export interface HtlcInfo { /** * The timelock on the incoming htlc. * - * @generated from protobuf field: uint32 incoming_timelock = 1; + * @generated from protobuf field: uint32 incoming_timelock = 1 */ incomingTimelock: number; /** * The timelock on the outgoing htlc. * - * @generated from protobuf field: uint32 outgoing_timelock = 2; + * @generated from protobuf field: uint32 outgoing_timelock = 2 */ outgoingTimelock: number; /** * The amount of the incoming htlc. * - * @generated from protobuf field: uint64 incoming_amt_msat = 3; + * @generated from protobuf field: uint64 incoming_amt_msat = 3 */ incomingAmtMsat: bigint; /** * The amount of the outgoing htlc. * - * @generated from protobuf field: uint64 outgoing_amt_msat = 4; + * @generated from protobuf field: uint64 outgoing_amt_msat = 4 */ outgoingAmtMsat: bigint; } @@ -811,7 +1034,7 @@ export interface ForwardEvent { /** * Info contains details about the htlc that was forwarded. * - * @generated from protobuf field: routerrpc.HtlcInfo info = 1; + * @generated from protobuf field: routerrpc.HtlcInfo info = 1 */ info?: HtlcInfo; } @@ -827,7 +1050,7 @@ export interface SettleEvent { /** * The revealed preimage. * - * @generated from protobuf field: bytes preimage = 1; + * @generated from protobuf field: bytes preimage = 1 */ preimage: Uint8Array; } @@ -836,11 +1059,11 @@ export interface SettleEvent { */ export interface FinalHtlcEvent { /** - * @generated from protobuf field: bool settled = 1; + * @generated from protobuf field: bool settled = 1 */ settled: boolean; /** - * @generated from protobuf field: bool offchain = 2; + * @generated from protobuf field: bool offchain = 2 */ offchain: boolean; } @@ -856,13 +1079,13 @@ export interface LinkFailEvent { /** * Info contains details about the htlc that we failed. * - * @generated from protobuf field: routerrpc.HtlcInfo info = 1; + * @generated from protobuf field: routerrpc.HtlcInfo info = 1 */ info?: HtlcInfo; /** * FailureCode is the BOLT error code for the failure. * - * @generated from protobuf field: lnrpc.Failure.FailureCode wire_failure = 2; + * @generated from protobuf field: lnrpc.Failure.FailureCode wire_failure = 2 */ wireFailure: Failure_FailureCode; /** @@ -871,13 +1094,13 @@ export interface LinkFailEvent { * failure. This detail enriches the information provided by the wire message * and may be 'no detail' if the wire message requires no additional metadata. * - * @generated from protobuf field: routerrpc.FailureDetail failure_detail = 3; + * @generated from protobuf field: routerrpc.FailureDetail failure_detail = 3 */ failureDetail: FailureDetail; /** * A string representation of the link failure. * - * @generated from protobuf field: string failure_string = 4; + * @generated from protobuf field: string failure_string = 4 */ failureString: string; } @@ -888,21 +1111,21 @@ export interface PaymentStatus { /** * Current state the payment is in. * - * @generated from protobuf field: routerrpc.PaymentState state = 1; + * @generated from protobuf field: routerrpc.PaymentState state = 1 */ state: PaymentState; /** * * The pre-image of the payment when state is SUCCEEDED. * - * @generated from protobuf field: bytes preimage = 2; + * @generated from protobuf field: bytes preimage = 2 */ preimage: Uint8Array; /** * * The HTLCs made in attempt to settle the payment [EXPERIMENTAL]. * - * @generated from protobuf field: repeated lnrpc.HTLCAttempt htlcs = 4; + * @generated from protobuf field: repeated lnrpc.HTLCAttempt htlcs = 4 */ htlcs: HTLCAttempt[]; } @@ -913,13 +1136,13 @@ export interface CircuitKey { /** * / The id of the channel that the is part of this circuit. * - * @generated from protobuf field: uint64 chan_id = 1; + * @generated from protobuf field: uint64 chan_id = 1 */ chanId: bigint; /** * / The index of the incoming htlc in the incoming channel. * - * @generated from protobuf field: uint64 htlc_id = 2; + * @generated from protobuf field: uint64 htlc_id = 2 */ htlcId: bigint; } @@ -932,19 +1155,19 @@ export interface ForwardHtlcInterceptRequest { * The key of this forwarded htlc. It defines the incoming channel id and * the index in this channel. * - * @generated from protobuf field: routerrpc.CircuitKey incoming_circuit_key = 1; + * @generated from protobuf field: routerrpc.CircuitKey incoming_circuit_key = 1 */ incomingCircuitKey?: CircuitKey; /** * The incoming htlc amount. * - * @generated from protobuf field: uint64 incoming_amount_msat = 5; + * @generated from protobuf field: uint64 incoming_amount_msat = 5 */ incomingAmountMsat: bigint; /** * The incoming htlc expiry. * - * @generated from protobuf field: uint32 incoming_expiry = 6; + * @generated from protobuf field: uint32 incoming_expiry = 6 */ incomingExpiry: number; /** @@ -952,7 +1175,7 @@ export interface ForwardHtlcInterceptRequest { * The htlc payment hash. This value is not guaranteed to be unique per * request. * - * @generated from protobuf field: bytes payment_hash = 2; + * @generated from protobuf field: bytes payment_hash = 2 */ paymentHash: Uint8Array; /** @@ -961,25 +1184,25 @@ export interface ForwardHtlcInterceptRequest { * packet will be forwarded eventually. A different channel to the same peer * may be selected as well. * - * @generated from protobuf field: uint64 outgoing_requested_chan_id = 7; + * @generated from protobuf field: uint64 outgoing_requested_chan_id = 7 */ outgoingRequestedChanId: bigint; /** * The outgoing htlc amount. * - * @generated from protobuf field: uint64 outgoing_amount_msat = 3; + * @generated from protobuf field: uint64 outgoing_amount_msat = 3 */ outgoingAmountMsat: bigint; /** * The outgoing htlc expiry. * - * @generated from protobuf field: uint32 outgoing_expiry = 4; + * @generated from protobuf field: uint32 outgoing_expiry = 4 */ outgoingExpiry: number; /** * Any custom records that were present in the payload. * - * @generated from protobuf field: map custom_records = 8; + * @generated from protobuf field: map custom_records = 8 */ customRecords: { [key: string]: Uint8Array; @@ -987,22 +1210,32 @@ export interface ForwardHtlcInterceptRequest { /** * The onion blob for the next hop * - * @generated from protobuf field: bytes onion_blob = 9; + * @generated from protobuf field: bytes onion_blob = 9 */ onionBlob: Uint8Array; /** * The block height at which this htlc will be auto-failed to prevent the * channel from force-closing. * - * @generated from protobuf field: int32 auto_fail_height = 10; + * @generated from protobuf field: int32 auto_fail_height = 10 */ autoFailHeight: number; + /** + * The custom records of the peer's incoming p2p wire message. + * + * @generated from protobuf field: map in_wire_custom_records = 11 + */ + inWireCustomRecords: { + [key: string]: Uint8Array; + }; } /** * * * ForwardHtlcInterceptResponse enables the caller to resolve a previously hold * forward. The caller can choose either to: * - `Resume`: Execute the default behavior (usually forward). + * - `ResumeModified`: Execute the default behavior (usually forward) with HTLC + * field modifications. * - `Reject`: Fail the htlc backwards. * - `Settle`: Settle this htlc with a given preimage. * @@ -1014,19 +1247,19 @@ export interface ForwardHtlcInterceptResponse { * The key of this forwarded htlc. It defines the incoming channel id and * the index in this channel. * - * @generated from protobuf field: routerrpc.CircuitKey incoming_circuit_key = 1; + * @generated from protobuf field: routerrpc.CircuitKey incoming_circuit_key = 1 */ incomingCircuitKey?: CircuitKey; /** * The resolve action for this intercepted htlc. * - * @generated from protobuf field: routerrpc.ResolveHoldForwardAction action = 2; + * @generated from protobuf field: routerrpc.ResolveHoldForwardAction action = 2 */ action: ResolveHoldForwardAction; /** * The preimage in case the resolve action is Settle. * - * @generated from protobuf field: bytes preimage = 3; + * @generated from protobuf field: bytes preimage = 3 */ preimage: Uint8Array; /** @@ -1035,7 +1268,7 @@ export interface ForwardHtlcInterceptResponse { * If failure_message is specified, the failure_code field must be set * to zero. * - * @generated from protobuf field: bytes failure_message = 4; + * @generated from protobuf field: bytes failure_message = 4 */ failureMessage: Uint8Array; /** @@ -1047,20 +1280,49 @@ export interface ForwardHtlcInterceptResponse { * For backwards-compatibility reasons, TEMPORARY_CHANNEL_FAILURE is the * default value for this field. * - * @generated from protobuf field: lnrpc.Failure.FailureCode failure_code = 5; + * @generated from protobuf field: lnrpc.Failure.FailureCode failure_code = 5 */ failureCode: Failure_FailureCode; + /** + * The amount that was set on the p2p wire message of the incoming HTLC. + * This field is ignored if the action is not RESUME_MODIFIED or the amount + * is zero. + * + * @generated from protobuf field: uint64 in_amount_msat = 6 + */ + inAmountMsat: bigint; + /** + * The amount to set on the p2p wire message of the resumed HTLC. This field + * is ignored if the action is not RESUME_MODIFIED or the amount is zero. + * + * @generated from protobuf field: uint64 out_amount_msat = 7 + */ + outAmountMsat: bigint; + /** + * Any custom records that should be set on the p2p wire message message of + * the resumed HTLC. This field is ignored if the action is not + * RESUME_MODIFIED. + * + * This map will merge with the existing set of custom records (if any), + * replacing any conflicting types. Note that there currently is no support + * for deleting existing custom records (they can only be replaced). + * + * @generated from protobuf field: map out_wire_custom_records = 8 + */ + outWireCustomRecords: { + [key: string]: Uint8Array; + }; } /** * @generated from protobuf message routerrpc.UpdateChanStatusRequest */ export interface UpdateChanStatusRequest { /** - * @generated from protobuf field: lnrpc.ChannelPoint chan_point = 1; + * @generated from protobuf field: lnrpc.ChannelPoint chan_point = 1 */ chanPoint?: ChannelPoint; /** - * @generated from protobuf field: routerrpc.ChanStatusAction action = 2; + * @generated from protobuf field: routerrpc.ChanStatusAction action = 2 */ action: ChanStatusAction; } @@ -1069,6 +1331,42 @@ export interface UpdateChanStatusRequest { */ export interface UpdateChanStatusResponse { } +/** + * @generated from protobuf message routerrpc.AddAliasesRequest + */ +export interface AddAliasesRequest { + /** + * @generated from protobuf field: repeated lnrpc.AliasMap alias_maps = 1 + */ + aliasMaps: AliasMap[]; +} +/** + * @generated from protobuf message routerrpc.AddAliasesResponse + */ +export interface AddAliasesResponse { + /** + * @generated from protobuf field: repeated lnrpc.AliasMap alias_maps = 1 + */ + aliasMaps: AliasMap[]; +} +/** + * @generated from protobuf message routerrpc.DeleteAliasesRequest + */ +export interface DeleteAliasesRequest { + /** + * @generated from protobuf field: repeated lnrpc.AliasMap alias_maps = 1 + */ + aliasMaps: AliasMap[]; +} +/** + * @generated from protobuf message routerrpc.DeleteAliasesResponse + */ +export interface DeleteAliasesResponse { + /** + * @generated from protobuf field: repeated lnrpc.AliasMap alias_maps = 1 + */ + aliasMaps: AliasMap[]; +} /** * @generated from protobuf enum routerrpc.FailureDetail */ @@ -1227,17 +1525,31 @@ export enum PaymentState { */ export enum ResolveHoldForwardAction { /** + * SETTLE is an action that is used to settle an HTLC instead of forwarding + * it. + * * @generated from protobuf enum value: SETTLE = 0; */ SETTLE = 0, /** + * FAIL is an action that is used to fail an HTLC backwards. + * * @generated from protobuf enum value: FAIL = 1; */ FAIL = 1, /** + * RESUME is an action that is used to resume a forward HTLC. + * * @generated from protobuf enum value: RESUME = 2; */ - RESUME = 2 + RESUME = 2, + /** + * RESUME_MODIFIED is an action that is used to resume a hold forward HTLC + * with modifications specified during interception. + * + * @generated from protobuf enum value: RESUME_MODIFIED = 3; + */ + RESUME_MODIFIED = 3 } /** * @generated from protobuf enum routerrpc.ChanStatusAction @@ -1262,32 +1574,58 @@ class SendPaymentRequest$Type extends MessageType { super("routerrpc.SendPaymentRequest", [ { no: 1, name: "dest", kind: "scalar", T: 12 /*ScalarType.BYTES*/ }, { no: 2, name: "amt", kind: "scalar", T: 3 /*ScalarType.INT64*/, L: 0 /*LongType.BIGINT*/ }, - { no: 12, name: "amt_msat", kind: "scalar", T: 3 /*ScalarType.INT64*/, L: 0 /*LongType.BIGINT*/ }, { no: 3, name: "payment_hash", kind: "scalar", T: 12 /*ScalarType.BYTES*/ }, { no: 4, name: "final_cltv_delta", kind: "scalar", T: 5 /*ScalarType.INT32*/ }, - { no: 20, name: "payment_addr", kind: "scalar", T: 12 /*ScalarType.BYTES*/ }, { no: 5, name: "payment_request", kind: "scalar", T: 9 /*ScalarType.STRING*/ }, { no: 6, name: "timeout_seconds", kind: "scalar", T: 5 /*ScalarType.INT32*/ }, { no: 7, name: "fee_limit_sat", kind: "scalar", T: 3 /*ScalarType.INT64*/, L: 0 /*LongType.BIGINT*/ }, - { no: 13, name: "fee_limit_msat", kind: "scalar", T: 3 /*ScalarType.INT64*/, L: 0 /*LongType.BIGINT*/ }, { no: 8, name: "outgoing_chan_id", kind: "scalar", T: 4 /*ScalarType.UINT64*/ }, - { no: 19, name: "outgoing_chan_ids", kind: "scalar", repeat: 1 /*RepeatType.PACKED*/, T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ }, - { no: 14, name: "last_hop_pubkey", kind: "scalar", T: 12 /*ScalarType.BYTES*/ }, { no: 9, name: "cltv_limit", kind: "scalar", T: 5 /*ScalarType.INT32*/ }, - { no: 10, name: "route_hints", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => RouteHint }, + { no: 10, name: "route_hints", kind: "message", repeat: 2 /*RepeatType.UNPACKED*/, T: () => RouteHint }, { no: 11, name: "dest_custom_records", kind: "map", K: 4 /*ScalarType.UINT64*/, V: { kind: "scalar", T: 12 /*ScalarType.BYTES*/ } }, + { no: 12, name: "amt_msat", kind: "scalar", T: 3 /*ScalarType.INT64*/, L: 0 /*LongType.BIGINT*/ }, + { no: 13, name: "fee_limit_msat", kind: "scalar", T: 3 /*ScalarType.INT64*/, L: 0 /*LongType.BIGINT*/ }, + { no: 14, name: "last_hop_pubkey", kind: "scalar", T: 12 /*ScalarType.BYTES*/ }, { no: 15, name: "allow_self_payment", kind: "scalar", T: 8 /*ScalarType.BOOL*/ }, { no: 16, name: "dest_features", kind: "enum", repeat: 1 /*RepeatType.PACKED*/, T: () => ["lnrpc.FeatureBit", FeatureBit] }, { no: 17, name: "max_parts", kind: "scalar", T: 13 /*ScalarType.UINT32*/ }, { no: 18, name: "no_inflight_updates", kind: "scalar", T: 8 /*ScalarType.BOOL*/ }, + { no: 19, name: "outgoing_chan_ids", kind: "scalar", repeat: 1 /*RepeatType.PACKED*/, T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ }, + { no: 20, name: "payment_addr", kind: "scalar", T: 12 /*ScalarType.BYTES*/ }, { no: 21, name: "max_shard_size_msat", kind: "scalar", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ }, { no: 22, name: "amp", kind: "scalar", T: 8 /*ScalarType.BOOL*/ }, - { no: 23, name: "time_pref", kind: "scalar", T: 1 /*ScalarType.DOUBLE*/ } + { no: 23, name: "time_pref", kind: "scalar", T: 1 /*ScalarType.DOUBLE*/ }, + { no: 24, name: "cancelable", kind: "scalar", T: 8 /*ScalarType.BOOL*/ }, + { no: 25, name: "first_hop_custom_records", kind: "map", K: 4 /*ScalarType.UINT64*/, V: { kind: "scalar", T: 12 /*ScalarType.BYTES*/ } } ]); } create(value?: PartialMessage): SendPaymentRequest { - const message = { dest: new Uint8Array(0), amt: 0n, amtMsat: 0n, paymentHash: new Uint8Array(0), finalCltvDelta: 0, paymentAddr: new Uint8Array(0), paymentRequest: "", timeoutSeconds: 0, feeLimitSat: 0n, feeLimitMsat: 0n, outgoingChanId: "0", outgoingChanIds: [], lastHopPubkey: new Uint8Array(0), cltvLimit: 0, routeHints: [], destCustomRecords: {}, allowSelfPayment: false, destFeatures: [], maxParts: 0, noInflightUpdates: false, maxShardSizeMsat: 0n, amp: false, timePref: 0 }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.dest = new Uint8Array(0); + message.amt = 0n; + message.paymentHash = new Uint8Array(0); + message.finalCltvDelta = 0; + message.paymentRequest = ""; + message.timeoutSeconds = 0; + message.feeLimitSat = 0n; + message.outgoingChanId = "0"; + message.cltvLimit = 0; + message.routeHints = []; + message.destCustomRecords = {}; + message.amtMsat = 0n; + message.feeLimitMsat = 0n; + message.lastHopPubkey = new Uint8Array(0); + message.allowSelfPayment = false; + message.destFeatures = []; + message.maxParts = 0; + message.noInflightUpdates = false; + message.outgoingChanIds = []; + message.paymentAddr = new Uint8Array(0); + message.maxShardSizeMsat = 0n; + message.amp = false; + message.timePref = 0; + message.cancelable = false; + message.firstHopCustomRecords = {}; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -1303,18 +1641,12 @@ class SendPaymentRequest$Type extends MessageType { case /* int64 amt */ 2: message.amt = reader.int64().toBigInt(); break; - case /* int64 amt_msat */ 12: - message.amtMsat = reader.int64().toBigInt(); - break; case /* bytes payment_hash */ 3: message.paymentHash = reader.bytes(); break; case /* int32 final_cltv_delta */ 4: message.finalCltvDelta = reader.int32(); break; - case /* bytes payment_addr */ 20: - message.paymentAddr = reader.bytes(); - break; case /* string payment_request */ 5: message.paymentRequest = reader.string(); break; @@ -1324,22 +1656,9 @@ class SendPaymentRequest$Type extends MessageType { case /* int64 fee_limit_sat */ 7: message.feeLimitSat = reader.int64().toBigInt(); break; - case /* int64 fee_limit_msat */ 13: - message.feeLimitMsat = reader.int64().toBigInt(); - break; - case /* uint64 outgoing_chan_id = 8 [deprecated = true, jstype = JS_STRING];*/ 8: + case /* uint64 outgoing_chan_id = 8 [jstype = JS_STRING, deprecated = true] */ 8: message.outgoingChanId = reader.uint64().toString(); break; - case /* repeated uint64 outgoing_chan_ids */ 19: - if (wireType === WireType.LengthDelimited) - for (let e = reader.int32() + reader.pos; reader.pos < e;) - message.outgoingChanIds.push(reader.uint64().toBigInt()); - else - message.outgoingChanIds.push(reader.uint64().toBigInt()); - break; - case /* bytes last_hop_pubkey */ 14: - message.lastHopPubkey = reader.bytes(); - break; case /* int32 cltv_limit */ 9: message.cltvLimit = reader.int32(); break; @@ -1349,6 +1668,15 @@ class SendPaymentRequest$Type extends MessageType { case /* map dest_custom_records */ 11: this.binaryReadMap11(message.destCustomRecords, reader, options); break; + case /* int64 amt_msat */ 12: + message.amtMsat = reader.int64().toBigInt(); + break; + case /* int64 fee_limit_msat */ 13: + message.feeLimitMsat = reader.int64().toBigInt(); + break; + case /* bytes last_hop_pubkey */ 14: + message.lastHopPubkey = reader.bytes(); + break; case /* bool allow_self_payment */ 15: message.allowSelfPayment = reader.bool(); break; @@ -1365,6 +1693,16 @@ class SendPaymentRequest$Type extends MessageType { case /* bool no_inflight_updates */ 18: message.noInflightUpdates = reader.bool(); break; + case /* repeated uint64 outgoing_chan_ids */ 19: + if (wireType === WireType.LengthDelimited) + for (let e = reader.int32() + reader.pos; reader.pos < e;) + message.outgoingChanIds.push(reader.uint64().toBigInt()); + else + message.outgoingChanIds.push(reader.uint64().toBigInt()); + break; + case /* bytes payment_addr */ 20: + message.paymentAddr = reader.bytes(); + break; case /* uint64 max_shard_size_msat */ 21: message.maxShardSizeMsat = reader.uint64().toBigInt(); break; @@ -1374,6 +1712,12 @@ class SendPaymentRequest$Type extends MessageType { case /* double time_pref */ 23: message.timePref = reader.double(); break; + case /* bool cancelable */ 24: + message.cancelable = reader.bool(); + break; + case /* map first_hop_custom_records */ 25: + this.binaryReadMap25(message.firstHopCustomRecords, reader, options); + break; default: let u = options.readUnknownField; if (u === "throw") @@ -1396,7 +1740,23 @@ class SendPaymentRequest$Type extends MessageType { case 2: val = reader.bytes(); break; - default: throw new globalThis.Error("unknown map entry field for field routerrpc.SendPaymentRequest.dest_custom_records"); + default: throw new globalThis.Error("unknown map entry field for routerrpc.SendPaymentRequest.dest_custom_records"); + } + } + map[key ?? "0"] = val ?? new Uint8Array(0); + } + private binaryReadMap25(map: SendPaymentRequest["firstHopCustomRecords"], reader: IBinaryReader, options: BinaryReadOptions): void { + let len = reader.uint32(), end = reader.pos + len, key: keyof SendPaymentRequest["firstHopCustomRecords"] | undefined, val: SendPaymentRequest["firstHopCustomRecords"][any] | undefined; + while (reader.pos < end) { + let [fieldNo, wireType] = reader.tag(); + switch (fieldNo) { + case 1: + key = reader.uint64().toString(); + break; + case 2: + val = reader.bytes(); + break; + default: throw new globalThis.Error("unknown map entry field for routerrpc.SendPaymentRequest.first_hop_custom_records"); } } map[key ?? "0"] = val ?? new Uint8Array(0); @@ -1408,18 +1768,12 @@ class SendPaymentRequest$Type extends MessageType { /* int64 amt = 2; */ if (message.amt !== 0n) writer.tag(2, WireType.Varint).int64(message.amt); - /* int64 amt_msat = 12; */ - if (message.amtMsat !== 0n) - writer.tag(12, WireType.Varint).int64(message.amtMsat); /* bytes payment_hash = 3; */ if (message.paymentHash.length) writer.tag(3, WireType.LengthDelimited).bytes(message.paymentHash); /* int32 final_cltv_delta = 4; */ if (message.finalCltvDelta !== 0) writer.tag(4, WireType.Varint).int32(message.finalCltvDelta); - /* bytes payment_addr = 20; */ - if (message.paymentAddr.length) - writer.tag(20, WireType.LengthDelimited).bytes(message.paymentAddr); /* string payment_request = 5; */ if (message.paymentRequest !== "") writer.tag(5, WireType.LengthDelimited).string(message.paymentRequest); @@ -1429,22 +1783,9 @@ class SendPaymentRequest$Type extends MessageType { /* int64 fee_limit_sat = 7; */ if (message.feeLimitSat !== 0n) writer.tag(7, WireType.Varint).int64(message.feeLimitSat); - /* int64 fee_limit_msat = 13; */ - if (message.feeLimitMsat !== 0n) - writer.tag(13, WireType.Varint).int64(message.feeLimitMsat); - /* uint64 outgoing_chan_id = 8 [deprecated = true, jstype = JS_STRING]; */ + /* uint64 outgoing_chan_id = 8 [jstype = JS_STRING, deprecated = true]; */ if (message.outgoingChanId !== "0") writer.tag(8, WireType.Varint).uint64(message.outgoingChanId); - /* repeated uint64 outgoing_chan_ids = 19; */ - if (message.outgoingChanIds.length) { - writer.tag(19, WireType.LengthDelimited).fork(); - for (let i = 0; i < message.outgoingChanIds.length; i++) - writer.uint64(message.outgoingChanIds[i]); - writer.join(); - } - /* bytes last_hop_pubkey = 14; */ - if (message.lastHopPubkey.length) - writer.tag(14, WireType.LengthDelimited).bytes(message.lastHopPubkey); /* int32 cltv_limit = 9; */ if (message.cltvLimit !== 0) writer.tag(9, WireType.Varint).int32(message.cltvLimit); @@ -1452,8 +1793,17 @@ class SendPaymentRequest$Type extends MessageType { for (let i = 0; i < message.routeHints.length; i++) RouteHint.internalBinaryWrite(message.routeHints[i], writer.tag(10, WireType.LengthDelimited).fork(), options).join(); /* map dest_custom_records = 11; */ - for (let k of Object.keys(message.destCustomRecords)) + for (let k of globalThis.Object.keys(message.destCustomRecords)) writer.tag(11, WireType.LengthDelimited).fork().tag(1, WireType.Varint).uint64(k).tag(2, WireType.LengthDelimited).bytes(message.destCustomRecords[k]).join(); + /* int64 amt_msat = 12; */ + if (message.amtMsat !== 0n) + writer.tag(12, WireType.Varint).int64(message.amtMsat); + /* int64 fee_limit_msat = 13; */ + if (message.feeLimitMsat !== 0n) + writer.tag(13, WireType.Varint).int64(message.feeLimitMsat); + /* bytes last_hop_pubkey = 14; */ + if (message.lastHopPubkey.length) + writer.tag(14, WireType.LengthDelimited).bytes(message.lastHopPubkey); /* bool allow_self_payment = 15; */ if (message.allowSelfPayment !== false) writer.tag(15, WireType.Varint).bool(message.allowSelfPayment); @@ -1470,6 +1820,16 @@ class SendPaymentRequest$Type extends MessageType { /* bool no_inflight_updates = 18; */ if (message.noInflightUpdates !== false) writer.tag(18, WireType.Varint).bool(message.noInflightUpdates); + /* repeated uint64 outgoing_chan_ids = 19; */ + if (message.outgoingChanIds.length) { + writer.tag(19, WireType.LengthDelimited).fork(); + for (let i = 0; i < message.outgoingChanIds.length; i++) + writer.uint64(message.outgoingChanIds[i]); + writer.join(); + } + /* bytes payment_addr = 20; */ + if (message.paymentAddr.length) + writer.tag(20, WireType.LengthDelimited).bytes(message.paymentAddr); /* uint64 max_shard_size_msat = 21; */ if (message.maxShardSizeMsat !== 0n) writer.tag(21, WireType.Varint).uint64(message.maxShardSizeMsat); @@ -1479,6 +1839,12 @@ class SendPaymentRequest$Type extends MessageType { /* double time_pref = 23; */ if (message.timePref !== 0) writer.tag(23, WireType.Bit64).double(message.timePref); + /* bool cancelable = 24; */ + if (message.cancelable !== false) + writer.tag(24, WireType.Varint).bool(message.cancelable); + /* map first_hop_custom_records = 25; */ + for (let k of globalThis.Object.keys(message.firstHopCustomRecords)) + writer.tag(25, WireType.LengthDelimited).fork().tag(1, WireType.Varint).uint64(k).tag(2, WireType.LengthDelimited).bytes(message.firstHopCustomRecords[k]).join(); let u = options.writeUnknownFields; if (u !== false) (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer); @@ -1498,8 +1864,9 @@ class TrackPaymentRequest$Type extends MessageType { ]); } create(value?: PartialMessage): TrackPaymentRequest { - const message = { paymentHash: new Uint8Array(0), noInflightUpdates: false }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.paymentHash = new Uint8Array(0); + message.noInflightUpdates = false; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -1551,8 +1918,8 @@ class TrackPaymentsRequest$Type extends MessageType { ]); } create(value?: PartialMessage): TrackPaymentsRequest { - const message = { noInflightUpdates: false }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.noInflightUpdates = false; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -1595,12 +1962,17 @@ class RouteFeeRequest$Type extends MessageType { constructor() { super("routerrpc.RouteFeeRequest", [ { no: 1, name: "dest", kind: "scalar", T: 12 /*ScalarType.BYTES*/ }, - { no: 2, name: "amt_sat", kind: "scalar", T: 3 /*ScalarType.INT64*/, L: 0 /*LongType.BIGINT*/ } + { no: 2, name: "amt_sat", kind: "scalar", T: 3 /*ScalarType.INT64*/, L: 0 /*LongType.BIGINT*/ }, + { no: 3, name: "payment_request", kind: "scalar", T: 9 /*ScalarType.STRING*/ }, + { no: 4, name: "timeout", kind: "scalar", T: 13 /*ScalarType.UINT32*/ } ]); } create(value?: PartialMessage): RouteFeeRequest { - const message = { dest: new Uint8Array(0), amtSat: 0n }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.dest = new Uint8Array(0); + message.amtSat = 0n; + message.paymentRequest = ""; + message.timeout = 0; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -1616,6 +1988,12 @@ class RouteFeeRequest$Type extends MessageType { case /* int64 amt_sat */ 2: message.amtSat = reader.int64().toBigInt(); break; + case /* string payment_request */ 3: + message.paymentRequest = reader.string(); + break; + case /* uint32 timeout */ 4: + message.timeout = reader.uint32(); + break; default: let u = options.readUnknownField; if (u === "throw") @@ -1634,6 +2012,12 @@ class RouteFeeRequest$Type extends MessageType { /* int64 amt_sat = 2; */ if (message.amtSat !== 0n) writer.tag(2, WireType.Varint).int64(message.amtSat); + /* string payment_request = 3; */ + if (message.paymentRequest !== "") + writer.tag(3, WireType.LengthDelimited).string(message.paymentRequest); + /* uint32 timeout = 4; */ + if (message.timeout !== 0) + writer.tag(4, WireType.Varint).uint32(message.timeout); let u = options.writeUnknownFields; if (u !== false) (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer); @@ -1649,12 +2033,15 @@ class RouteFeeResponse$Type extends MessageType { constructor() { super("routerrpc.RouteFeeResponse", [ { no: 1, name: "routing_fee_msat", kind: "scalar", T: 3 /*ScalarType.INT64*/, L: 0 /*LongType.BIGINT*/ }, - { no: 2, name: "time_lock_delay", kind: "scalar", T: 3 /*ScalarType.INT64*/, L: 0 /*LongType.BIGINT*/ } + { no: 2, name: "time_lock_delay", kind: "scalar", T: 3 /*ScalarType.INT64*/, L: 0 /*LongType.BIGINT*/ }, + { no: 5, name: "failure_reason", kind: "enum", T: () => ["lnrpc.PaymentFailureReason", PaymentFailureReason] } ]); } create(value?: PartialMessage): RouteFeeResponse { - const message = { routingFeeMsat: 0n, timeLockDelay: 0n }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.routingFeeMsat = 0n; + message.timeLockDelay = 0n; + message.failureReason = 0; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -1670,6 +2057,9 @@ class RouteFeeResponse$Type extends MessageType { case /* int64 time_lock_delay */ 2: message.timeLockDelay = reader.int64().toBigInt(); break; + case /* lnrpc.PaymentFailureReason failure_reason */ 5: + message.failureReason = reader.int32(); + break; default: let u = options.readUnknownField; if (u === "throw") @@ -1688,6 +2078,9 @@ class RouteFeeResponse$Type extends MessageType { /* int64 time_lock_delay = 2; */ if (message.timeLockDelay !== 0n) writer.tag(2, WireType.Varint).int64(message.timeLockDelay); + /* lnrpc.PaymentFailureReason failure_reason = 5; */ + if (message.failureReason !== 0) + writer.tag(5, WireType.Varint).int32(message.failureReason); let u = options.writeUnknownFields; if (u !== false) (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer); @@ -1704,12 +2097,15 @@ class SendToRouteRequest$Type extends MessageType { super("routerrpc.SendToRouteRequest", [ { no: 1, name: "payment_hash", kind: "scalar", T: 12 /*ScalarType.BYTES*/ }, { no: 2, name: "route", kind: "message", T: () => Route }, - { no: 3, name: "skip_temp_err", kind: "scalar", T: 8 /*ScalarType.BOOL*/ } + { no: 3, name: "skip_temp_err", kind: "scalar", T: 8 /*ScalarType.BOOL*/ }, + { no: 4, name: "first_hop_custom_records", kind: "map", K: 4 /*ScalarType.UINT64*/, V: { kind: "scalar", T: 12 /*ScalarType.BYTES*/ } } ]); } create(value?: PartialMessage): SendToRouteRequest { - const message = { paymentHash: new Uint8Array(0), skipTempErr: false }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.paymentHash = new Uint8Array(0); + message.skipTempErr = false; + message.firstHopCustomRecords = {}; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -1728,6 +2124,9 @@ class SendToRouteRequest$Type extends MessageType { case /* bool skip_temp_err */ 3: message.skipTempErr = reader.bool(); break; + case /* map first_hop_custom_records */ 4: + this.binaryReadMap4(message.firstHopCustomRecords, reader, options); + break; default: let u = options.readUnknownField; if (u === "throw") @@ -1739,6 +2138,22 @@ class SendToRouteRequest$Type extends MessageType { } return message; } + private binaryReadMap4(map: SendToRouteRequest["firstHopCustomRecords"], reader: IBinaryReader, options: BinaryReadOptions): void { + let len = reader.uint32(), end = reader.pos + len, key: keyof SendToRouteRequest["firstHopCustomRecords"] | undefined, val: SendToRouteRequest["firstHopCustomRecords"][any] | undefined; + while (reader.pos < end) { + let [fieldNo, wireType] = reader.tag(); + switch (fieldNo) { + case 1: + key = reader.uint64().toString(); + break; + case 2: + val = reader.bytes(); + break; + default: throw new globalThis.Error("unknown map entry field for routerrpc.SendToRouteRequest.first_hop_custom_records"); + } + } + map[key ?? "0"] = val ?? new Uint8Array(0); + } internalBinaryWrite(message: SendToRouteRequest, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter { /* bytes payment_hash = 1; */ if (message.paymentHash.length) @@ -1749,6 +2164,9 @@ class SendToRouteRequest$Type extends MessageType { /* bool skip_temp_err = 3; */ if (message.skipTempErr !== false) writer.tag(3, WireType.Varint).bool(message.skipTempErr); + /* map first_hop_custom_records = 4; */ + for (let k of globalThis.Object.keys(message.firstHopCustomRecords)) + writer.tag(4, WireType.LengthDelimited).fork().tag(1, WireType.Varint).uint64(k).tag(2, WireType.LengthDelimited).bytes(message.firstHopCustomRecords[k]).join(); let u = options.writeUnknownFields; if (u !== false) (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer); @@ -1768,8 +2186,8 @@ class SendToRouteResponse$Type extends MessageType { ]); } create(value?: PartialMessage): SendToRouteResponse { - const message = { preimage: new Uint8Array(0) }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.preimage = new Uint8Array(0); if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -1819,14 +2237,26 @@ class ResetMissionControlRequest$Type extends MessageType): ResetMissionControlRequest { - const message = {}; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); if (value !== undefined) reflectionMergePartial(this, message, value); return message; } internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: ResetMissionControlRequest): ResetMissionControlRequest { - return target ?? this.create(); + let message = target ?? this.create(), end = reader.pos + length; + while (reader.pos < end) { + let [fieldNo, wireType] = reader.tag(); + switch (fieldNo) { + default: + let u = options.readUnknownField; + if (u === "throw") + throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`); + let d = reader.skip(wireType); + if (u !== false) + (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d); + } + } + return message; } internalBinaryWrite(message: ResetMissionControlRequest, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter { let u = options.writeUnknownFields; @@ -1845,14 +2275,26 @@ class ResetMissionControlResponse$Type extends MessageType): ResetMissionControlResponse { - const message = {}; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); if (value !== undefined) reflectionMergePartial(this, message, value); return message; } internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: ResetMissionControlResponse): ResetMissionControlResponse { - return target ?? this.create(); + let message = target ?? this.create(), end = reader.pos + length; + while (reader.pos < end) { + let [fieldNo, wireType] = reader.tag(); + switch (fieldNo) { + default: + let u = options.readUnknownField; + if (u === "throw") + throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`); + let d = reader.skip(wireType); + if (u !== false) + (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d); + } + } + return message; } internalBinaryWrite(message: ResetMissionControlResponse, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter { let u = options.writeUnknownFields; @@ -1871,14 +2313,26 @@ class QueryMissionControlRequest$Type extends MessageType): QueryMissionControlRequest { - const message = {}; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); if (value !== undefined) reflectionMergePartial(this, message, value); return message; } internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: QueryMissionControlRequest): QueryMissionControlRequest { - return target ?? this.create(); + let message = target ?? this.create(), end = reader.pos + length; + while (reader.pos < end) { + let [fieldNo, wireType] = reader.tag(); + switch (fieldNo) { + default: + let u = options.readUnknownField; + if (u === "throw") + throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`); + let d = reader.skip(wireType); + if (u !== false) + (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d); + } + } + return message; } internalBinaryWrite(message: QueryMissionControlRequest, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter { let u = options.writeUnknownFields; @@ -1895,12 +2349,12 @@ export const QueryMissionControlRequest = new QueryMissionControlRequest$Type(); class QueryMissionControlResponse$Type extends MessageType { constructor() { super("routerrpc.QueryMissionControlResponse", [ - { no: 2, name: "pairs", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => PairHistory } + { no: 2, name: "pairs", kind: "message", repeat: 2 /*RepeatType.UNPACKED*/, T: () => PairHistory } ]); } create(value?: PartialMessage): QueryMissionControlResponse { - const message = { pairs: [] }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.pairs = []; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -1942,13 +2396,14 @@ export const QueryMissionControlResponse = new QueryMissionControlResponse$Type( class XImportMissionControlRequest$Type extends MessageType { constructor() { super("routerrpc.XImportMissionControlRequest", [ - { no: 1, name: "pairs", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => PairHistory }, + { no: 1, name: "pairs", kind: "message", repeat: 2 /*RepeatType.UNPACKED*/, T: () => PairHistory }, { no: 2, name: "force", kind: "scalar", T: 8 /*ScalarType.BOOL*/ } ]); } create(value?: PartialMessage): XImportMissionControlRequest { - const message = { pairs: [], force: false }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.pairs = []; + message.force = false; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -1998,14 +2453,26 @@ class XImportMissionControlResponse$Type extends MessageType): XImportMissionControlResponse { - const message = {}; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); if (value !== undefined) reflectionMergePartial(this, message, value); return message; } internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: XImportMissionControlResponse): XImportMissionControlResponse { - return target ?? this.create(); + let message = target ?? this.create(), end = reader.pos + length; + while (reader.pos < end) { + let [fieldNo, wireType] = reader.tag(); + switch (fieldNo) { + default: + let u = options.readUnknownField; + if (u === "throw") + throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`); + let d = reader.skip(wireType); + if (u !== false) + (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d); + } + } + return message; } internalBinaryWrite(message: XImportMissionControlResponse, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter { let u = options.writeUnknownFields; @@ -2028,8 +2495,9 @@ class PairHistory$Type extends MessageType { ]); } create(value?: PartialMessage): PairHistory { - const message = { nodeFrom: new Uint8Array(0), nodeTo: new Uint8Array(0) }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.nodeFrom = new Uint8Array(0); + message.nodeTo = new Uint8Array(0); if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -2092,8 +2560,13 @@ class PairData$Type extends MessageType { ]); } create(value?: PartialMessage): PairData { - const message = { failTime: 0n, failAmtSat: 0n, failAmtMsat: 0n, successTime: 0n, successAmtSat: 0n, successAmtMsat: 0n }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.failTime = 0n; + message.failAmtSat = 0n; + message.failAmtMsat = 0n; + message.successTime = 0n; + message.successAmtSat = 0n; + message.successAmtMsat = 0n; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -2167,14 +2640,26 @@ class GetMissionControlConfigRequest$Type extends MessageType): GetMissionControlConfigRequest { - const message = {}; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); if (value !== undefined) reflectionMergePartial(this, message, value); return message; } internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: GetMissionControlConfigRequest): GetMissionControlConfigRequest { - return target ?? this.create(); + let message = target ?? this.create(), end = reader.pos + length; + while (reader.pos < end) { + let [fieldNo, wireType] = reader.tag(); + switch (fieldNo) { + default: + let u = options.readUnknownField; + if (u === "throw") + throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`); + let d = reader.skip(wireType); + if (u !== false) + (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d); + } + } + return message; } internalBinaryWrite(message: GetMissionControlConfigRequest, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter { let u = options.writeUnknownFields; @@ -2195,8 +2680,7 @@ class GetMissionControlConfigResponse$Type extends MessageType): GetMissionControlConfigResponse { - const message = {}; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -2242,8 +2726,7 @@ class SetMissionControlConfigRequest$Type extends MessageType): SetMissionControlConfigRequest { - const message = {}; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -2287,14 +2770,26 @@ class SetMissionControlConfigResponse$Type extends MessageType): SetMissionControlConfigResponse { - const message = {}; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); if (value !== undefined) reflectionMergePartial(this, message, value); return message; } internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: SetMissionControlConfigResponse): SetMissionControlConfigResponse { - return target ?? this.create(); + let message = target ?? this.create(), end = reader.pos + length; + while (reader.pos < end) { + let [fieldNo, wireType] = reader.tag(); + switch (fieldNo) { + default: + let u = options.readUnknownField; + if (u === "throw") + throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`); + let d = reader.skip(wireType); + if (u !== false) + (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d); + } + } + return message; } internalBinaryWrite(message: SetMissionControlConfigResponse, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter { let u = options.writeUnknownFields; @@ -2315,12 +2810,21 @@ class MissionControlConfig$Type extends MessageType { { no: 2, name: "hop_probability", kind: "scalar", T: 2 /*ScalarType.FLOAT*/ }, { no: 3, name: "weight", kind: "scalar", T: 2 /*ScalarType.FLOAT*/ }, { no: 4, name: "maximum_payment_results", kind: "scalar", T: 13 /*ScalarType.UINT32*/ }, - { no: 5, name: "minimum_failure_relax_interval", kind: "scalar", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ } + { no: 5, name: "minimum_failure_relax_interval", kind: "scalar", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ }, + { no: 6, name: "model", kind: "enum", T: () => ["routerrpc.MissionControlConfig.ProbabilityModel", MissionControlConfig_ProbabilityModel] }, + { no: 7, name: "apriori", kind: "message", oneof: "estimatorConfig", T: () => AprioriParameters }, + { no: 8, name: "bimodal", kind: "message", oneof: "estimatorConfig", T: () => BimodalParameters } ]); } create(value?: PartialMessage): MissionControlConfig { - const message = { halfLifeSeconds: 0n, hopProbability: 0, weight: 0, maximumPaymentResults: 0, minimumFailureRelaxInterval: 0n }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.halfLifeSeconds = 0n; + message.hopProbability = 0; + message.weight = 0; + message.maximumPaymentResults = 0; + message.minimumFailureRelaxInterval = 0n; + message.model = 0; + message.estimatorConfig = { oneofKind: undefined }; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -2330,13 +2834,13 @@ class MissionControlConfig$Type extends MessageType { while (reader.pos < end) { let [fieldNo, wireType] = reader.tag(); switch (fieldNo) { - case /* uint64 half_life_seconds */ 1: + case /* uint64 half_life_seconds = 1 [deprecated = true] */ 1: message.halfLifeSeconds = reader.uint64().toBigInt(); break; - case /* float hop_probability */ 2: + case /* float hop_probability = 2 [deprecated = true] */ 2: message.hopProbability = reader.float(); break; - case /* float weight */ 3: + case /* float weight = 3 [deprecated = true] */ 3: message.weight = reader.float(); break; case /* uint32 maximum_payment_results */ 4: @@ -2345,6 +2849,21 @@ class MissionControlConfig$Type extends MessageType { case /* uint64 minimum_failure_relax_interval */ 5: message.minimumFailureRelaxInterval = reader.uint64().toBigInt(); break; + case /* routerrpc.MissionControlConfig.ProbabilityModel model */ 6: + message.model = reader.int32(); + break; + case /* routerrpc.AprioriParameters apriori */ 7: + message.estimatorConfig = { + oneofKind: "apriori", + apriori: AprioriParameters.internalBinaryRead(reader, reader.uint32(), options, (message.estimatorConfig as any).apriori) + }; + break; + case /* routerrpc.BimodalParameters bimodal */ 8: + message.estimatorConfig = { + oneofKind: "bimodal", + bimodal: BimodalParameters.internalBinaryRead(reader, reader.uint32(), options, (message.estimatorConfig as any).bimodal) + }; + break; default: let u = options.readUnknownField; if (u === "throw") @@ -2357,13 +2876,13 @@ class MissionControlConfig$Type extends MessageType { return message; } internalBinaryWrite(message: MissionControlConfig, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter { - /* uint64 half_life_seconds = 1; */ + /* uint64 half_life_seconds = 1 [deprecated = true]; */ if (message.halfLifeSeconds !== 0n) writer.tag(1, WireType.Varint).uint64(message.halfLifeSeconds); - /* float hop_probability = 2; */ + /* float hop_probability = 2 [deprecated = true]; */ if (message.hopProbability !== 0) writer.tag(2, WireType.Bit32).float(message.hopProbability); - /* float weight = 3; */ + /* float weight = 3 [deprecated = true]; */ if (message.weight !== 0) writer.tag(3, WireType.Bit32).float(message.weight); /* uint32 maximum_payment_results = 4; */ @@ -2372,6 +2891,15 @@ class MissionControlConfig$Type extends MessageType { /* uint64 minimum_failure_relax_interval = 5; */ if (message.minimumFailureRelaxInterval !== 0n) writer.tag(5, WireType.Varint).uint64(message.minimumFailureRelaxInterval); + /* routerrpc.MissionControlConfig.ProbabilityModel model = 6; */ + if (message.model !== 0) + writer.tag(6, WireType.Varint).int32(message.model); + /* routerrpc.AprioriParameters apriori = 7; */ + if (message.estimatorConfig.oneofKind === "apriori") + AprioriParameters.internalBinaryWrite(message.estimatorConfig.apriori, writer.tag(7, WireType.LengthDelimited).fork(), options).join(); + /* routerrpc.BimodalParameters bimodal = 8; */ + if (message.estimatorConfig.oneofKind === "bimodal") + BimodalParameters.internalBinaryWrite(message.estimatorConfig.bimodal, writer.tag(8, WireType.LengthDelimited).fork(), options).join(); let u = options.writeUnknownFields; if (u !== false) (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer); @@ -2383,6 +2911,140 @@ class MissionControlConfig$Type extends MessageType { */ export const MissionControlConfig = new MissionControlConfig$Type(); // @generated message type with reflection information, may provide speed optimized methods +class BimodalParameters$Type extends MessageType { + constructor() { + super("routerrpc.BimodalParameters", [ + { no: 1, name: "node_weight", kind: "scalar", T: 1 /*ScalarType.DOUBLE*/ }, + { no: 2, name: "scale_msat", kind: "scalar", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ }, + { no: 3, name: "decay_time", kind: "scalar", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ } + ]); + } + create(value?: PartialMessage): BimodalParameters { + const message = globalThis.Object.create((this.messagePrototype!)); + message.nodeWeight = 0; + message.scaleMsat = 0n; + message.decayTime = 0n; + if (value !== undefined) + reflectionMergePartial(this, message, value); + return message; + } + internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: BimodalParameters): BimodalParameters { + let message = target ?? this.create(), end = reader.pos + length; + while (reader.pos < end) { + let [fieldNo, wireType] = reader.tag(); + switch (fieldNo) { + case /* double node_weight */ 1: + message.nodeWeight = reader.double(); + break; + case /* uint64 scale_msat */ 2: + message.scaleMsat = reader.uint64().toBigInt(); + break; + case /* uint64 decay_time */ 3: + message.decayTime = reader.uint64().toBigInt(); + break; + default: + let u = options.readUnknownField; + if (u === "throw") + throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`); + let d = reader.skip(wireType); + if (u !== false) + (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d); + } + } + return message; + } + internalBinaryWrite(message: BimodalParameters, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter { + /* double node_weight = 1; */ + if (message.nodeWeight !== 0) + writer.tag(1, WireType.Bit64).double(message.nodeWeight); + /* uint64 scale_msat = 2; */ + if (message.scaleMsat !== 0n) + writer.tag(2, WireType.Varint).uint64(message.scaleMsat); + /* uint64 decay_time = 3; */ + if (message.decayTime !== 0n) + writer.tag(3, WireType.Varint).uint64(message.decayTime); + let u = options.writeUnknownFields; + if (u !== false) + (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer); + return writer; + } +} +/** + * @generated MessageType for protobuf message routerrpc.BimodalParameters + */ +export const BimodalParameters = new BimodalParameters$Type(); +// @generated message type with reflection information, may provide speed optimized methods +class AprioriParameters$Type extends MessageType { + constructor() { + super("routerrpc.AprioriParameters", [ + { no: 1, name: "half_life_seconds", kind: "scalar", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ }, + { no: 2, name: "hop_probability", kind: "scalar", T: 1 /*ScalarType.DOUBLE*/ }, + { no: 3, name: "weight", kind: "scalar", T: 1 /*ScalarType.DOUBLE*/ }, + { no: 4, name: "capacity_fraction", kind: "scalar", T: 1 /*ScalarType.DOUBLE*/ } + ]); + } + create(value?: PartialMessage): AprioriParameters { + const message = globalThis.Object.create((this.messagePrototype!)); + message.halfLifeSeconds = 0n; + message.hopProbability = 0; + message.weight = 0; + message.capacityFraction = 0; + if (value !== undefined) + reflectionMergePartial(this, message, value); + return message; + } + internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: AprioriParameters): AprioriParameters { + let message = target ?? this.create(), end = reader.pos + length; + while (reader.pos < end) { + let [fieldNo, wireType] = reader.tag(); + switch (fieldNo) { + case /* uint64 half_life_seconds */ 1: + message.halfLifeSeconds = reader.uint64().toBigInt(); + break; + case /* double hop_probability */ 2: + message.hopProbability = reader.double(); + break; + case /* double weight */ 3: + message.weight = reader.double(); + break; + case /* double capacity_fraction */ 4: + message.capacityFraction = reader.double(); + break; + default: + let u = options.readUnknownField; + if (u === "throw") + throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`); + let d = reader.skip(wireType); + if (u !== false) + (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d); + } + } + return message; + } + internalBinaryWrite(message: AprioriParameters, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter { + /* uint64 half_life_seconds = 1; */ + if (message.halfLifeSeconds !== 0n) + writer.tag(1, WireType.Varint).uint64(message.halfLifeSeconds); + /* double hop_probability = 2; */ + if (message.hopProbability !== 0) + writer.tag(2, WireType.Bit64).double(message.hopProbability); + /* double weight = 3; */ + if (message.weight !== 0) + writer.tag(3, WireType.Bit64).double(message.weight); + /* double capacity_fraction = 4; */ + if (message.capacityFraction !== 0) + writer.tag(4, WireType.Bit64).double(message.capacityFraction); + let u = options.writeUnknownFields; + if (u !== false) + (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer); + return writer; + } +} +/** + * @generated MessageType for protobuf message routerrpc.AprioriParameters + */ +export const AprioriParameters = new AprioriParameters$Type(); +// @generated message type with reflection information, may provide speed optimized methods class QueryProbabilityRequest$Type extends MessageType { constructor() { super("routerrpc.QueryProbabilityRequest", [ @@ -2392,8 +3054,10 @@ class QueryProbabilityRequest$Type extends MessageType ]); } create(value?: PartialMessage): QueryProbabilityRequest { - const message = { fromNode: new Uint8Array(0), toNode: new Uint8Array(0), amtMsat: 0n }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.fromNode = new Uint8Array(0); + message.toNode = new Uint8Array(0); + message.amtMsat = 0n; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -2452,8 +3116,8 @@ class QueryProbabilityResponse$Type extends MessageType): QueryProbabilityResponse { - const message = { probability: 0 }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.probability = 0; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -2505,12 +3169,18 @@ class BuildRouteRequest$Type extends MessageType { { no: 2, name: "final_cltv_delta", kind: "scalar", T: 5 /*ScalarType.INT32*/ }, { no: 3, name: "outgoing_chan_id", kind: "scalar", T: 4 /*ScalarType.UINT64*/ }, { no: 4, name: "hop_pubkeys", kind: "scalar", repeat: 2 /*RepeatType.UNPACKED*/, T: 12 /*ScalarType.BYTES*/ }, - { no: 5, name: "payment_addr", kind: "scalar", T: 12 /*ScalarType.BYTES*/ } + { no: 5, name: "payment_addr", kind: "scalar", T: 12 /*ScalarType.BYTES*/ }, + { no: 6, name: "first_hop_custom_records", kind: "map", K: 4 /*ScalarType.UINT64*/, V: { kind: "scalar", T: 12 /*ScalarType.BYTES*/ } } ]); } create(value?: PartialMessage): BuildRouteRequest { - const message = { amtMsat: 0n, finalCltvDelta: 0, outgoingChanId: "0", hopPubkeys: [], paymentAddr: new Uint8Array(0) }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.amtMsat = 0n; + message.finalCltvDelta = 0; + message.outgoingChanId = "0"; + message.hopPubkeys = []; + message.paymentAddr = new Uint8Array(0); + message.firstHopCustomRecords = {}; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -2526,7 +3196,7 @@ class BuildRouteRequest$Type extends MessageType { case /* int32 final_cltv_delta */ 2: message.finalCltvDelta = reader.int32(); break; - case /* uint64 outgoing_chan_id = 3 [jstype = JS_STRING];*/ 3: + case /* uint64 outgoing_chan_id = 3 [jstype = JS_STRING] */ 3: message.outgoingChanId = reader.uint64().toString(); break; case /* repeated bytes hop_pubkeys */ 4: @@ -2535,6 +3205,9 @@ class BuildRouteRequest$Type extends MessageType { case /* bytes payment_addr */ 5: message.paymentAddr = reader.bytes(); break; + case /* map first_hop_custom_records */ 6: + this.binaryReadMap6(message.firstHopCustomRecords, reader, options); + break; default: let u = options.readUnknownField; if (u === "throw") @@ -2546,6 +3219,22 @@ class BuildRouteRequest$Type extends MessageType { } return message; } + private binaryReadMap6(map: BuildRouteRequest["firstHopCustomRecords"], reader: IBinaryReader, options: BinaryReadOptions): void { + let len = reader.uint32(), end = reader.pos + len, key: keyof BuildRouteRequest["firstHopCustomRecords"] | undefined, val: BuildRouteRequest["firstHopCustomRecords"][any] | undefined; + while (reader.pos < end) { + let [fieldNo, wireType] = reader.tag(); + switch (fieldNo) { + case 1: + key = reader.uint64().toString(); + break; + case 2: + val = reader.bytes(); + break; + default: throw new globalThis.Error("unknown map entry field for routerrpc.BuildRouteRequest.first_hop_custom_records"); + } + } + map[key ?? "0"] = val ?? new Uint8Array(0); + } internalBinaryWrite(message: BuildRouteRequest, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter { /* int64 amt_msat = 1; */ if (message.amtMsat !== 0n) @@ -2562,6 +3251,9 @@ class BuildRouteRequest$Type extends MessageType { /* bytes payment_addr = 5; */ if (message.paymentAddr.length) writer.tag(5, WireType.LengthDelimited).bytes(message.paymentAddr); + /* map first_hop_custom_records = 6; */ + for (let k of globalThis.Object.keys(message.firstHopCustomRecords)) + writer.tag(6, WireType.LengthDelimited).fork().tag(1, WireType.Varint).uint64(k).tag(2, WireType.LengthDelimited).bytes(message.firstHopCustomRecords[k]).join(); let u = options.writeUnknownFields; if (u !== false) (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer); @@ -2580,8 +3272,7 @@ class BuildRouteResponse$Type extends MessageType { ]); } create(value?: PartialMessage): BuildRouteResponse { - const message = {}; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -2625,14 +3316,26 @@ class SubscribeHtlcEventsRequest$Type extends MessageType): SubscribeHtlcEventsRequest { - const message = {}; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); if (value !== undefined) reflectionMergePartial(this, message, value); return message; } internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: SubscribeHtlcEventsRequest): SubscribeHtlcEventsRequest { - return target ?? this.create(); + let message = target ?? this.create(), end = reader.pos + length; + while (reader.pos < end) { + let [fieldNo, wireType] = reader.tag(); + switch (fieldNo) { + default: + let u = options.readUnknownField; + if (u === "throw") + throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`); + let d = reader.skip(wireType); + if (u !== false) + (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d); + } + } + return message; } internalBinaryWrite(message: SubscribeHtlcEventsRequest, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter { let u = options.writeUnknownFields; @@ -2664,8 +3367,14 @@ class HtlcEvent$Type extends MessageType { ]); } create(value?: PartialMessage): HtlcEvent { - const message = { incomingChannelId: 0n, outgoingChannelId: 0n, incomingHtlcId: 0n, outgoingHtlcId: 0n, timestampNs: 0n, eventType: 0, event: { oneofKind: undefined } }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.incomingChannelId = 0n; + message.outgoingChannelId = 0n; + message.incomingHtlcId = 0n; + message.outgoingHtlcId = 0n; + message.timestampNs = 0n; + message.eventType = 0; + message.event = { oneofKind: undefined }; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -2798,8 +3507,11 @@ class HtlcInfo$Type extends MessageType { ]); } create(value?: PartialMessage): HtlcInfo { - const message = { incomingTimelock: 0, outgoingTimelock: 0, incomingAmtMsat: 0n, outgoingAmtMsat: 0n }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.incomingTimelock = 0; + message.outgoingTimelock = 0; + message.incomingAmtMsat = 0n; + message.outgoingAmtMsat = 0n; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -2863,8 +3575,7 @@ class ForwardEvent$Type extends MessageType { ]); } create(value?: PartialMessage): ForwardEvent { - const message = {}; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -2908,14 +3619,26 @@ class ForwardFailEvent$Type extends MessageType { super("routerrpc.ForwardFailEvent", []); } create(value?: PartialMessage): ForwardFailEvent { - const message = {}; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); if (value !== undefined) reflectionMergePartial(this, message, value); return message; } internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: ForwardFailEvent): ForwardFailEvent { - return target ?? this.create(); + let message = target ?? this.create(), end = reader.pos + length; + while (reader.pos < end) { + let [fieldNo, wireType] = reader.tag(); + switch (fieldNo) { + default: + let u = options.readUnknownField; + if (u === "throw") + throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`); + let d = reader.skip(wireType); + if (u !== false) + (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d); + } + } + return message; } internalBinaryWrite(message: ForwardFailEvent, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter { let u = options.writeUnknownFields; @@ -2936,8 +3659,8 @@ class SettleEvent$Type extends MessageType { ]); } create(value?: PartialMessage): SettleEvent { - const message = { preimage: new Uint8Array(0) }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.preimage = new Uint8Array(0); if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -2984,8 +3707,9 @@ class FinalHtlcEvent$Type extends MessageType { ]); } create(value?: PartialMessage): FinalHtlcEvent { - const message = { settled: false, offchain: false }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.settled = false; + message.offchain = false; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -3035,14 +3759,26 @@ class SubscribedEvent$Type extends MessageType { super("routerrpc.SubscribedEvent", []); } create(value?: PartialMessage): SubscribedEvent { - const message = {}; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); if (value !== undefined) reflectionMergePartial(this, message, value); return message; } internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: SubscribedEvent): SubscribedEvent { - return target ?? this.create(); + let message = target ?? this.create(), end = reader.pos + length; + while (reader.pos < end) { + let [fieldNo, wireType] = reader.tag(); + switch (fieldNo) { + default: + let u = options.readUnknownField; + if (u === "throw") + throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`); + let d = reader.skip(wireType); + if (u !== false) + (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d); + } + } + return message; } internalBinaryWrite(message: SubscribedEvent, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter { let u = options.writeUnknownFields; @@ -3066,8 +3802,10 @@ class LinkFailEvent$Type extends MessageType { ]); } create(value?: PartialMessage): LinkFailEvent { - const message = { wireFailure: 0, failureDetail: 0, failureString: "" }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.wireFailure = 0; + message.failureDetail = 0; + message.failureString = ""; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -3129,12 +3867,14 @@ class PaymentStatus$Type extends MessageType { super("routerrpc.PaymentStatus", [ { no: 1, name: "state", kind: "enum", T: () => ["routerrpc.PaymentState", PaymentState] }, { no: 2, name: "preimage", kind: "scalar", T: 12 /*ScalarType.BYTES*/ }, - { no: 4, name: "htlcs", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => HTLCAttempt } + { no: 4, name: "htlcs", kind: "message", repeat: 2 /*RepeatType.UNPACKED*/, T: () => HTLCAttempt } ]); } create(value?: PartialMessage): PaymentStatus { - const message = { state: 0, preimage: new Uint8Array(0), htlcs: [] }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.state = 0; + message.preimage = new Uint8Array(0); + message.htlcs = []; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -3193,8 +3933,9 @@ class CircuitKey$Type extends MessageType { ]); } create(value?: PartialMessage): CircuitKey { - const message = { chanId: 0n, htlcId: 0n }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.chanId = 0n; + message.htlcId = 0n; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -3251,12 +3992,22 @@ class ForwardHtlcInterceptRequest$Type extends MessageType): ForwardHtlcInterceptRequest { - const message = { incomingAmountMsat: 0n, incomingExpiry: 0, paymentHash: new Uint8Array(0), outgoingRequestedChanId: 0n, outgoingAmountMsat: 0n, outgoingExpiry: 0, customRecords: {}, onionBlob: new Uint8Array(0), autoFailHeight: 0 }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.incomingAmountMsat = 0n; + message.incomingExpiry = 0; + message.paymentHash = new Uint8Array(0); + message.outgoingRequestedChanId = 0n; + message.outgoingAmountMsat = 0n; + message.outgoingExpiry = 0; + message.customRecords = {}; + message.onionBlob = new Uint8Array(0); + message.autoFailHeight = 0; + message.inWireCustomRecords = {}; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -3296,6 +4047,9 @@ class ForwardHtlcInterceptRequest$Type extends MessageType in_wire_custom_records */ 11: + this.binaryReadMap11(message.inWireCustomRecords, reader, options); + break; default: let u = options.readUnknownField; if (u === "throw") @@ -3318,7 +4072,23 @@ class ForwardHtlcInterceptRequest$Type extends MessageType custom_records = 8; */ - for (let k of Object.keys(message.customRecords)) + for (let k of globalThis.Object.keys(message.customRecords)) writer.tag(8, WireType.LengthDelimited).fork().tag(1, WireType.Varint).uint64(k).tag(2, WireType.LengthDelimited).bytes(message.customRecords[k]).join(); /* bytes onion_blob = 9; */ if (message.onionBlob.length) @@ -3354,6 +4124,9 @@ class ForwardHtlcInterceptRequest$Type extends MessageType in_wire_custom_records = 11; */ + for (let k of globalThis.Object.keys(message.inWireCustomRecords)) + writer.tag(11, WireType.LengthDelimited).fork().tag(1, WireType.Varint).uint64(k).tag(2, WireType.LengthDelimited).bytes(message.inWireCustomRecords[k]).join(); let u = options.writeUnknownFields; if (u !== false) (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer); @@ -3372,12 +4145,21 @@ class ForwardHtlcInterceptResponse$Type extends MessageType ["routerrpc.ResolveHoldForwardAction", ResolveHoldForwardAction] }, { no: 3, name: "preimage", kind: "scalar", T: 12 /*ScalarType.BYTES*/ }, { no: 4, name: "failure_message", kind: "scalar", T: 12 /*ScalarType.BYTES*/ }, - { no: 5, name: "failure_code", kind: "enum", T: () => ["lnrpc.Failure.FailureCode", Failure_FailureCode] } + { no: 5, name: "failure_code", kind: "enum", T: () => ["lnrpc.Failure.FailureCode", Failure_FailureCode] }, + { no: 6, name: "in_amount_msat", kind: "scalar", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ }, + { no: 7, name: "out_amount_msat", kind: "scalar", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ }, + { no: 8, name: "out_wire_custom_records", kind: "map", K: 4 /*ScalarType.UINT64*/, V: { kind: "scalar", T: 12 /*ScalarType.BYTES*/ } } ]); } create(value?: PartialMessage): ForwardHtlcInterceptResponse { - const message = { action: 0, preimage: new Uint8Array(0), failureMessage: new Uint8Array(0), failureCode: 0 }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.action = 0; + message.preimage = new Uint8Array(0); + message.failureMessage = new Uint8Array(0); + message.failureCode = 0; + message.inAmountMsat = 0n; + message.outAmountMsat = 0n; + message.outWireCustomRecords = {}; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -3402,6 +4184,15 @@ class ForwardHtlcInterceptResponse$Type extends MessageType out_wire_custom_records */ 8: + this.binaryReadMap8(message.outWireCustomRecords, reader, options); + break; default: let u = options.readUnknownField; if (u === "throw") @@ -3413,6 +4204,22 @@ class ForwardHtlcInterceptResponse$Type extends MessageType out_wire_custom_records = 8; */ + for (let k of globalThis.Object.keys(message.outWireCustomRecords)) + writer.tag(8, WireType.LengthDelimited).fork().tag(1, WireType.Varint).uint64(k).tag(2, WireType.LengthDelimited).bytes(message.outWireCustomRecords[k]).join(); let u = options.writeUnknownFields; if (u !== false) (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer); @@ -3448,8 +4264,8 @@ class UpdateChanStatusRequest$Type extends MessageType ]); } create(value?: PartialMessage): UpdateChanStatusRequest { - const message = { action: 0 }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.action = 0; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -3499,14 +4315,26 @@ class UpdateChanStatusResponse$Type extends MessageType): UpdateChanStatusResponse { - const message = {}; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); if (value !== undefined) reflectionMergePartial(this, message, value); return message; } internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: UpdateChanStatusResponse): UpdateChanStatusResponse { - return target ?? this.create(); + let message = target ?? this.create(), end = reader.pos + length; + while (reader.pos < end) { + let [fieldNo, wireType] = reader.tag(); + switch (fieldNo) { + default: + let u = options.readUnknownField; + if (u === "throw") + throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`); + let d = reader.skip(wireType); + if (u !== false) + (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d); + } + } + return message; } internalBinaryWrite(message: UpdateChanStatusResponse, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter { let u = options.writeUnknownFields; @@ -3519,6 +4347,194 @@ class UpdateChanStatusResponse$Type extends MessageType { + constructor() { + super("routerrpc.AddAliasesRequest", [ + { no: 1, name: "alias_maps", kind: "message", repeat: 2 /*RepeatType.UNPACKED*/, T: () => AliasMap } + ]); + } + create(value?: PartialMessage): AddAliasesRequest { + const message = globalThis.Object.create((this.messagePrototype!)); + message.aliasMaps = []; + if (value !== undefined) + reflectionMergePartial(this, message, value); + return message; + } + internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: AddAliasesRequest): AddAliasesRequest { + let message = target ?? this.create(), end = reader.pos + length; + while (reader.pos < end) { + let [fieldNo, wireType] = reader.tag(); + switch (fieldNo) { + case /* repeated lnrpc.AliasMap alias_maps */ 1: + message.aliasMaps.push(AliasMap.internalBinaryRead(reader, reader.uint32(), options)); + break; + default: + let u = options.readUnknownField; + if (u === "throw") + throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`); + let d = reader.skip(wireType); + if (u !== false) + (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d); + } + } + return message; + } + internalBinaryWrite(message: AddAliasesRequest, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter { + /* repeated lnrpc.AliasMap alias_maps = 1; */ + for (let i = 0; i < message.aliasMaps.length; i++) + AliasMap.internalBinaryWrite(message.aliasMaps[i], writer.tag(1, WireType.LengthDelimited).fork(), options).join(); + let u = options.writeUnknownFields; + if (u !== false) + (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer); + return writer; + } +} +/** + * @generated MessageType for protobuf message routerrpc.AddAliasesRequest + */ +export const AddAliasesRequest = new AddAliasesRequest$Type(); +// @generated message type with reflection information, may provide speed optimized methods +class AddAliasesResponse$Type extends MessageType { + constructor() { + super("routerrpc.AddAliasesResponse", [ + { no: 1, name: "alias_maps", kind: "message", repeat: 2 /*RepeatType.UNPACKED*/, T: () => AliasMap } + ]); + } + create(value?: PartialMessage): AddAliasesResponse { + const message = globalThis.Object.create((this.messagePrototype!)); + message.aliasMaps = []; + if (value !== undefined) + reflectionMergePartial(this, message, value); + return message; + } + internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: AddAliasesResponse): AddAliasesResponse { + let message = target ?? this.create(), end = reader.pos + length; + while (reader.pos < end) { + let [fieldNo, wireType] = reader.tag(); + switch (fieldNo) { + case /* repeated lnrpc.AliasMap alias_maps */ 1: + message.aliasMaps.push(AliasMap.internalBinaryRead(reader, reader.uint32(), options)); + break; + default: + let u = options.readUnknownField; + if (u === "throw") + throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`); + let d = reader.skip(wireType); + if (u !== false) + (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d); + } + } + return message; + } + internalBinaryWrite(message: AddAliasesResponse, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter { + /* repeated lnrpc.AliasMap alias_maps = 1; */ + for (let i = 0; i < message.aliasMaps.length; i++) + AliasMap.internalBinaryWrite(message.aliasMaps[i], writer.tag(1, WireType.LengthDelimited).fork(), options).join(); + let u = options.writeUnknownFields; + if (u !== false) + (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer); + return writer; + } +} +/** + * @generated MessageType for protobuf message routerrpc.AddAliasesResponse + */ +export const AddAliasesResponse = new AddAliasesResponse$Type(); +// @generated message type with reflection information, may provide speed optimized methods +class DeleteAliasesRequest$Type extends MessageType { + constructor() { + super("routerrpc.DeleteAliasesRequest", [ + { no: 1, name: "alias_maps", kind: "message", repeat: 2 /*RepeatType.UNPACKED*/, T: () => AliasMap } + ]); + } + create(value?: PartialMessage): DeleteAliasesRequest { + const message = globalThis.Object.create((this.messagePrototype!)); + message.aliasMaps = []; + if (value !== undefined) + reflectionMergePartial(this, message, value); + return message; + } + internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: DeleteAliasesRequest): DeleteAliasesRequest { + let message = target ?? this.create(), end = reader.pos + length; + while (reader.pos < end) { + let [fieldNo, wireType] = reader.tag(); + switch (fieldNo) { + case /* repeated lnrpc.AliasMap alias_maps */ 1: + message.aliasMaps.push(AliasMap.internalBinaryRead(reader, reader.uint32(), options)); + break; + default: + let u = options.readUnknownField; + if (u === "throw") + throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`); + let d = reader.skip(wireType); + if (u !== false) + (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d); + } + } + return message; + } + internalBinaryWrite(message: DeleteAliasesRequest, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter { + /* repeated lnrpc.AliasMap alias_maps = 1; */ + for (let i = 0; i < message.aliasMaps.length; i++) + AliasMap.internalBinaryWrite(message.aliasMaps[i], writer.tag(1, WireType.LengthDelimited).fork(), options).join(); + let u = options.writeUnknownFields; + if (u !== false) + (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer); + return writer; + } +} +/** + * @generated MessageType for protobuf message routerrpc.DeleteAliasesRequest + */ +export const DeleteAliasesRequest = new DeleteAliasesRequest$Type(); +// @generated message type with reflection information, may provide speed optimized methods +class DeleteAliasesResponse$Type extends MessageType { + constructor() { + super("routerrpc.DeleteAliasesResponse", [ + { no: 1, name: "alias_maps", kind: "message", repeat: 2 /*RepeatType.UNPACKED*/, T: () => AliasMap } + ]); + } + create(value?: PartialMessage): DeleteAliasesResponse { + const message = globalThis.Object.create((this.messagePrototype!)); + message.aliasMaps = []; + if (value !== undefined) + reflectionMergePartial(this, message, value); + return message; + } + internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: DeleteAliasesResponse): DeleteAliasesResponse { + let message = target ?? this.create(), end = reader.pos + length; + while (reader.pos < end) { + let [fieldNo, wireType] = reader.tag(); + switch (fieldNo) { + case /* repeated lnrpc.AliasMap alias_maps */ 1: + message.aliasMaps.push(AliasMap.internalBinaryRead(reader, reader.uint32(), options)); + break; + default: + let u = options.readUnknownField; + if (u === "throw") + throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`); + let d = reader.skip(wireType); + if (u !== false) + (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d); + } + } + return message; + } + internalBinaryWrite(message: DeleteAliasesResponse, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter { + /* repeated lnrpc.AliasMap alias_maps = 1; */ + for (let i = 0; i < message.aliasMaps.length; i++) + AliasMap.internalBinaryWrite(message.aliasMaps[i], writer.tag(1, WireType.LengthDelimited).fork(), options).join(); + let u = options.writeUnknownFields; + if (u !== false) + (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer); + return writer; + } +} +/** + * @generated MessageType for protobuf message routerrpc.DeleteAliasesResponse + */ +export const DeleteAliasesResponse = new DeleteAliasesResponse$Type(); /** * @generated ServiceType for protobuf service routerrpc.Router */ @@ -3540,5 +4556,7 @@ export const Router = new ServiceType("routerrpc.Router", [ { name: "SendPayment", serverStreaming: true, options: {}, I: SendPaymentRequest, O: PaymentStatus }, { name: "TrackPayment", serverStreaming: true, options: {}, I: TrackPaymentRequest, O: PaymentStatus }, { name: "HtlcInterceptor", serverStreaming: true, clientStreaming: true, options: {}, I: ForwardHtlcInterceptResponse, O: ForwardHtlcInterceptRequest }, - { name: "UpdateChanStatus", options: {}, I: UpdateChanStatusRequest, O: UpdateChanStatusResponse } + { name: "UpdateChanStatus", options: {}, I: UpdateChanStatusRequest, O: UpdateChanStatusResponse }, + { name: "XAddLocalChanAliases", options: {}, I: AddAliasesRequest, O: AddAliasesResponse }, + { name: "XDeleteLocalChanAliases", options: {}, I: DeleteAliasesRequest, O: DeleteAliasesResponse } ]); diff --git a/proto/lnd/signer.client.ts b/proto/lnd/signer.client.ts index 8ce80d4c..6fc8ac0a 100644 --- a/proto/lnd/signer.client.ts +++ b/proto/lnd/signer.client.ts @@ -1,4 +1,4 @@ -// @generated by protobuf-ts 2.8.1 +// @generated by protobuf-ts 2.11.1 // @generated from protobuf file "signer.proto" (package "signrpc", syntax proto3) // tslint:disable import type { RpcTransport } from "@protobuf-ts/runtime-rpc"; @@ -46,7 +46,7 @@ export interface ISignerClient { * If we are unable to sign using the specified keys, then an error will be * returned. * - * @generated from protobuf rpc: SignOutputRaw(signrpc.SignReq) returns (signrpc.SignResp); + * @generated from protobuf rpc: SignOutputRaw */ signOutputRaw(input: SignReq, options?: RpcOptions): UnaryCall; /** @@ -62,7 +62,7 @@ export interface ISignerClient { * in the TxOut field, the value in that same field, and finally the input * index. * - * @generated from protobuf rpc: ComputeInputScript(signrpc.SignReq) returns (signrpc.InputScriptResp); + * @generated from protobuf rpc: ComputeInputScript */ computeInputScript(input: SignReq, options?: RpcOptions): UnaryCall; /** @@ -73,7 +73,7 @@ export interface ISignerClient { * The main difference to SignMessage in the main RPC is that a specific key is * used to sign the message instead of the node identity private key. * - * @generated from protobuf rpc: SignMessage(signrpc.SignMessageReq) returns (signrpc.SignMessageResp); + * @generated from protobuf rpc: SignMessage */ signMessage(input: SignMessageReq, options?: RpcOptions): UnaryCall; /** @@ -84,7 +84,7 @@ export interface ISignerClient { * The main difference to VerifyMessage in the main RPC is that the public key * used to sign the message does not have to be a node known to the network. * - * @generated from protobuf rpc: VerifyMessage(signrpc.VerifyMessageReq) returns (signrpc.VerifyMessageResp); + * @generated from protobuf rpc: VerifyMessage */ verifyMessage(input: VerifyMessageReq, options?: RpcOptions): UnaryCall; /** @@ -98,7 +98,7 @@ export interface ISignerClient { * The resulting shared public key is serialized in the compressed format and * hashed with sha256, resulting in the final key length of 256bit. * - * @generated from protobuf rpc: DeriveSharedKey(signrpc.SharedKeyRequest) returns (signrpc.SharedKeyResponse); + * @generated from protobuf rpc: DeriveSharedKey */ deriveSharedKey(input: SharedKeyRequest, options?: RpcOptions): UnaryCall; /** @@ -115,7 +115,7 @@ export interface ISignerClient { * considered to be HIGHLY EXPERIMENTAL and subject to change in upcoming * releases. Backward compatibility is not guaranteed! * - * @generated from protobuf rpc: MuSig2CombineKeys(signrpc.MuSig2CombineKeysRequest) returns (signrpc.MuSig2CombineKeysResponse); + * @generated from protobuf rpc: MuSig2CombineKeys */ muSig2CombineKeys(input: MuSig2CombineKeysRequest, options?: RpcOptions): UnaryCall; /** @@ -131,7 +131,7 @@ export interface ISignerClient { * considered to be HIGHLY EXPERIMENTAL and subject to change in upcoming * releases. Backward compatibility is not guaranteed! * - * @generated from protobuf rpc: MuSig2CreateSession(signrpc.MuSig2SessionRequest) returns (signrpc.MuSig2SessionResponse); + * @generated from protobuf rpc: MuSig2CreateSession */ muSig2CreateSession(input: MuSig2SessionRequest, options?: RpcOptions): UnaryCall; /** @@ -144,7 +144,7 @@ export interface ISignerClient { * considered to be HIGHLY EXPERIMENTAL and subject to change in upcoming * releases. Backward compatibility is not guaranteed! * - * @generated from protobuf rpc: MuSig2RegisterNonces(signrpc.MuSig2RegisterNoncesRequest) returns (signrpc.MuSig2RegisterNoncesResponse); + * @generated from protobuf rpc: MuSig2RegisterNonces */ muSig2RegisterNonces(input: MuSig2RegisterNoncesRequest, options?: RpcOptions): UnaryCall; /** @@ -160,7 +160,7 @@ export interface ISignerClient { * considered to be HIGHLY EXPERIMENTAL and subject to change in upcoming * releases. Backward compatibility is not guaranteed! * - * @generated from protobuf rpc: MuSig2Sign(signrpc.MuSig2SignRequest) returns (signrpc.MuSig2SignResponse); + * @generated from protobuf rpc: MuSig2Sign */ muSig2Sign(input: MuSig2SignRequest, options?: RpcOptions): UnaryCall; /** @@ -174,7 +174,7 @@ export interface ISignerClient { * considered to be HIGHLY EXPERIMENTAL and subject to change in upcoming * releases. Backward compatibility is not guaranteed! * - * @generated from protobuf rpc: MuSig2CombineSig(signrpc.MuSig2CombineSigRequest) returns (signrpc.MuSig2CombineSigResponse); + * @generated from protobuf rpc: MuSig2CombineSig */ muSig2CombineSig(input: MuSig2CombineSigRequest, options?: RpcOptions): UnaryCall; /** @@ -187,7 +187,7 @@ export interface ISignerClient { * considered to be HIGHLY EXPERIMENTAL and subject to change in upcoming * releases. Backward compatibility is not guaranteed! * - * @generated from protobuf rpc: MuSig2Cleanup(signrpc.MuSig2CleanupRequest) returns (signrpc.MuSig2CleanupResponse); + * @generated from protobuf rpc: MuSig2Cleanup */ muSig2Cleanup(input: MuSig2CleanupRequest, options?: RpcOptions): UnaryCall; } @@ -214,7 +214,7 @@ export class SignerClient implements ISignerClient, ServiceInfo { * If we are unable to sign using the specified keys, then an error will be * returned. * - * @generated from protobuf rpc: SignOutputRaw(signrpc.SignReq) returns (signrpc.SignResp); + * @generated from protobuf rpc: SignOutputRaw */ signOutputRaw(input: SignReq, options?: RpcOptions): UnaryCall { const method = this.methods[0], opt = this._transport.mergeOptions(options); @@ -233,7 +233,7 @@ export class SignerClient implements ISignerClient, ServiceInfo { * in the TxOut field, the value in that same field, and finally the input * index. * - * @generated from protobuf rpc: ComputeInputScript(signrpc.SignReq) returns (signrpc.InputScriptResp); + * @generated from protobuf rpc: ComputeInputScript */ computeInputScript(input: SignReq, options?: RpcOptions): UnaryCall { const method = this.methods[1], opt = this._transport.mergeOptions(options); @@ -247,7 +247,7 @@ export class SignerClient implements ISignerClient, ServiceInfo { * The main difference to SignMessage in the main RPC is that a specific key is * used to sign the message instead of the node identity private key. * - * @generated from protobuf rpc: SignMessage(signrpc.SignMessageReq) returns (signrpc.SignMessageResp); + * @generated from protobuf rpc: SignMessage */ signMessage(input: SignMessageReq, options?: RpcOptions): UnaryCall { const method = this.methods[2], opt = this._transport.mergeOptions(options); @@ -261,7 +261,7 @@ export class SignerClient implements ISignerClient, ServiceInfo { * The main difference to VerifyMessage in the main RPC is that the public key * used to sign the message does not have to be a node known to the network. * - * @generated from protobuf rpc: VerifyMessage(signrpc.VerifyMessageReq) returns (signrpc.VerifyMessageResp); + * @generated from protobuf rpc: VerifyMessage */ verifyMessage(input: VerifyMessageReq, options?: RpcOptions): UnaryCall { const method = this.methods[3], opt = this._transport.mergeOptions(options); @@ -278,7 +278,7 @@ export class SignerClient implements ISignerClient, ServiceInfo { * The resulting shared public key is serialized in the compressed format and * hashed with sha256, resulting in the final key length of 256bit. * - * @generated from protobuf rpc: DeriveSharedKey(signrpc.SharedKeyRequest) returns (signrpc.SharedKeyResponse); + * @generated from protobuf rpc: DeriveSharedKey */ deriveSharedKey(input: SharedKeyRequest, options?: RpcOptions): UnaryCall { const method = this.methods[4], opt = this._transport.mergeOptions(options); @@ -298,7 +298,7 @@ export class SignerClient implements ISignerClient, ServiceInfo { * considered to be HIGHLY EXPERIMENTAL and subject to change in upcoming * releases. Backward compatibility is not guaranteed! * - * @generated from protobuf rpc: MuSig2CombineKeys(signrpc.MuSig2CombineKeysRequest) returns (signrpc.MuSig2CombineKeysResponse); + * @generated from protobuf rpc: MuSig2CombineKeys */ muSig2CombineKeys(input: MuSig2CombineKeysRequest, options?: RpcOptions): UnaryCall { const method = this.methods[5], opt = this._transport.mergeOptions(options); @@ -317,7 +317,7 @@ export class SignerClient implements ISignerClient, ServiceInfo { * considered to be HIGHLY EXPERIMENTAL and subject to change in upcoming * releases. Backward compatibility is not guaranteed! * - * @generated from protobuf rpc: MuSig2CreateSession(signrpc.MuSig2SessionRequest) returns (signrpc.MuSig2SessionResponse); + * @generated from protobuf rpc: MuSig2CreateSession */ muSig2CreateSession(input: MuSig2SessionRequest, options?: RpcOptions): UnaryCall { const method = this.methods[6], opt = this._transport.mergeOptions(options); @@ -333,7 +333,7 @@ export class SignerClient implements ISignerClient, ServiceInfo { * considered to be HIGHLY EXPERIMENTAL and subject to change in upcoming * releases. Backward compatibility is not guaranteed! * - * @generated from protobuf rpc: MuSig2RegisterNonces(signrpc.MuSig2RegisterNoncesRequest) returns (signrpc.MuSig2RegisterNoncesResponse); + * @generated from protobuf rpc: MuSig2RegisterNonces */ muSig2RegisterNonces(input: MuSig2RegisterNoncesRequest, options?: RpcOptions): UnaryCall { const method = this.methods[7], opt = this._transport.mergeOptions(options); @@ -352,7 +352,7 @@ export class SignerClient implements ISignerClient, ServiceInfo { * considered to be HIGHLY EXPERIMENTAL and subject to change in upcoming * releases. Backward compatibility is not guaranteed! * - * @generated from protobuf rpc: MuSig2Sign(signrpc.MuSig2SignRequest) returns (signrpc.MuSig2SignResponse); + * @generated from protobuf rpc: MuSig2Sign */ muSig2Sign(input: MuSig2SignRequest, options?: RpcOptions): UnaryCall { const method = this.methods[8], opt = this._transport.mergeOptions(options); @@ -369,7 +369,7 @@ export class SignerClient implements ISignerClient, ServiceInfo { * considered to be HIGHLY EXPERIMENTAL and subject to change in upcoming * releases. Backward compatibility is not guaranteed! * - * @generated from protobuf rpc: MuSig2CombineSig(signrpc.MuSig2CombineSigRequest) returns (signrpc.MuSig2CombineSigResponse); + * @generated from protobuf rpc: MuSig2CombineSig */ muSig2CombineSig(input: MuSig2CombineSigRequest, options?: RpcOptions): UnaryCall { const method = this.methods[9], opt = this._transport.mergeOptions(options); @@ -385,7 +385,7 @@ export class SignerClient implements ISignerClient, ServiceInfo { * considered to be HIGHLY EXPERIMENTAL and subject to change in upcoming * releases. Backward compatibility is not guaranteed! * - * @generated from protobuf rpc: MuSig2Cleanup(signrpc.MuSig2CleanupRequest) returns (signrpc.MuSig2CleanupResponse); + * @generated from protobuf rpc: MuSig2Cleanup */ muSig2Cleanup(input: MuSig2CleanupRequest, options?: RpcOptions): UnaryCall { const method = this.methods[10], opt = this._transport.mergeOptions(options); diff --git a/proto/lnd/signer.ts b/proto/lnd/signer.ts index cf9cf1d4..2b55dc9f 100644 --- a/proto/lnd/signer.ts +++ b/proto/lnd/signer.ts @@ -1,4 +1,4 @@ -// @generated by protobuf-ts 2.8.1 +// @generated by protobuf-ts 2.11.1 // @generated from protobuf file "signer.proto" (package "signrpc", syntax proto3) // tslint:disable import { ServiceType } from "@protobuf-ts/runtime-rpc"; @@ -10,7 +10,6 @@ import type { IBinaryReader } from "@protobuf-ts/runtime"; import { UnknownFieldHandler } from "@protobuf-ts/runtime"; import type { PartialMessage } from "@protobuf-ts/runtime"; import { reflectionMergePartial } from "@protobuf-ts/runtime"; -import { MESSAGE_TYPE } from "@protobuf-ts/runtime"; import { MessageType } from "@protobuf-ts/runtime"; /** * @generated from protobuf message signrpc.KeyLocator @@ -19,13 +18,13 @@ export interface KeyLocator { /** * The family of key being identified. * - * @generated from protobuf field: int32 key_family = 1; + * @generated from protobuf field: int32 key_family = 1 */ keyFamily: number; /** * The precise index of the key being identified. * - * @generated from protobuf field: int32 key_index = 2; + * @generated from protobuf field: int32 key_index = 2 */ keyIndex: number; } @@ -38,7 +37,7 @@ export interface KeyDescriptor { * The raw bytes of the public key in the key pair being identified. Either * this or the KeyLocator must be specified. * - * @generated from protobuf field: bytes raw_key_bytes = 1; + * @generated from protobuf field: bytes raw_key_bytes = 1 */ rawKeyBytes: Uint8Array; /** @@ -46,7 +45,7 @@ export interface KeyDescriptor { * The key locator that identifies which private key to use for signing. * Either this or the raw bytes of the target public key must be specified. * - * @generated from protobuf field: signrpc.KeyLocator key_loc = 2; + * @generated from protobuf field: signrpc.KeyLocator key_loc = 2 */ keyLoc?: KeyLocator; } @@ -57,13 +56,13 @@ export interface TxOut { /** * The value of the output being spent. * - * @generated from protobuf field: int64 value = 1; + * @generated from protobuf field: int64 value = 1 */ value: bigint; /** * The script of the output being spent. * - * @generated from protobuf field: bytes pk_script = 2; + * @generated from protobuf field: bytes pk_script = 2 */ pkScript: Uint8Array; } @@ -81,7 +80,7 @@ export interface SignDescriptor { * then the key locator MUST always be provided, since the derived keys are not * persisted unlike with DeriveNextKey. * - * @generated from protobuf field: signrpc.KeyDescriptor key_desc = 1; + * @generated from protobuf field: signrpc.KeyDescriptor key_desc = 1 */ keyDesc?: KeyDescriptor; /** @@ -92,7 +91,7 @@ export interface SignDescriptor { * * derivedKey = privkey + sha256(perCommitmentPoint || pubKey) mod N * - * @generated from protobuf field: bytes single_tweak = 2; + * @generated from protobuf field: bytes single_tweak = 2 */ singleTweak: Uint8Array; /** @@ -107,7 +106,7 @@ export interface SignDescriptor { * k = (privKey*sha256(pubKey || tweakPub) + * tweakPriv*sha256(tweakPub || pubKey)) mod N * - * @generated from protobuf field: bytes double_tweak = 3; + * @generated from protobuf field: bytes double_tweak = 3 */ doubleTweak: Uint8Array; /** @@ -121,7 +120,7 @@ export interface SignDescriptor { * When doing a normal key path spend, with the output key committing to an * actual script root, then this field should be: the tapscript root hash. * - * @generated from protobuf field: bytes tap_tweak = 10; + * @generated from protobuf field: bytes tap_tweak = 10 */ tapTweak: Uint8Array; /** @@ -131,7 +130,7 @@ export interface SignDescriptor { * taproot script path spend is being attempted, then this should be the raw * leaf script. * - * @generated from protobuf field: bytes witness_script = 4; + * @generated from protobuf field: bytes witness_script = 4 */ witnessScript: Uint8Array; /** @@ -139,7 +138,7 @@ export interface SignDescriptor { * A description of the output being spent. The value and script MUST be * provided. * - * @generated from protobuf field: signrpc.TxOut output = 5; + * @generated from protobuf field: signrpc.TxOut output = 5 */ output?: TxOut; /** @@ -147,14 +146,14 @@ export interface SignDescriptor { * The target sighash type that should be used when generating the final * sighash, and signature. * - * @generated from protobuf field: uint32 sighash = 7; + * @generated from protobuf field: uint32 sighash = 7 */ sighash: number; /** * * The target input within the transaction that should be signed. * - * @generated from protobuf field: int32 input_index = 8; + * @generated from protobuf field: int32 input_index = 8 */ inputIndex: number; /** @@ -164,7 +163,7 @@ export interface SignDescriptor { * Defaults to SegWit v0 signing to be backward compatible with older RPC * clients. * - * @generated from protobuf field: signrpc.SignMethod sign_method = 9; + * @generated from protobuf field: signrpc.SignMethod sign_method = 9 */ signMethod: SignMethod; } @@ -175,13 +174,13 @@ export interface SignReq { /** * The raw bytes of the transaction to be signed. * - * @generated from protobuf field: bytes raw_tx_bytes = 1; + * @generated from protobuf field: bytes raw_tx_bytes = 1 */ rawTxBytes: Uint8Array; /** * A set of sign descriptors, for each input to be signed. * - * @generated from protobuf field: repeated signrpc.SignDescriptor sign_descs = 2; + * @generated from protobuf field: repeated signrpc.SignDescriptor sign_descs = 2 */ signDescs: SignDescriptor[]; /** @@ -189,7 +188,7 @@ export interface SignReq { * The full list of UTXO information for each of the inputs being spent. This * is required when spending one or more taproot (SegWit v1) outputs. * - * @generated from protobuf field: repeated signrpc.TxOut prev_outputs = 3; + * @generated from protobuf field: repeated signrpc.TxOut prev_outputs = 3 */ prevOutputs: TxOut[]; } @@ -202,7 +201,7 @@ export interface SignResp { * A set of signatures realized in a fixed 64-byte format ordered in ascending * input order. * - * @generated from protobuf field: repeated bytes raw_sigs = 1; + * @generated from protobuf field: repeated bytes raw_sigs = 1 */ rawSigs: Uint8Array[]; } @@ -213,7 +212,7 @@ export interface InputScript { /** * The serializes witness stack for the specified input. * - * @generated from protobuf field: repeated bytes witness = 1; + * @generated from protobuf field: repeated bytes witness = 1 */ witness: Uint8Array[]; /** @@ -221,7 +220,7 @@ export interface InputScript { * The optional sig script for the specified witness that will only be set if * the input specified is a nested p2sh witness program. * - * @generated from protobuf field: bytes sig_script = 2; + * @generated from protobuf field: bytes sig_script = 2 */ sigScript: Uint8Array; } @@ -232,7 +231,7 @@ export interface InputScriptResp { /** * The set of fully valid input scripts requested. * - * @generated from protobuf field: repeated signrpc.InputScript input_scripts = 1; + * @generated from protobuf field: repeated signrpc.InputScript input_scripts = 1 */ inputScripts: InputScript[]; } @@ -245,19 +244,19 @@ export interface SignMessageReq { * The message to be signed. When using REST, this field must be encoded as * base64. * - * @generated from protobuf field: bytes msg = 1; + * @generated from protobuf field: bytes msg = 1 */ msg: Uint8Array; /** * The key locator that identifies which key to use for signing. * - * @generated from protobuf field: signrpc.KeyLocator key_loc = 2; + * @generated from protobuf field: signrpc.KeyLocator key_loc = 2 */ keyLoc?: KeyLocator; /** * Double-SHA256 hash instead of just the default single round. * - * @generated from protobuf field: bool double_hash = 3; + * @generated from protobuf field: bool double_hash = 3 */ doubleHash: boolean; /** @@ -265,14 +264,14 @@ export interface SignMessageReq { * Use the compact (pubkey recoverable) format instead of the raw lnwire * format. This option cannot be used with Schnorr signatures. * - * @generated from protobuf field: bool compact_sig = 4; + * @generated from protobuf field: bool compact_sig = 4 */ compactSig: boolean; /** * * Use Schnorr signature. This option cannot be used with compact format. * - * @generated from protobuf field: bool schnorr_sig = 5; + * @generated from protobuf field: bool schnorr_sig = 5 */ schnorrSig: boolean; /** @@ -281,7 +280,7 @@ export interface SignMessageReq { * a Schnorr signature. The private key is tweaked as described in BIP-341: * privKey + h_tapTweak(internalKey || tapTweak) * - * @generated from protobuf field: bytes schnorr_sig_tap_tweak = 6; + * @generated from protobuf field: bytes schnorr_sig_tap_tweak = 6 */ schnorrSigTapTweak: Uint8Array; /** @@ -289,7 +288,7 @@ export interface SignMessageReq { * An optional tag that can be provided when taking a tagged hash of a * message. This option can only be used when schnorr_sig is true. * - * @generated from protobuf field: bytes tag = 7; + * @generated from protobuf field: bytes tag = 7 */ tag: Uint8Array; } @@ -301,7 +300,7 @@ export interface SignMessageResp { * * The signature for the given message in the fixed-size LN wire format. * - * @generated from protobuf field: bytes signature = 1; + * @generated from protobuf field: bytes signature = 1 */ signature: Uint8Array; } @@ -313,7 +312,7 @@ export interface VerifyMessageReq { * The message over which the signature is to be verified. When using * REST, this field must be encoded as base64. * - * @generated from protobuf field: bytes msg = 1; + * @generated from protobuf field: bytes msg = 1 */ msg: Uint8Array; /** @@ -321,7 +320,7 @@ export interface VerifyMessageReq { * The fixed-size LN wire encoded signature to be verified over the given * message. When using REST, this field must be encoded as base64. * - * @generated from protobuf field: bytes signature = 2; + * @generated from protobuf field: bytes signature = 2 */ signature: Uint8Array; /** @@ -331,14 +330,14 @@ export interface VerifyMessageReq { * the public key is expected to be in the 32-byte x-only serialization * according to BIP-340. * - * @generated from protobuf field: bytes pubkey = 3; + * @generated from protobuf field: bytes pubkey = 3 */ pubkey: Uint8Array; /** * * Specifies if the signature is a Schnorr signature. * - * @generated from protobuf field: bool is_schnorr_sig = 4; + * @generated from protobuf field: bool is_schnorr_sig = 4 */ isSchnorrSig: boolean; /** @@ -346,7 +345,7 @@ export interface VerifyMessageReq { * An optional tag that can be provided when taking a tagged hash of a * message. This option can only be used when is_schnorr_sig is true. * - * @generated from protobuf field: bytes tag = 5; + * @generated from protobuf field: bytes tag = 5 */ tag: Uint8Array; } @@ -357,7 +356,7 @@ export interface VerifyMessageResp { /** * Whether the signature was valid over the given message. * - * @generated from protobuf field: bool valid = 1; + * @generated from protobuf field: bool valid = 1 */ valid: boolean; } @@ -368,7 +367,7 @@ export interface SharedKeyRequest { /** * The ephemeral public key to use for the DH key derivation. * - * @generated from protobuf field: bytes ephemeral_pubkey = 1; + * @generated from protobuf field: bytes ephemeral_pubkey = 1 */ ephemeralPubkey: Uint8Array; /** @@ -378,7 +377,7 @@ export interface SharedKeyRequest { * used. * * @deprecated - * @generated from protobuf field: signrpc.KeyLocator key_loc = 2 [deprecated = true]; + * @generated from protobuf field: signrpc.KeyLocator key_loc = 2 [deprecated = true] */ keyLoc?: KeyLocator; /** @@ -387,7 +386,7 @@ export interface SharedKeyRequest { * locator or a raw public key is expected, if neither is supplied, defaults to * the node's identity private key. * - * @generated from protobuf field: signrpc.KeyDescriptor key_desc = 3; + * @generated from protobuf field: signrpc.KeyDescriptor key_desc = 3 */ keyDesc?: KeyDescriptor; } @@ -398,7 +397,7 @@ export interface SharedKeyResponse { /** * The shared public key, hashed with sha256. * - * @generated from protobuf field: bytes shared_key = 1; + * @generated from protobuf field: bytes shared_key = 1 */ sharedKey: Uint8Array; } @@ -410,7 +409,7 @@ export interface TweakDesc { * * Tweak is the 32-byte value that will modify the public key. * - * @generated from protobuf field: bytes tweak = 1; + * @generated from protobuf field: bytes tweak = 1 */ tweak: Uint8Array; /** @@ -419,7 +418,7 @@ export interface TweakDesc { * before tweaking. If true, then the public key will be mapped to an x-only * key before the tweaking operation is applied. * - * @generated from protobuf field: bool is_x_only = 2; + * @generated from protobuf field: bool is_x_only = 2 */ isXOnly: boolean; } @@ -436,7 +435,7 @@ export interface TaprootTweakDesc { * differentiate between a zero-size byte slice and a nil byte slice (both * would be serialized the same way). So the extra boolean is required. * - * @generated from protobuf field: bytes script_root = 1; + * @generated from protobuf field: bytes script_root = 1 */ scriptRoot: Uint8Array; /** @@ -445,7 +444,7 @@ export interface TaprootTweakDesc { * is a BIP-0086 key spend only commitment where only the internal key is * committed to instead of also including a script root hash. * - * @generated from protobuf field: bool key_spend_only = 2; + * @generated from protobuf field: bool key_spend_only = 2 */ keySpendOnly: boolean; } @@ -460,7 +459,7 @@ export interface MuSig2CombineKeysRequest { * session. The list will always be sorted lexicographically internally. This * must include the local key which is described by the above key_loc. * - * @generated from protobuf field: repeated bytes all_signer_pubkeys = 1; + * @generated from protobuf field: repeated bytes all_signer_pubkeys = 1 */ allSignerPubkeys: Uint8Array[]; /** @@ -468,7 +467,7 @@ export interface MuSig2CombineKeysRequest { * A series of optional generic tweaks to be applied to the aggregated * public key. * - * @generated from protobuf field: repeated signrpc.TweakDesc tweaks = 2; + * @generated from protobuf field: repeated signrpc.TweakDesc tweaks = 2 */ tweaks: TweakDesc[]; /** @@ -477,7 +476,7 @@ export interface MuSig2CombineKeysRequest { * combined key will be used as the main taproot key of a taproot output * on-chain. * - * @generated from protobuf field: signrpc.TaprootTweakDesc taproot_tweak = 3; + * @generated from protobuf field: signrpc.TaprootTweakDesc taproot_tweak = 3 */ taprootTweak?: TaprootTweakDesc; /** @@ -487,7 +486,7 @@ export interface MuSig2CombineKeysRequest { * experimental RPC was already released. Some of those changes affect how the * combined key and nonces are created. * - * @generated from protobuf field: signrpc.MuSig2Version version = 4; + * @generated from protobuf field: signrpc.MuSig2Version version = 4 */ version: MuSig2Version; } @@ -501,7 +500,7 @@ export interface MuSig2CombineKeysResponse { * applied to it. If a taproot tweak is specified, this corresponds to the * taproot key that can be put into the on-chain output. * - * @generated from protobuf field: bytes combined_key = 1; + * @generated from protobuf field: bytes combined_key = 1 */ combinedKey: Uint8Array; /** @@ -511,14 +510,14 @@ export interface MuSig2CombineKeysResponse { * internal key that needs to be put into the witness if the script spend path * is used. * - * @generated from protobuf field: bytes taproot_internal_key = 2; + * @generated from protobuf field: bytes taproot_internal_key = 2 */ taprootInternalKey: Uint8Array; /** * * The version of the MuSig2 BIP that was used to combine the keys. * - * @generated from protobuf field: signrpc.MuSig2Version version = 4; + * @generated from protobuf field: signrpc.MuSig2Version version = 4 */ version: MuSig2Version; } @@ -530,7 +529,7 @@ export interface MuSig2SessionRequest { * * The key locator that identifies which key to use for signing. * - * @generated from protobuf field: signrpc.KeyLocator key_loc = 1; + * @generated from protobuf field: signrpc.KeyLocator key_loc = 1 */ keyLoc?: KeyLocator; /** @@ -540,7 +539,7 @@ export interface MuSig2SessionRequest { * session. The list will always be sorted lexicographically internally. This * must include the local key which is described by the above key_loc. * - * @generated from protobuf field: repeated bytes all_signer_pubkeys = 2; + * @generated from protobuf field: repeated bytes all_signer_pubkeys = 2 */ allSignerPubkeys: Uint8Array[]; /** @@ -548,7 +547,7 @@ export interface MuSig2SessionRequest { * An optional list of all public nonces of other signing participants that * might already be known. * - * @generated from protobuf field: repeated bytes other_signer_public_nonces = 3; + * @generated from protobuf field: repeated bytes other_signer_public_nonces = 3 */ otherSignerPublicNonces: Uint8Array[]; /** @@ -556,7 +555,7 @@ export interface MuSig2SessionRequest { * A series of optional generic tweaks to be applied to the aggregated * public key. * - * @generated from protobuf field: repeated signrpc.TweakDesc tweaks = 4; + * @generated from protobuf field: repeated signrpc.TweakDesc tweaks = 4 */ tweaks: TweakDesc[]; /** @@ -565,7 +564,7 @@ export interface MuSig2SessionRequest { * combined key will be used as the main taproot key of a taproot output * on-chain. * - * @generated from protobuf field: signrpc.TaprootTweakDesc taproot_tweak = 5; + * @generated from protobuf field: signrpc.TaprootTweakDesc taproot_tweak = 5 */ taprootTweak?: TaprootTweakDesc; /** @@ -575,7 +574,7 @@ export interface MuSig2SessionRequest { * experimental RPC was already released. Some of those changes affect how the * combined key and nonces are created. * - * @generated from protobuf field: signrpc.MuSig2Version version = 6; + * @generated from protobuf field: signrpc.MuSig2Version version = 6 */ version: MuSig2Version; /** @@ -587,7 +586,7 @@ export interface MuSig2SessionRequest { * values and local public key used for signing as specified in the key_loc * field. * - * @generated from protobuf field: bytes pregenerated_local_nonce = 7; + * @generated from protobuf field: bytes pregenerated_local_nonce = 7 */ pregeneratedLocalNonce: Uint8Array; } @@ -601,7 +600,7 @@ export interface MuSig2SessionResponse { * for producing a signature a single time. If the signing fails for any * reason, a new session with the same participants needs to be created. * - * @generated from protobuf field: bytes session_id = 1; + * @generated from protobuf field: bytes session_id = 1 */ sessionId: Uint8Array; /** @@ -610,7 +609,7 @@ export interface MuSig2SessionResponse { * applied to it. If a taproot tweak is specified, this corresponds to the * taproot key that can be put into the on-chain output. * - * @generated from protobuf field: bytes combined_key = 2; + * @generated from protobuf field: bytes combined_key = 2 */ combinedKey: Uint8Array; /** @@ -620,7 +619,7 @@ export interface MuSig2SessionResponse { * internal key that needs to be put into the witness if the script spend path * is used. * - * @generated from protobuf field: bytes taproot_internal_key = 3; + * @generated from protobuf field: bytes taproot_internal_key = 3 */ taprootInternalKey: Uint8Array; /** @@ -629,7 +628,7 @@ export interface MuSig2SessionResponse { * of 66 bytes. Can be split into the two 33-byte points to get the individual * nonces. * - * @generated from protobuf field: bytes local_public_nonces = 4; + * @generated from protobuf field: bytes local_public_nonces = 4 */ localPublicNonces: Uint8Array; /** @@ -637,14 +636,14 @@ export interface MuSig2SessionResponse { * Indicates whether all nonces required to start the signing process are known * now. * - * @generated from protobuf field: bool have_all_nonces = 5; + * @generated from protobuf field: bool have_all_nonces = 5 */ haveAllNonces: boolean; /** * * The version of the MuSig2 BIP that was used to create the session. * - * @generated from protobuf field: signrpc.MuSig2Version version = 6; + * @generated from protobuf field: signrpc.MuSig2Version version = 6 */ version: MuSig2Version; } @@ -656,7 +655,7 @@ export interface MuSig2RegisterNoncesRequest { * * The unique ID of the signing session those nonces should be registered with. * - * @generated from protobuf field: bytes session_id = 1; + * @generated from protobuf field: bytes session_id = 1 */ sessionId: Uint8Array; /** @@ -664,7 +663,7 @@ export interface MuSig2RegisterNoncesRequest { * A list of all public nonces of other signing participants that should be * registered. * - * @generated from protobuf field: repeated bytes other_signer_public_nonces = 3; + * @generated from protobuf field: repeated bytes other_signer_public_nonces = 3 */ otherSignerPublicNonces: Uint8Array[]; } @@ -677,7 +676,7 @@ export interface MuSig2RegisterNoncesResponse { * Indicates whether all nonces required to start the signing process are known * now. * - * @generated from protobuf field: bool have_all_nonces = 1; + * @generated from protobuf field: bool have_all_nonces = 1 */ haveAllNonces: boolean; } @@ -689,14 +688,14 @@ export interface MuSig2SignRequest { * * The unique ID of the signing session to use for signing. * - * @generated from protobuf field: bytes session_id = 1; + * @generated from protobuf field: bytes session_id = 1 */ sessionId: Uint8Array; /** * * The 32-byte SHA256 digest of the message to sign. * - * @generated from protobuf field: bytes message_digest = 2; + * @generated from protobuf field: bytes message_digest = 2 */ messageDigest: Uint8Array; /** @@ -705,7 +704,7 @@ export interface MuSig2SignRequest { * since another participant is going to be responsible for combining the * partial signatures. * - * @generated from protobuf field: bool cleanup = 3; + * @generated from protobuf field: bool cleanup = 3 */ cleanup: boolean; } @@ -717,7 +716,7 @@ export interface MuSig2SignResponse { * * The partial signature created by the local signer. * - * @generated from protobuf field: bytes local_partial_signature = 1; + * @generated from protobuf field: bytes local_partial_signature = 1 */ localPartialSignature: Uint8Array; } @@ -729,7 +728,7 @@ export interface MuSig2CombineSigRequest { * * The unique ID of the signing session to combine the signatures for. * - * @generated from protobuf field: bytes session_id = 1; + * @generated from protobuf field: bytes session_id = 1 */ sessionId: Uint8Array; /** @@ -737,7 +736,7 @@ export interface MuSig2CombineSigRequest { * The list of all other participants' partial signatures to add to the current * session. * - * @generated from protobuf field: repeated bytes other_partial_signatures = 2; + * @generated from protobuf field: repeated bytes other_partial_signatures = 2 */ otherPartialSignatures: Uint8Array[]; } @@ -751,14 +750,14 @@ export interface MuSig2CombineSigResponse { * signature are known yet. If this is true, then the final_signature field is * set, otherwise it is empty. * - * @generated from protobuf field: bool have_all_signatures = 1; + * @generated from protobuf field: bool have_all_signatures = 1 */ haveAllSignatures: boolean; /** * * The final, full signature that is valid for the combined public key. * - * @generated from protobuf field: bytes final_signature = 2; + * @generated from protobuf field: bytes final_signature = 2 */ finalSignature: Uint8Array; } @@ -770,7 +769,7 @@ export interface MuSig2CleanupRequest { * * The unique ID of the signing session that should be removed/cleaned up. * - * @generated from protobuf field: bytes session_id = 1; + * @generated from protobuf field: bytes session_id = 1 */ sessionId: Uint8Array; } @@ -855,8 +854,9 @@ class KeyLocator$Type extends MessageType { ]); } create(value?: PartialMessage): KeyLocator { - const message = { keyFamily: 0, keyIndex: 0 }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.keyFamily = 0; + message.keyIndex = 0; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -909,8 +909,8 @@ class KeyDescriptor$Type extends MessageType { ]); } create(value?: PartialMessage): KeyDescriptor { - const message = { rawKeyBytes: new Uint8Array(0) }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.rawKeyBytes = new Uint8Array(0); if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -963,8 +963,9 @@ class TxOut$Type extends MessageType { ]); } create(value?: PartialMessage): TxOut { - const message = { value: 0n, pkScript: new Uint8Array(0) }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.value = 0n; + message.pkScript = new Uint8Array(0); if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -1024,8 +1025,14 @@ class SignDescriptor$Type extends MessageType { ]); } create(value?: PartialMessage): SignDescriptor { - const message = { singleTweak: new Uint8Array(0), doubleTweak: new Uint8Array(0), tapTweak: new Uint8Array(0), witnessScript: new Uint8Array(0), sighash: 0, inputIndex: 0, signMethod: 0 }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.singleTweak = new Uint8Array(0); + message.doubleTweak = new Uint8Array(0); + message.tapTweak = new Uint8Array(0); + message.witnessScript = new Uint8Array(0); + message.sighash = 0; + message.inputIndex = 0; + message.signMethod = 0; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -1083,9 +1090,6 @@ class SignDescriptor$Type extends MessageType { /* bytes double_tweak = 3; */ if (message.doubleTweak.length) writer.tag(3, WireType.LengthDelimited).bytes(message.doubleTweak); - /* bytes tap_tweak = 10; */ - if (message.tapTweak.length) - writer.tag(10, WireType.LengthDelimited).bytes(message.tapTweak); /* bytes witness_script = 4; */ if (message.witnessScript.length) writer.tag(4, WireType.LengthDelimited).bytes(message.witnessScript); @@ -1101,6 +1105,9 @@ class SignDescriptor$Type extends MessageType { /* signrpc.SignMethod sign_method = 9; */ if (message.signMethod !== 0) writer.tag(9, WireType.Varint).int32(message.signMethod); + /* bytes tap_tweak = 10; */ + if (message.tapTweak.length) + writer.tag(10, WireType.LengthDelimited).bytes(message.tapTweak); let u = options.writeUnknownFields; if (u !== false) (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer); @@ -1116,13 +1123,15 @@ class SignReq$Type extends MessageType { constructor() { super("signrpc.SignReq", [ { no: 1, name: "raw_tx_bytes", kind: "scalar", T: 12 /*ScalarType.BYTES*/ }, - { no: 2, name: "sign_descs", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => SignDescriptor }, - { no: 3, name: "prev_outputs", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => TxOut } + { no: 2, name: "sign_descs", kind: "message", repeat: 2 /*RepeatType.UNPACKED*/, T: () => SignDescriptor }, + { no: 3, name: "prev_outputs", kind: "message", repeat: 2 /*RepeatType.UNPACKED*/, T: () => TxOut } ]); } create(value?: PartialMessage): SignReq { - const message = { rawTxBytes: new Uint8Array(0), signDescs: [], prevOutputs: [] }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.rawTxBytes = new Uint8Array(0); + message.signDescs = []; + message.prevOutputs = []; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -1180,8 +1189,8 @@ class SignResp$Type extends MessageType { ]); } create(value?: PartialMessage): SignResp { - const message = { rawSigs: [] }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.rawSigs = []; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -1228,8 +1237,9 @@ class InputScript$Type extends MessageType { ]); } create(value?: PartialMessage): InputScript { - const message = { witness: [], sigScript: new Uint8Array(0) }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.witness = []; + message.sigScript = new Uint8Array(0); if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -1277,12 +1287,12 @@ export const InputScript = new InputScript$Type(); class InputScriptResp$Type extends MessageType { constructor() { super("signrpc.InputScriptResp", [ - { no: 1, name: "input_scripts", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => InputScript } + { no: 1, name: "input_scripts", kind: "message", repeat: 2 /*RepeatType.UNPACKED*/, T: () => InputScript } ]); } create(value?: PartialMessage): InputScriptResp { - const message = { inputScripts: [] }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.inputScripts = []; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -1334,8 +1344,13 @@ class SignMessageReq$Type extends MessageType { ]); } create(value?: PartialMessage): SignMessageReq { - const message = { msg: new Uint8Array(0), doubleHash: false, compactSig: false, schnorrSig: false, schnorrSigTapTweak: new Uint8Array(0), tag: new Uint8Array(0) }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.msg = new Uint8Array(0); + message.doubleHash = false; + message.compactSig = false; + message.schnorrSig = false; + message.schnorrSigTapTweak = new Uint8Array(0); + message.tag = new Uint8Array(0); if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -1417,8 +1432,8 @@ class SignMessageResp$Type extends MessageType { ]); } create(value?: PartialMessage): SignMessageResp { - const message = { signature: new Uint8Array(0) }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.signature = new Uint8Array(0); if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -1468,8 +1483,12 @@ class VerifyMessageReq$Type extends MessageType { ]); } create(value?: PartialMessage): VerifyMessageReq { - const message = { msg: new Uint8Array(0), signature: new Uint8Array(0), pubkey: new Uint8Array(0), isSchnorrSig: false, tag: new Uint8Array(0) }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.msg = new Uint8Array(0); + message.signature = new Uint8Array(0); + message.pubkey = new Uint8Array(0); + message.isSchnorrSig = false; + message.tag = new Uint8Array(0); if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -1539,8 +1558,8 @@ class VerifyMessageResp$Type extends MessageType { ]); } create(value?: PartialMessage): VerifyMessageResp { - const message = { valid: false }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.valid = false; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -1588,8 +1607,8 @@ class SharedKeyRequest$Type extends MessageType { ]); } create(value?: PartialMessage): SharedKeyRequest { - const message = { ephemeralPubkey: new Uint8Array(0) }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.ephemeralPubkey = new Uint8Array(0); if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -1602,7 +1621,7 @@ class SharedKeyRequest$Type extends MessageType { case /* bytes ephemeral_pubkey */ 1: message.ephemeralPubkey = reader.bytes(); break; - case /* signrpc.KeyLocator key_loc = 2 [deprecated = true];*/ 2: + case /* signrpc.KeyLocator key_loc = 2 [deprecated = true] */ 2: message.keyLoc = KeyLocator.internalBinaryRead(reader, reader.uint32(), options, message.keyLoc); break; case /* signrpc.KeyDescriptor key_desc */ 3: @@ -1647,8 +1666,8 @@ class SharedKeyResponse$Type extends MessageType { ]); } create(value?: PartialMessage): SharedKeyResponse { - const message = { sharedKey: new Uint8Array(0) }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.sharedKey = new Uint8Array(0); if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -1695,8 +1714,9 @@ class TweakDesc$Type extends MessageType { ]); } create(value?: PartialMessage): TweakDesc { - const message = { tweak: new Uint8Array(0), isXOnly: false }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.tweak = new Uint8Array(0); + message.isXOnly = false; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -1749,8 +1769,9 @@ class TaprootTweakDesc$Type extends MessageType { ]); } create(value?: PartialMessage): TaprootTweakDesc { - const message = { scriptRoot: new Uint8Array(0), keySpendOnly: false }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.scriptRoot = new Uint8Array(0); + message.keySpendOnly = false; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -1799,14 +1820,16 @@ class MuSig2CombineKeysRequest$Type extends MessageType TweakDesc }, + { no: 2, name: "tweaks", kind: "message", repeat: 2 /*RepeatType.UNPACKED*/, T: () => TweakDesc }, { no: 3, name: "taproot_tweak", kind: "message", T: () => TaprootTweakDesc }, { no: 4, name: "version", kind: "enum", T: () => ["signrpc.MuSig2Version", MuSig2Version] } ]); } create(value?: PartialMessage): MuSig2CombineKeysRequest { - const message = { allSignerPubkeys: [], tweaks: [], version: 0 }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.allSignerPubkeys = []; + message.tweaks = []; + message.version = 0; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -1872,8 +1895,10 @@ class MuSig2CombineKeysResponse$Type extends MessageType): MuSig2CombineKeysResponse { - const message = { combinedKey: new Uint8Array(0), taprootInternalKey: new Uint8Array(0), version: 0 }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.combinedKey = new Uint8Array(0); + message.taprootInternalKey = new Uint8Array(0); + message.version = 0; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -1930,15 +1955,19 @@ class MuSig2SessionRequest$Type extends MessageType { { no: 1, name: "key_loc", kind: "message", T: () => KeyLocator }, { no: 2, name: "all_signer_pubkeys", kind: "scalar", repeat: 2 /*RepeatType.UNPACKED*/, T: 12 /*ScalarType.BYTES*/ }, { no: 3, name: "other_signer_public_nonces", kind: "scalar", repeat: 2 /*RepeatType.UNPACKED*/, T: 12 /*ScalarType.BYTES*/ }, - { no: 4, name: "tweaks", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => TweakDesc }, + { no: 4, name: "tweaks", kind: "message", repeat: 2 /*RepeatType.UNPACKED*/, T: () => TweakDesc }, { no: 5, name: "taproot_tweak", kind: "message", T: () => TaprootTweakDesc }, { no: 6, name: "version", kind: "enum", T: () => ["signrpc.MuSig2Version", MuSig2Version] }, { no: 7, name: "pregenerated_local_nonce", kind: "scalar", T: 12 /*ScalarType.BYTES*/ } ]); } create(value?: PartialMessage): MuSig2SessionRequest { - const message = { allSignerPubkeys: [], otherSignerPublicNonces: [], tweaks: [], version: 0, pregeneratedLocalNonce: new Uint8Array(0) }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.allSignerPubkeys = []; + message.otherSignerPublicNonces = []; + message.tweaks = []; + message.version = 0; + message.pregeneratedLocalNonce = new Uint8Array(0); if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -2025,8 +2054,13 @@ class MuSig2SessionResponse$Type extends MessageType { ]); } create(value?: PartialMessage): MuSig2SessionResponse { - const message = { sessionId: new Uint8Array(0), combinedKey: new Uint8Array(0), taprootInternalKey: new Uint8Array(0), localPublicNonces: new Uint8Array(0), haveAllNonces: false, version: 0 }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.sessionId = new Uint8Array(0); + message.combinedKey = new Uint8Array(0); + message.taprootInternalKey = new Uint8Array(0); + message.localPublicNonces = new Uint8Array(0); + message.haveAllNonces = false; + message.version = 0; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -2103,8 +2137,9 @@ class MuSig2RegisterNoncesRequest$Type extends MessageType): MuSig2RegisterNoncesRequest { - const message = { sessionId: new Uint8Array(0), otherSignerPublicNonces: [] }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.sessionId = new Uint8Array(0); + message.otherSignerPublicNonces = []; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -2156,8 +2191,8 @@ class MuSig2RegisterNoncesResponse$Type extends MessageType): MuSig2RegisterNoncesResponse { - const message = { haveAllNonces: false }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.haveAllNonces = false; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -2205,8 +2240,10 @@ class MuSig2SignRequest$Type extends MessageType { ]); } create(value?: PartialMessage): MuSig2SignRequest { - const message = { sessionId: new Uint8Array(0), messageDigest: new Uint8Array(0), cleanup: false }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.sessionId = new Uint8Array(0); + message.messageDigest = new Uint8Array(0); + message.cleanup = false; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -2264,8 +2301,8 @@ class MuSig2SignResponse$Type extends MessageType { ]); } create(value?: PartialMessage): MuSig2SignResponse { - const message = { localPartialSignature: new Uint8Array(0) }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.localPartialSignature = new Uint8Array(0); if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -2312,8 +2349,9 @@ class MuSig2CombineSigRequest$Type extends MessageType ]); } create(value?: PartialMessage): MuSig2CombineSigRequest { - const message = { sessionId: new Uint8Array(0), otherPartialSignatures: [] }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.sessionId = new Uint8Array(0); + message.otherPartialSignatures = []; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -2366,8 +2404,9 @@ class MuSig2CombineSigResponse$Type extends MessageType): MuSig2CombineSigResponse { - const message = { haveAllSignatures: false, finalSignature: new Uint8Array(0) }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.haveAllSignatures = false; + message.finalSignature = new Uint8Array(0); if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -2419,8 +2458,8 @@ class MuSig2CleanupRequest$Type extends MessageType { ]); } create(value?: PartialMessage): MuSig2CleanupRequest { - const message = { sessionId: new Uint8Array(0) }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.sessionId = new Uint8Array(0); if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -2464,14 +2503,26 @@ class MuSig2CleanupResponse$Type extends MessageType { super("signrpc.MuSig2CleanupResponse", []); } create(value?: PartialMessage): MuSig2CleanupResponse { - const message = {}; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); if (value !== undefined) reflectionMergePartial(this, message, value); return message; } internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: MuSig2CleanupResponse): MuSig2CleanupResponse { - return target ?? this.create(); + let message = target ?? this.create(), end = reader.pos + length; + while (reader.pos < end) { + let [fieldNo, wireType] = reader.tag(); + switch (fieldNo) { + default: + let u = options.readUnknownField; + if (u === "throw") + throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`); + let d = reader.skip(wireType); + if (u !== false) + (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d); + } + } + return message; } internalBinaryWrite(message: MuSig2CleanupResponse, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter { let u = options.writeUnknownFields; diff --git a/proto/lnd/walletkit.client.ts b/proto/lnd/walletkit.client.ts index f136b7af..5f4fd335 100644 --- a/proto/lnd/walletkit.client.ts +++ b/proto/lnd/walletkit.client.ts @@ -1,4 +1,4 @@ -// @generated by protobuf-ts 2.8.1 +// @generated by protobuf-ts 2.11.1 // @generated from protobuf file "walletkit.proto" (package "walletrpc", syntax proto3) // tslint:disable import type { RpcTransport } from "@protobuf-ts/runtime-rpc"; @@ -43,7 +43,7 @@ import type { RequiredReserveResponse } from "./walletkit.js"; import type { RequiredReserveRequest } from "./walletkit.js"; import type { ListAccountsResponse } from "./walletkit.js"; import type { ListAccountsRequest } from "./walletkit.js"; -import type { Transaction } from "./lightning"; +import type { Transaction } from "./lightning.js"; import type { GetTransactionRequest } from "./walletkit.js"; import type { AddrResponse } from "./walletkit.js"; import type { AddrRequest } from "./walletkit.js"; @@ -92,7 +92,7 @@ export interface IWalletKitClient { * default, all utxos are listed. To list only the unconfirmed utxos, set * the unconfirmed_only to true. * - * @generated from protobuf rpc: ListUnspent(walletrpc.ListUnspentRequest) returns (walletrpc.ListUnspentResponse); + * @generated from protobuf rpc: ListUnspent */ listUnspent(input: ListUnspentRequest, options?: RpcOptions): UnaryCall; /** @@ -103,7 +103,7 @@ export interface IWalletKitClient { * successive invocations of this RPC. Outputs can be unlocked before their * expiration through `ReleaseOutput`. * - * @generated from protobuf rpc: LeaseOutput(walletrpc.LeaseOutputRequest) returns (walletrpc.LeaseOutputResponse); + * @generated from protobuf rpc: LeaseOutput */ leaseOutput(input: LeaseOutputRequest, options?: RpcOptions): UnaryCall; /** @@ -112,14 +112,14 @@ export interface IWalletKitClient { * selection if it remains unspent. The ID should match the one used to * originally lock the output. * - * @generated from protobuf rpc: ReleaseOutput(walletrpc.ReleaseOutputRequest) returns (walletrpc.ReleaseOutputResponse); + * @generated from protobuf rpc: ReleaseOutput */ releaseOutput(input: ReleaseOutputRequest, options?: RpcOptions): UnaryCall; /** * lncli: `wallet listleases` * ListLeases lists all currently locked utxos. * - * @generated from protobuf rpc: ListLeases(walletrpc.ListLeasesRequest) returns (walletrpc.ListLeasesResponse); + * @generated from protobuf rpc: ListLeases */ listLeases(input: ListLeasesRequest, options?: RpcOptions): UnaryCall; /** @@ -128,7 +128,7 @@ export interface IWalletKitClient { * (account in BIP43) specified. This method should return the next external * child within this branch. * - * @generated from protobuf rpc: DeriveNextKey(walletrpc.KeyReq) returns (signrpc.KeyDescriptor); + * @generated from protobuf rpc: DeriveNextKey */ deriveNextKey(input: KeyReq, options?: RpcOptions): UnaryCall; /** @@ -136,21 +136,21 @@ export interface IWalletKitClient { * DeriveKey attempts to derive an arbitrary key specified by the passed * KeyLocator. * - * @generated from protobuf rpc: DeriveKey(signrpc.KeyLocator) returns (signrpc.KeyDescriptor); + * @generated from protobuf rpc: DeriveKey */ deriveKey(input: KeyLocator, options?: RpcOptions): UnaryCall; /** * * NextAddr returns the next unused address within the wallet. * - * @generated from protobuf rpc: NextAddr(walletrpc.AddrRequest) returns (walletrpc.AddrResponse); + * @generated from protobuf rpc: NextAddr */ nextAddr(input: AddrRequest, options?: RpcOptions): UnaryCall; /** * lncli: `wallet gettx` * GetTransaction returns details for a transaction found in the wallet. * - * @generated from protobuf rpc: GetTransaction(walletrpc.GetTransactionRequest) returns (lnrpc.Transaction); + * @generated from protobuf rpc: GetTransaction */ getTransaction(input: GetTransactionRequest, options?: RpcOptions): UnaryCall; /** @@ -159,7 +159,7 @@ export interface IWalletKitClient { * name and key scope filter can be provided to filter through all of the * wallet accounts and return only those matching. * - * @generated from protobuf rpc: ListAccounts(walletrpc.ListAccountsRequest) returns (walletrpc.ListAccountsResponse); + * @generated from protobuf rpc: ListAccounts */ listAccounts(input: ListAccountsRequest, options?: RpcOptions): UnaryCall; /** @@ -168,7 +168,7 @@ export interface IWalletKitClient { * in the wallet in order to fee bump anchor channels if necessary. The value * scales with the number of public anchor channels but is capped at a maximum. * - * @generated from protobuf rpc: RequiredReserve(walletrpc.RequiredReserveRequest) returns (walletrpc.RequiredReserveResponse); + * @generated from protobuf rpc: RequiredReserve */ requiredReserve(input: RequiredReserveRequest, options?: RpcOptions): UnaryCall; /** @@ -177,7 +177,7 @@ export interface IWalletKitClient { * account name filter can be provided to filter through all of the * wallet accounts and return the addresses of only those matching. * - * @generated from protobuf rpc: ListAddresses(walletrpc.ListAddressesRequest) returns (walletrpc.ListAddressesResponse); + * @generated from protobuf rpc: ListAddresses */ listAddresses(input: ListAddressesRequest, options?: RpcOptions): UnaryCall; /** @@ -195,7 +195,7 @@ export interface IWalletKitClient { * For P2TR addresses this represents a special case. ECDSA is used to create * a compact signature which makes the public key of the signature recoverable. * - * @generated from protobuf rpc: SignMessageWithAddr(walletrpc.SignMessageWithAddrRequest) returns (walletrpc.SignMessageWithAddrResponse); + * @generated from protobuf rpc: SignMessageWithAddr */ signMessageWithAddr(input: SignMessageWithAddrRequest, options?: RpcOptions): UnaryCall; /** @@ -220,7 +220,7 @@ export interface IWalletKitClient { * taproot key. The compact ECDSA signature format was used because there * are still no known compact signature schemes for schnorr signatures. * - * @generated from protobuf rpc: VerifyMessageWithAddr(walletrpc.VerifyMessageWithAddrRequest) returns (walletrpc.VerifyMessageWithAddrResponse); + * @generated from protobuf rpc: VerifyMessageWithAddr */ verifyMessageWithAddr(input: VerifyMessageWithAddrRequest, options?: RpcOptions): UnaryCall; /** @@ -249,7 +249,7 @@ export interface IWalletKitClient { * detected by lnd if they happen after the import. Rescans to detect past * events will be supported later on. * - * @generated from protobuf rpc: ImportAccount(walletrpc.ImportAccountRequest) returns (walletrpc.ImportAccountResponse); + * @generated from protobuf rpc: ImportAccount */ importAccount(input: ImportAccountRequest, options?: RpcOptions): UnaryCall; /** @@ -264,7 +264,7 @@ export interface IWalletKitClient { * they happen after the import. Rescans to detect past events will be * supported later on. * - * @generated from protobuf rpc: ImportPublicKey(walletrpc.ImportPublicKeyRequest) returns (walletrpc.ImportPublicKeyResponse); + * @generated from protobuf rpc: ImportPublicKey */ importPublicKey(input: ImportPublicKeyRequest, options?: RpcOptions): UnaryCall; /** @@ -281,7 +281,7 @@ export interface IWalletKitClient { * NOTE: Taproot keys imported through this RPC currently _cannot_ be used for * funding PSBTs. Only tracking the balance and UTXOs is currently supported. * - * @generated from protobuf rpc: ImportTapscript(walletrpc.ImportTapscriptRequest) returns (walletrpc.ImportTapscriptResponse); + * @generated from protobuf rpc: ImportTapscript */ importTapscript(input: ImportTapscriptRequest, options?: RpcOptions): UnaryCall; /** @@ -291,7 +291,7 @@ export interface IWalletKitClient { * attempt to re-broadcast the transaction on start up, until it enters the * chain. * - * @generated from protobuf rpc: PublishTransaction(walletrpc.Transaction) returns (walletrpc.PublishResponse); + * @generated from protobuf rpc: PublishTransaction */ publishTransaction(input: Transaction$, options?: RpcOptions): UnaryCall; /** @@ -299,7 +299,7 @@ export interface IWalletKitClient { * RemoveTransaction attempts to remove the provided transaction from the * internal transaction store of the wallet. * - * @generated from protobuf rpc: RemoveTransaction(walletrpc.GetTransactionRequest) returns (walletrpc.RemoveTransactionResponse); + * @generated from protobuf rpc: RemoveTransaction */ removeTransaction(input: GetTransactionRequest, options?: RpcOptions): UnaryCall; /** @@ -308,7 +308,7 @@ export interface IWalletKitClient { * allows the caller to create a transaction that sends to several outputs at * once. This is ideal when wanting to batch create a set of transactions. * - * @generated from protobuf rpc: SendOutputs(walletrpc.SendOutputsRequest) returns (walletrpc.SendOutputsResponse); + * @generated from protobuf rpc: SendOutputs */ sendOutputs(input: SendOutputsRequest, options?: RpcOptions): UnaryCall; /** @@ -317,7 +317,7 @@ export interface IWalletKitClient { * determine the fee (in sat/kw) to attach to a transaction in order to * achieve the confirmation target. * - * @generated from protobuf rpc: EstimateFee(walletrpc.EstimateFeeRequest) returns (walletrpc.EstimateFeeResponse); + * @generated from protobuf rpc: EstimateFee */ estimateFee(input: EstimateFeeRequest, options?: RpcOptions): UnaryCall; /** @@ -331,7 +331,7 @@ export interface IWalletKitClient { * remain supported. This is an advanced API that depends on the internals of * the UtxoSweeper, so things may change. * - * @generated from protobuf rpc: PendingSweeps(walletrpc.PendingSweepsRequest) returns (walletrpc.PendingSweepsResponse); + * @generated from protobuf rpc: PendingSweeps */ pendingSweeps(input: PendingSweepsRequest, options?: RpcOptions): UnaryCall; /** @@ -365,7 +365,7 @@ export interface IWalletKitClient { * done by specifying an outpoint within the low fee transaction that is under * the control of the wallet. * - * @generated from protobuf rpc: BumpFee(walletrpc.BumpFeeRequest) returns (walletrpc.BumpFeeResponse); + * @generated from protobuf rpc: BumpFee */ bumpFee(input: BumpFeeRequest, options?: RpcOptions): UnaryCall; /** @@ -373,7 +373,7 @@ export interface IWalletKitClient { * BumpForceCloseFee is an endpoint that allows users to bump the fee of a * channel force close. This only works for channels with option_anchors. * - * @generated from protobuf rpc: BumpForceCloseFee(walletrpc.BumpForceCloseFeeRequest) returns (walletrpc.BumpForceCloseFeeResponse); + * @generated from protobuf rpc: BumpForceCloseFee */ bumpForceCloseFee(input: BumpForceCloseFeeRequest, options?: RpcOptions): UnaryCall; /** @@ -382,7 +382,7 @@ export interface IWalletKitClient { * Note that these sweeps may not be confirmed yet, as we record sweeps on * broadcast, not confirmation. * - * @generated from protobuf rpc: ListSweeps(walletrpc.ListSweepsRequest) returns (walletrpc.ListSweepsResponse); + * @generated from protobuf rpc: ListSweeps */ listSweeps(input: ListSweepsRequest, options?: RpcOptions): UnaryCall; /** @@ -392,7 +392,7 @@ export interface IWalletKitClient { * overwrite the existing transaction label. Labels must not be empty, and * cannot exceed 500 characters. * - * @generated from protobuf rpc: LabelTransaction(walletrpc.LabelTransactionRequest) returns (walletrpc.LabelTransactionResponse); + * @generated from protobuf rpc: LabelTransaction */ labelTransaction(input: LabelTransactionRequest, options?: RpcOptions): UnaryCall; /** @@ -426,7 +426,7 @@ export interface IWalletKitClient { * publishing the transaction) or to unlock/release the locked UTXOs in case of * an error on the caller's side. * - * @generated from protobuf rpc: FundPsbt(walletrpc.FundPsbtRequest) returns (walletrpc.FundPsbtResponse); + * @generated from protobuf rpc: FundPsbt */ fundPsbt(input: FundPsbtRequest, options?: RpcOptions): UnaryCall; /** @@ -443,7 +443,7 @@ export interface IWalletKitClient { * input/output/fee value validation, PSBT finalization). Any input that is * incomplete will be skipped. * - * @generated from protobuf rpc: SignPsbt(walletrpc.SignPsbtRequest) returns (walletrpc.SignPsbtResponse); + * @generated from protobuf rpc: SignPsbt */ signPsbt(input: SignPsbtRequest, options?: RpcOptions): UnaryCall; /** @@ -460,7 +460,7 @@ export interface IWalletKitClient { * caller's responsibility to either publish the transaction on success or * unlock/release any locked UTXOs in case of an error in this method. * - * @generated from protobuf rpc: FinalizePsbt(walletrpc.FinalizePsbtRequest) returns (walletrpc.FinalizePsbtResponse); + * @generated from protobuf rpc: FinalizePsbt */ finalizePsbt(input: FinalizePsbtRequest, options?: RpcOptions): UnaryCall; } @@ -500,7 +500,7 @@ export class WalletKitClient implements IWalletKitClient, ServiceInfo { * default, all utxos are listed. To list only the unconfirmed utxos, set * the unconfirmed_only to true. * - * @generated from protobuf rpc: ListUnspent(walletrpc.ListUnspentRequest) returns (walletrpc.ListUnspentResponse); + * @generated from protobuf rpc: ListUnspent */ listUnspent(input: ListUnspentRequest, options?: RpcOptions): UnaryCall { const method = this.methods[0], opt = this._transport.mergeOptions(options); @@ -514,7 +514,7 @@ export class WalletKitClient implements IWalletKitClient, ServiceInfo { * successive invocations of this RPC. Outputs can be unlocked before their * expiration through `ReleaseOutput`. * - * @generated from protobuf rpc: LeaseOutput(walletrpc.LeaseOutputRequest) returns (walletrpc.LeaseOutputResponse); + * @generated from protobuf rpc: LeaseOutput */ leaseOutput(input: LeaseOutputRequest, options?: RpcOptions): UnaryCall { const method = this.methods[1], opt = this._transport.mergeOptions(options); @@ -526,7 +526,7 @@ export class WalletKitClient implements IWalletKitClient, ServiceInfo { * selection if it remains unspent. The ID should match the one used to * originally lock the output. * - * @generated from protobuf rpc: ReleaseOutput(walletrpc.ReleaseOutputRequest) returns (walletrpc.ReleaseOutputResponse); + * @generated from protobuf rpc: ReleaseOutput */ releaseOutput(input: ReleaseOutputRequest, options?: RpcOptions): UnaryCall { const method = this.methods[2], opt = this._transport.mergeOptions(options); @@ -536,7 +536,7 @@ export class WalletKitClient implements IWalletKitClient, ServiceInfo { * lncli: `wallet listleases` * ListLeases lists all currently locked utxos. * - * @generated from protobuf rpc: ListLeases(walletrpc.ListLeasesRequest) returns (walletrpc.ListLeasesResponse); + * @generated from protobuf rpc: ListLeases */ listLeases(input: ListLeasesRequest, options?: RpcOptions): UnaryCall { const method = this.methods[3], opt = this._transport.mergeOptions(options); @@ -548,7 +548,7 @@ export class WalletKitClient implements IWalletKitClient, ServiceInfo { * (account in BIP43) specified. This method should return the next external * child within this branch. * - * @generated from protobuf rpc: DeriveNextKey(walletrpc.KeyReq) returns (signrpc.KeyDescriptor); + * @generated from protobuf rpc: DeriveNextKey */ deriveNextKey(input: KeyReq, options?: RpcOptions): UnaryCall { const method = this.methods[4], opt = this._transport.mergeOptions(options); @@ -559,7 +559,7 @@ export class WalletKitClient implements IWalletKitClient, ServiceInfo { * DeriveKey attempts to derive an arbitrary key specified by the passed * KeyLocator. * - * @generated from protobuf rpc: DeriveKey(signrpc.KeyLocator) returns (signrpc.KeyDescriptor); + * @generated from protobuf rpc: DeriveKey */ deriveKey(input: KeyLocator, options?: RpcOptions): UnaryCall { const method = this.methods[5], opt = this._transport.mergeOptions(options); @@ -569,7 +569,7 @@ export class WalletKitClient implements IWalletKitClient, ServiceInfo { * * NextAddr returns the next unused address within the wallet. * - * @generated from protobuf rpc: NextAddr(walletrpc.AddrRequest) returns (walletrpc.AddrResponse); + * @generated from protobuf rpc: NextAddr */ nextAddr(input: AddrRequest, options?: RpcOptions): UnaryCall { const method = this.methods[6], opt = this._transport.mergeOptions(options); @@ -579,7 +579,7 @@ export class WalletKitClient implements IWalletKitClient, ServiceInfo { * lncli: `wallet gettx` * GetTransaction returns details for a transaction found in the wallet. * - * @generated from protobuf rpc: GetTransaction(walletrpc.GetTransactionRequest) returns (lnrpc.Transaction); + * @generated from protobuf rpc: GetTransaction */ getTransaction(input: GetTransactionRequest, options?: RpcOptions): UnaryCall { const method = this.methods[7], opt = this._transport.mergeOptions(options); @@ -591,7 +591,7 @@ export class WalletKitClient implements IWalletKitClient, ServiceInfo { * name and key scope filter can be provided to filter through all of the * wallet accounts and return only those matching. * - * @generated from protobuf rpc: ListAccounts(walletrpc.ListAccountsRequest) returns (walletrpc.ListAccountsResponse); + * @generated from protobuf rpc: ListAccounts */ listAccounts(input: ListAccountsRequest, options?: RpcOptions): UnaryCall { const method = this.methods[8], opt = this._transport.mergeOptions(options); @@ -603,7 +603,7 @@ export class WalletKitClient implements IWalletKitClient, ServiceInfo { * in the wallet in order to fee bump anchor channels if necessary. The value * scales with the number of public anchor channels but is capped at a maximum. * - * @generated from protobuf rpc: RequiredReserve(walletrpc.RequiredReserveRequest) returns (walletrpc.RequiredReserveResponse); + * @generated from protobuf rpc: RequiredReserve */ requiredReserve(input: RequiredReserveRequest, options?: RpcOptions): UnaryCall { const method = this.methods[9], opt = this._transport.mergeOptions(options); @@ -615,7 +615,7 @@ export class WalletKitClient implements IWalletKitClient, ServiceInfo { * account name filter can be provided to filter through all of the * wallet accounts and return the addresses of only those matching. * - * @generated from protobuf rpc: ListAddresses(walletrpc.ListAddressesRequest) returns (walletrpc.ListAddressesResponse); + * @generated from protobuf rpc: ListAddresses */ listAddresses(input: ListAddressesRequest, options?: RpcOptions): UnaryCall { const method = this.methods[10], opt = this._transport.mergeOptions(options); @@ -636,7 +636,7 @@ export class WalletKitClient implements IWalletKitClient, ServiceInfo { * For P2TR addresses this represents a special case. ECDSA is used to create * a compact signature which makes the public key of the signature recoverable. * - * @generated from protobuf rpc: SignMessageWithAddr(walletrpc.SignMessageWithAddrRequest) returns (walletrpc.SignMessageWithAddrResponse); + * @generated from protobuf rpc: SignMessageWithAddr */ signMessageWithAddr(input: SignMessageWithAddrRequest, options?: RpcOptions): UnaryCall { const method = this.methods[11], opt = this._transport.mergeOptions(options); @@ -664,7 +664,7 @@ export class WalletKitClient implements IWalletKitClient, ServiceInfo { * taproot key. The compact ECDSA signature format was used because there * are still no known compact signature schemes for schnorr signatures. * - * @generated from protobuf rpc: VerifyMessageWithAddr(walletrpc.VerifyMessageWithAddrRequest) returns (walletrpc.VerifyMessageWithAddrResponse); + * @generated from protobuf rpc: VerifyMessageWithAddr */ verifyMessageWithAddr(input: VerifyMessageWithAddrRequest, options?: RpcOptions): UnaryCall { const method = this.methods[12], opt = this._transport.mergeOptions(options); @@ -696,7 +696,7 @@ export class WalletKitClient implements IWalletKitClient, ServiceInfo { * detected by lnd if they happen after the import. Rescans to detect past * events will be supported later on. * - * @generated from protobuf rpc: ImportAccount(walletrpc.ImportAccountRequest) returns (walletrpc.ImportAccountResponse); + * @generated from protobuf rpc: ImportAccount */ importAccount(input: ImportAccountRequest, options?: RpcOptions): UnaryCall { const method = this.methods[13], opt = this._transport.mergeOptions(options); @@ -714,7 +714,7 @@ export class WalletKitClient implements IWalletKitClient, ServiceInfo { * they happen after the import. Rescans to detect past events will be * supported later on. * - * @generated from protobuf rpc: ImportPublicKey(walletrpc.ImportPublicKeyRequest) returns (walletrpc.ImportPublicKeyResponse); + * @generated from protobuf rpc: ImportPublicKey */ importPublicKey(input: ImportPublicKeyRequest, options?: RpcOptions): UnaryCall { const method = this.methods[14], opt = this._transport.mergeOptions(options); @@ -734,7 +734,7 @@ export class WalletKitClient implements IWalletKitClient, ServiceInfo { * NOTE: Taproot keys imported through this RPC currently _cannot_ be used for * funding PSBTs. Only tracking the balance and UTXOs is currently supported. * - * @generated from protobuf rpc: ImportTapscript(walletrpc.ImportTapscriptRequest) returns (walletrpc.ImportTapscriptResponse); + * @generated from protobuf rpc: ImportTapscript */ importTapscript(input: ImportTapscriptRequest, options?: RpcOptions): UnaryCall { const method = this.methods[15], opt = this._transport.mergeOptions(options); @@ -747,7 +747,7 @@ export class WalletKitClient implements IWalletKitClient, ServiceInfo { * attempt to re-broadcast the transaction on start up, until it enters the * chain. * - * @generated from protobuf rpc: PublishTransaction(walletrpc.Transaction) returns (walletrpc.PublishResponse); + * @generated from protobuf rpc: PublishTransaction */ publishTransaction(input: Transaction$, options?: RpcOptions): UnaryCall { const method = this.methods[16], opt = this._transport.mergeOptions(options); @@ -758,7 +758,7 @@ export class WalletKitClient implements IWalletKitClient, ServiceInfo { * RemoveTransaction attempts to remove the provided transaction from the * internal transaction store of the wallet. * - * @generated from protobuf rpc: RemoveTransaction(walletrpc.GetTransactionRequest) returns (walletrpc.RemoveTransactionResponse); + * @generated from protobuf rpc: RemoveTransaction */ removeTransaction(input: GetTransactionRequest, options?: RpcOptions): UnaryCall { const method = this.methods[17], opt = this._transport.mergeOptions(options); @@ -770,7 +770,7 @@ export class WalletKitClient implements IWalletKitClient, ServiceInfo { * allows the caller to create a transaction that sends to several outputs at * once. This is ideal when wanting to batch create a set of transactions. * - * @generated from protobuf rpc: SendOutputs(walletrpc.SendOutputsRequest) returns (walletrpc.SendOutputsResponse); + * @generated from protobuf rpc: SendOutputs */ sendOutputs(input: SendOutputsRequest, options?: RpcOptions): UnaryCall { const method = this.methods[18], opt = this._transport.mergeOptions(options); @@ -782,7 +782,7 @@ export class WalletKitClient implements IWalletKitClient, ServiceInfo { * determine the fee (in sat/kw) to attach to a transaction in order to * achieve the confirmation target. * - * @generated from protobuf rpc: EstimateFee(walletrpc.EstimateFeeRequest) returns (walletrpc.EstimateFeeResponse); + * @generated from protobuf rpc: EstimateFee */ estimateFee(input: EstimateFeeRequest, options?: RpcOptions): UnaryCall { const method = this.methods[19], opt = this._transport.mergeOptions(options); @@ -799,7 +799,7 @@ export class WalletKitClient implements IWalletKitClient, ServiceInfo { * remain supported. This is an advanced API that depends on the internals of * the UtxoSweeper, so things may change. * - * @generated from protobuf rpc: PendingSweeps(walletrpc.PendingSweepsRequest) returns (walletrpc.PendingSweepsResponse); + * @generated from protobuf rpc: PendingSweeps */ pendingSweeps(input: PendingSweepsRequest, options?: RpcOptions): UnaryCall { const method = this.methods[20], opt = this._transport.mergeOptions(options); @@ -836,7 +836,7 @@ export class WalletKitClient implements IWalletKitClient, ServiceInfo { * done by specifying an outpoint within the low fee transaction that is under * the control of the wallet. * - * @generated from protobuf rpc: BumpFee(walletrpc.BumpFeeRequest) returns (walletrpc.BumpFeeResponse); + * @generated from protobuf rpc: BumpFee */ bumpFee(input: BumpFeeRequest, options?: RpcOptions): UnaryCall { const method = this.methods[21], opt = this._transport.mergeOptions(options); @@ -847,7 +847,7 @@ export class WalletKitClient implements IWalletKitClient, ServiceInfo { * BumpForceCloseFee is an endpoint that allows users to bump the fee of a * channel force close. This only works for channels with option_anchors. * - * @generated from protobuf rpc: BumpForceCloseFee(walletrpc.BumpForceCloseFeeRequest) returns (walletrpc.BumpForceCloseFeeResponse); + * @generated from protobuf rpc: BumpForceCloseFee */ bumpForceCloseFee(input: BumpForceCloseFeeRequest, options?: RpcOptions): UnaryCall { const method = this.methods[22], opt = this._transport.mergeOptions(options); @@ -859,7 +859,7 @@ export class WalletKitClient implements IWalletKitClient, ServiceInfo { * Note that these sweeps may not be confirmed yet, as we record sweeps on * broadcast, not confirmation. * - * @generated from protobuf rpc: ListSweeps(walletrpc.ListSweepsRequest) returns (walletrpc.ListSweepsResponse); + * @generated from protobuf rpc: ListSweeps */ listSweeps(input: ListSweepsRequest, options?: RpcOptions): UnaryCall { const method = this.methods[23], opt = this._transport.mergeOptions(options); @@ -872,7 +872,7 @@ export class WalletKitClient implements IWalletKitClient, ServiceInfo { * overwrite the existing transaction label. Labels must not be empty, and * cannot exceed 500 characters. * - * @generated from protobuf rpc: LabelTransaction(walletrpc.LabelTransactionRequest) returns (walletrpc.LabelTransactionResponse); + * @generated from protobuf rpc: LabelTransaction */ labelTransaction(input: LabelTransactionRequest, options?: RpcOptions): UnaryCall { const method = this.methods[24], opt = this._transport.mergeOptions(options); @@ -909,7 +909,7 @@ export class WalletKitClient implements IWalletKitClient, ServiceInfo { * publishing the transaction) or to unlock/release the locked UTXOs in case of * an error on the caller's side. * - * @generated from protobuf rpc: FundPsbt(walletrpc.FundPsbtRequest) returns (walletrpc.FundPsbtResponse); + * @generated from protobuf rpc: FundPsbt */ fundPsbt(input: FundPsbtRequest, options?: RpcOptions): UnaryCall { const method = this.methods[25], opt = this._transport.mergeOptions(options); @@ -929,7 +929,7 @@ export class WalletKitClient implements IWalletKitClient, ServiceInfo { * input/output/fee value validation, PSBT finalization). Any input that is * incomplete will be skipped. * - * @generated from protobuf rpc: SignPsbt(walletrpc.SignPsbtRequest) returns (walletrpc.SignPsbtResponse); + * @generated from protobuf rpc: SignPsbt */ signPsbt(input: SignPsbtRequest, options?: RpcOptions): UnaryCall { const method = this.methods[26], opt = this._transport.mergeOptions(options); @@ -949,7 +949,7 @@ export class WalletKitClient implements IWalletKitClient, ServiceInfo { * caller's responsibility to either publish the transaction on success or * unlock/release any locked UTXOs in case of an error in this method. * - * @generated from protobuf rpc: FinalizePsbt(walletrpc.FinalizePsbtRequest) returns (walletrpc.FinalizePsbtResponse); + * @generated from protobuf rpc: FinalizePsbt */ finalizePsbt(input: FinalizePsbtRequest, options?: RpcOptions): UnaryCall { const method = this.methods[27], opt = this._transport.mergeOptions(options); diff --git a/proto/lnd/walletkit.ts b/proto/lnd/walletkit.ts index dc895566..42e98185 100644 --- a/proto/lnd/walletkit.ts +++ b/proto/lnd/walletkit.ts @@ -1,4 +1,4 @@ -// @generated by protobuf-ts 2.8.1 +// @generated by protobuf-ts 2.11.1 // @generated from protobuf file "walletkit.proto" (package "walletrpc", syntax proto3) // tslint:disable import { Transaction as Transaction$ } from "./lightning.js"; @@ -13,7 +13,6 @@ import type { IBinaryReader } from "@protobuf-ts/runtime"; import { UnknownFieldHandler } from "@protobuf-ts/runtime"; import type { PartialMessage } from "@protobuf-ts/runtime"; import { reflectionMergePartial } from "@protobuf-ts/runtime"; -import { MESSAGE_TYPE } from "@protobuf-ts/runtime"; import { MessageType } from "@protobuf-ts/runtime"; import { TransactionDetails } from "./lightning.js"; import { ChannelPoint } from "./lightning.js"; @@ -28,19 +27,19 @@ export interface ListUnspentRequest { /** * The minimum number of confirmations to be included. * - * @generated from protobuf field: int32 min_confs = 1; + * @generated from protobuf field: int32 min_confs = 1 */ minConfs: number; /** * The maximum number of confirmations to be included. * - * @generated from protobuf field: int32 max_confs = 2; + * @generated from protobuf field: int32 max_confs = 2 */ maxConfs: number; /** * An optional filter to only include outputs belonging to an account. * - * @generated from protobuf field: string account = 3; + * @generated from protobuf field: string account = 3 */ account: string; /** @@ -50,7 +49,7 @@ export interface ListUnspentRequest { * zero. An error is returned if the value is true and both min_confs * and max_confs are non-zero. (default: false) * - * @generated from protobuf field: bool unconfirmed_only = 4; + * @generated from protobuf field: bool unconfirmed_only = 4 */ unconfirmedOnly: boolean; } @@ -61,7 +60,7 @@ export interface ListUnspentResponse { /** * A list of utxos satisfying the specified number of confirmations. * - * @generated from protobuf field: repeated lnrpc.Utxo utxos = 1; + * @generated from protobuf field: repeated lnrpc.Utxo utxos = 1 */ utxos: Utxo[]; } @@ -74,20 +73,20 @@ export interface LeaseOutputRequest { * An ID of 32 random bytes that must be unique for each distinct application * using this RPC which will be used to bound the output lease to. * - * @generated from protobuf field: bytes id = 1; + * @generated from protobuf field: bytes id = 1 */ id: Uint8Array; /** * The identifying outpoint of the output being leased. * - * @generated from protobuf field: lnrpc.OutPoint outpoint = 2; + * @generated from protobuf field: lnrpc.OutPoint outpoint = 2 */ outpoint?: OutPoint; /** * The time in seconds before the lock expires. If set to zero, the default * lock duration is used. * - * @generated from protobuf field: uint64 expiration_seconds = 3; + * @generated from protobuf field: uint64 expiration_seconds = 3 */ expirationSeconds: bigint; } @@ -99,7 +98,7 @@ export interface LeaseOutputResponse { * * The absolute expiration of the output lease represented as a unix timestamp. * - * @generated from protobuf field: uint64 expiration = 1; + * @generated from protobuf field: uint64 expiration = 1 */ expiration: bigint; } @@ -110,13 +109,13 @@ export interface ReleaseOutputRequest { /** * The unique ID that was used to lock the output. * - * @generated from protobuf field: bytes id = 1; + * @generated from protobuf field: bytes id = 1 */ id: Uint8Array; /** * The identifying outpoint of the output being released. * - * @generated from protobuf field: lnrpc.OutPoint outpoint = 2; + * @generated from protobuf field: lnrpc.OutPoint outpoint = 2 */ outpoint?: OutPoint; } @@ -127,7 +126,7 @@ export interface ReleaseOutputResponse { /** * The status of the release operation. * - * @generated from protobuf field: string status = 1; + * @generated from protobuf field: string status = 1 */ status: string; } @@ -141,7 +140,7 @@ export interface KeyReq { * This allows the WalletKit to possibly serve out keys for multiple HD chains * via public derivation. * - * @generated from protobuf field: int32 key_finger_print = 1; + * @generated from protobuf field: int32 key_finger_print = 1 */ keyFingerPrint: number; /** @@ -149,7 +148,7 @@ export interface KeyReq { * The target key family to derive a key from. In other contexts, this is * known as the "account". * - * @generated from protobuf field: int32 key_family = 2; + * @generated from protobuf field: int32 key_family = 2 */ keyFamily: number; } @@ -162,21 +161,21 @@ export interface AddrRequest { * The name of the account to retrieve the next address of. If empty, the * default wallet account is used. * - * @generated from protobuf field: string account = 1; + * @generated from protobuf field: string account = 1 */ account: string; /** * * The type of address to derive. * - * @generated from protobuf field: walletrpc.AddressType type = 2; + * @generated from protobuf field: walletrpc.AddressType type = 2 */ type: AddressType; /** * * Whether a change address should be derived. * - * @generated from protobuf field: bool change = 3; + * @generated from protobuf field: bool change = 3 */ change: boolean; } @@ -188,7 +187,7 @@ export interface AddrResponse { * * The address encoded using a bech32 format. * - * @generated from protobuf field: string addr = 1; + * @generated from protobuf field: string addr = 1 */ addr: string; } @@ -199,13 +198,13 @@ export interface Account { /** * The name used to identify the account. * - * @generated from protobuf field: string name = 1; + * @generated from protobuf field: string name = 1 */ name: string; /** * The type of addresses the account supports. * - * @generated from protobuf field: walletrpc.AddressType address_type = 2; + * @generated from protobuf field: walletrpc.AddressType address_type = 2 */ addressType: AddressType; /** @@ -214,7 +213,7 @@ export interface Account { * represented as an extended key. This will always be empty for the default * imported account in which single public keys are imported into. * - * @generated from protobuf field: string extended_public_key = 3; + * @generated from protobuf field: string extended_public_key = 3 */ extendedPublicKey: string; /** @@ -224,7 +223,7 @@ export interface Account { * which single public keys are imported into. The bytes are in big-endian * order. * - * @generated from protobuf field: bytes master_key_fingerprint = 4; + * @generated from protobuf field: bytes master_key_fingerprint = 4 */ masterKeyFingerprint: Uint8Array; /** @@ -233,7 +232,7 @@ export interface Account { * always be empty for the default imported account in which single public keys * are imported into. * - * @generated from protobuf field: string derivation_path = 5; + * @generated from protobuf field: string derivation_path = 5 */ derivationPath: string; /** @@ -242,7 +241,7 @@ export interface Account { * key. This will always be zero for the default imported account in which * single public keys are imported into. * - * @generated from protobuf field: uint32 external_key_count = 6; + * @generated from protobuf field: uint32 external_key_count = 6 */ externalKeyCount: number; /** @@ -251,13 +250,13 @@ export interface Account { * key. This will always be zero for the default imported account in which * single public keys are imported into. * - * @generated from protobuf field: uint32 internal_key_count = 7; + * @generated from protobuf field: uint32 internal_key_count = 7 */ internalKeyCount: number; /** * Whether the wallet stores private keys for the account. * - * @generated from protobuf field: bool watch_only = 8; + * @generated from protobuf field: bool watch_only = 8 */ watchOnly: boolean; } @@ -276,32 +275,32 @@ export interface AddressProperty { * on-chain balance, we'll show the public key instead (only if * the show_custom_accounts flag is provided). * - * @generated from protobuf field: string address = 1; + * @generated from protobuf field: string address = 1 */ address: string; /** * Denotes if the address is a change address. * - * @generated from protobuf field: bool is_internal = 2; + * @generated from protobuf field: bool is_internal = 2 */ isInternal: boolean; /** * The balance of the address. * - * @generated from protobuf field: int64 balance = 3; + * @generated from protobuf field: int64 balance = 3 */ balance: bigint; /** * The full derivation path of the address. This will be empty for imported * addresses. * - * @generated from protobuf field: string derivation_path = 4; + * @generated from protobuf field: string derivation_path = 4 */ derivationPath: string; /** * The public key of the address. This will be empty for imported addresses. * - * @generated from protobuf field: bytes public_key = 5; + * @generated from protobuf field: bytes public_key = 5 */ publicKey: Uint8Array; } @@ -312,13 +311,13 @@ export interface AccountWithAddresses { /** * The name used to identify the account. * - * @generated from protobuf field: string name = 1; + * @generated from protobuf field: string name = 1 */ name: string; /** * The type of addresses the account supports. * - * @generated from protobuf field: walletrpc.AddressType address_type = 2; + * @generated from protobuf field: walletrpc.AddressType address_type = 2 */ addressType: AddressType; /** @@ -327,7 +326,7 @@ export interface AccountWithAddresses { * always be empty for the default imported account in which single public keys * are imported into. * - * @generated from protobuf field: string derivation_path = 3; + * @generated from protobuf field: string derivation_path = 3 */ derivationPath: string; /** @@ -337,7 +336,7 @@ export interface AccountWithAddresses { * derivation index, since that information is not stored by the underlying * wallet. * - * @generated from protobuf field: repeated walletrpc.AddressProperty addresses = 4; + * @generated from protobuf field: repeated walletrpc.AddressProperty addresses = 4 */ addresses: AddressProperty[]; } @@ -348,13 +347,13 @@ export interface ListAccountsRequest { /** * An optional filter to only return accounts matching this name. * - * @generated from protobuf field: string name = 1; + * @generated from protobuf field: string name = 1 */ name: string; /** * An optional filter to only return accounts matching this address type. * - * @generated from protobuf field: walletrpc.AddressType address_type = 2; + * @generated from protobuf field: walletrpc.AddressType address_type = 2 */ addressType: AddressType; } @@ -363,7 +362,7 @@ export interface ListAccountsRequest { */ export interface ListAccountsResponse { /** - * @generated from protobuf field: repeated walletrpc.Account accounts = 1; + * @generated from protobuf field: repeated walletrpc.Account accounts = 1 */ accounts: Account[]; } @@ -374,7 +373,7 @@ export interface RequiredReserveRequest { /** * The number of additional channels the user would like to open. * - * @generated from protobuf field: uint32 additional_public_channels = 1; + * @generated from protobuf field: uint32 additional_public_channels = 1 */ additionalPublicChannels: number; } @@ -385,7 +384,7 @@ export interface RequiredReserveResponse { /** * The amount of reserve required. * - * @generated from protobuf field: int64 required_reserve = 1; + * @generated from protobuf field: int64 required_reserve = 1 */ requiredReserve: bigint; } @@ -396,14 +395,14 @@ export interface ListAddressesRequest { /** * An optional filter to only return addresses matching this account. * - * @generated from protobuf field: string account_name = 1; + * @generated from protobuf field: string account_name = 1 */ accountName: string; /** * An optional flag to return LND's custom accounts (Purpose=1017) * public key along with other addresses. * - * @generated from protobuf field: bool show_custom_accounts = 2; + * @generated from protobuf field: bool show_custom_accounts = 2 */ showCustomAccounts: boolean; } @@ -414,7 +413,7 @@ export interface ListAddressesResponse { /** * A list of all the accounts and their addresses. * - * @generated from protobuf field: repeated walletrpc.AccountWithAddresses account_with_addresses = 1; + * @generated from protobuf field: repeated walletrpc.AccountWithAddresses account_with_addresses = 1 */ accountWithAddresses: AccountWithAddresses[]; } @@ -425,7 +424,7 @@ export interface GetTransactionRequest { /** * The txid of the transaction. * - * @generated from protobuf field: string txid = 1; + * @generated from protobuf field: string txid = 1 */ txid: string; } @@ -437,14 +436,14 @@ export interface SignMessageWithAddrRequest { * The message to be signed. When using REST, this field must be encoded as * base64. * - * @generated from protobuf field: bytes msg = 1; + * @generated from protobuf field: bytes msg = 1 */ msg: Uint8Array; /** * The address which will be used to look up the private key and sign the * corresponding message. * - * @generated from protobuf field: string addr = 2; + * @generated from protobuf field: string addr = 2 */ addr: string; } @@ -455,7 +454,7 @@ export interface SignMessageWithAddrResponse { /** * The compact ECDSA signature for the given message encoded in base64. * - * @generated from protobuf field: string signature = 1; + * @generated from protobuf field: string signature = 1 */ signature: string; } @@ -467,21 +466,21 @@ export interface VerifyMessageWithAddrRequest { * The message to be signed. When using REST, this field must be encoded as * base64. * - * @generated from protobuf field: bytes msg = 1; + * @generated from protobuf field: bytes msg = 1 */ msg: Uint8Array; /** * The compact ECDSA signature to be verified over the given message * ecoded in base64. * - * @generated from protobuf field: string signature = 2; + * @generated from protobuf field: string signature = 2 */ signature: string; /** * The address which will be used to look up the public key and verify the * the signature. * - * @generated from protobuf field: string addr = 3; + * @generated from protobuf field: string addr = 3 */ addr: string; } @@ -492,13 +491,13 @@ export interface VerifyMessageWithAddrResponse { /** * Whether the signature was valid over the given message. * - * @generated from protobuf field: bool valid = 1; + * @generated from protobuf field: bool valid = 1 */ valid: boolean; /** * The pubkey recovered from the signature. * - * @generated from protobuf field: bytes pubkey = 2; + * @generated from protobuf field: bytes pubkey = 2 */ pubkey: Uint8Array; } @@ -509,7 +508,7 @@ export interface ImportAccountRequest { /** * A name to identify the account with. * - * @generated from protobuf field: string name = 1; + * @generated from protobuf field: string name = 1 */ name: string; /** @@ -518,7 +517,7 @@ export interface ImportAccountRequest { * key. It must conform to a derivation path of the form * m/purpose'/coin_type'/account'. * - * @generated from protobuf field: string extended_public_key = 2; + * @generated from protobuf field: string extended_public_key = 2 */ extendedPublicKey: string; /** @@ -528,7 +527,7 @@ export interface ImportAccountRequest { * by some hardware wallets for proper identification and signing. The bytes * must be in big-endian order. * - * @generated from protobuf field: bytes master_key_fingerprint = 3; + * @generated from protobuf field: bytes master_key_fingerprint = 3 */ masterKeyFingerprint: Uint8Array; /** @@ -537,7 +536,7 @@ export interface ImportAccountRequest { * legacy version (xpub, tpub, etc.), such that the wallet cannot detect what * address scheme it belongs to. * - * @generated from protobuf field: walletrpc.AddressType address_type = 4; + * @generated from protobuf field: walletrpc.AddressType address_type = 4 */ addressType: AddressType; /** @@ -548,7 +547,7 @@ export interface ImportAccountRequest { * the account. If these addresses match as expected, then it should be safe to * import the account as is. * - * @generated from protobuf field: bool dry_run = 5; + * @generated from protobuf field: bool dry_run = 5 */ dryRun: boolean; } @@ -559,7 +558,7 @@ export interface ImportAccountResponse { /** * The details of the imported account. * - * @generated from protobuf field: walletrpc.Account account = 1; + * @generated from protobuf field: walletrpc.Account account = 1 */ account?: Account; /** @@ -568,7 +567,7 @@ export interface ImportAccountResponse { * The external branch is typically used for external non-change addresses. * These are only returned if a dry run was specified within the request. * - * @generated from protobuf field: repeated string dry_run_external_addrs = 2; + * @generated from protobuf field: repeated string dry_run_external_addrs = 2 */ dryRunExternalAddrs: string[]; /** @@ -577,7 +576,7 @@ export interface ImportAccountResponse { * The internal branch is typically used for change addresses. These are only * returned if a dry run was specified within the request. * - * @generated from protobuf field: repeated string dry_run_internal_addrs = 3; + * @generated from protobuf field: repeated string dry_run_internal_addrs = 3 */ dryRunInternalAddrs: string[]; } @@ -588,13 +587,13 @@ export interface ImportPublicKeyRequest { /** * A compressed public key represented as raw bytes. * - * @generated from protobuf field: bytes public_key = 1; + * @generated from protobuf field: bytes public_key = 1 */ publicKey: Uint8Array; /** * The type of address that will be generated from the public key. * - * @generated from protobuf field: walletrpc.AddressType address_type = 2; + * @generated from protobuf field: walletrpc.AddressType address_type = 2 */ addressType: AddressType; } @@ -605,7 +604,7 @@ export interface ImportPublicKeyResponse { /** * The status of the import operation. * - * @generated from protobuf field: string status = 1; + * @generated from protobuf field: string status = 1 */ status: string; } @@ -617,7 +616,7 @@ export interface ImportTapscriptRequest { * * The internal public key, serialized as 32-byte x-only public key. * - * @generated from protobuf field: bytes internal_public_key = 1; + * @generated from protobuf field: bytes internal_public_key = 1 */ internalPublicKey: Uint8Array; /** @@ -630,7 +629,7 @@ export interface ImportTapscriptRequest { * The full script tree with all individual leaves is known and the root * hash can be constructed from the full tree directly. * - * @generated from protobuf field: walletrpc.TapscriptFullTree full_tree = 2; + * @generated from protobuf field: walletrpc.TapscriptFullTree full_tree = 2 */ fullTree: TapscriptFullTree; } | { @@ -640,7 +639,7 @@ export interface ImportTapscriptRequest { * Only a single script leaf is known. To construct the root hash, the full * inclusion proof must also be provided. * - * @generated from protobuf field: walletrpc.TapscriptPartialReveal partial_reveal = 3; + * @generated from protobuf field: walletrpc.TapscriptPartialReveal partial_reveal = 3 */ partialReveal: TapscriptPartialReveal; } | { @@ -650,7 +649,7 @@ export interface ImportTapscriptRequest { * Only the root hash of the Taproot script tree (or other form of Taproot * commitment) is known. * - * @generated from protobuf field: bytes root_hash_only = 4; + * @generated from protobuf field: bytes root_hash_only = 4 */ rootHashOnly: Uint8Array; } | { @@ -664,7 +663,7 @@ export interface ImportTapscriptRequest { * tracking arbitrary Taproot outputs without the goal of ever being able * to spend from them through the internal wallet. * - * @generated from protobuf field: bool full_key_only = 5; + * @generated from protobuf field: bool full_key_only = 5 */ fullKeyOnly: boolean; } | { @@ -679,7 +678,7 @@ export interface TapscriptFullTree { * * The complete, ordered list of all tap leaves of the tree. * - * @generated from protobuf field: repeated walletrpc.TapLeaf all_leaves = 1; + * @generated from protobuf field: repeated walletrpc.TapLeaf all_leaves = 1 */ allLeaves: TapLeaf[]; } @@ -690,13 +689,13 @@ export interface TapLeaf { /** * The leaf version. Should be 0xc0 (192) in case of a SegWit v1 script. * - * @generated from protobuf field: uint32 leaf_version = 1; + * @generated from protobuf field: uint32 leaf_version = 1 */ leafVersion: number; /** * The script of the tap leaf. * - * @generated from protobuf field: bytes script = 2; + * @generated from protobuf field: bytes script = 2 */ script: Uint8Array; } @@ -707,7 +706,7 @@ export interface TapscriptPartialReveal { /** * The tap leaf that is known and will be revealed. * - * @generated from protobuf field: walletrpc.TapLeaf revealed_leaf = 1; + * @generated from protobuf field: walletrpc.TapLeaf revealed_leaf = 1 */ revealedLeaf?: TapLeaf; /** @@ -716,7 +715,7 @@ export interface TapscriptPartialReveal { * bytes. If the tree only contained a single leaf (which is the revealed * leaf), this can be empty. * - * @generated from protobuf field: bytes full_inclusion_proof = 2; + * @generated from protobuf field: bytes full_inclusion_proof = 2 */ fullInclusionProof: Uint8Array; } @@ -729,7 +728,7 @@ export interface ImportTapscriptResponse { * The resulting pay-to-Taproot address that represents the imported internal * key with the script committed to it. * - * @generated from protobuf field: string p2tr_address = 1 [json_name = "p2trAddress"]; + * @generated from protobuf field: string p2tr_address = 1 */ p2TrAddress: string; } @@ -743,14 +742,14 @@ export interface Transaction { * specified in raw bytes (or base64 encoded when using REST) and not in hex. * To not break existing software, the field can't simply be renamed. * - * @generated from protobuf field: bytes tx_hex = 1; + * @generated from protobuf field: bytes tx_hex = 1 */ txHex: Uint8Array; /** * * An optional label to save with the transaction. Limited to 500 characters. * - * @generated from protobuf field: string label = 2; + * @generated from protobuf field: string label = 2 */ label: string; } @@ -766,7 +765,7 @@ export interface PublishResponse { * * TODO(roasbeef): map to a proper enum type * - * @generated from protobuf field: string publish_error = 1; + * @generated from protobuf field: string publish_error = 1 */ publishError: string; } @@ -777,7 +776,7 @@ export interface RemoveTransactionResponse { /** * The status of the remove transaction operation. * - * @generated from protobuf field: string status = 1; + * @generated from protobuf field: string status = 1 */ status: string; } @@ -790,39 +789,39 @@ export interface SendOutputsRequest { * The number of satoshis per kilo weight that should be used when crafting * this transaction. * - * @generated from protobuf field: int64 sat_per_kw = 1; + * @generated from protobuf field: int64 sat_per_kw = 1 */ satPerKw: bigint; /** * * A slice of the outputs that should be created in the transaction produced. * - * @generated from protobuf field: repeated signrpc.TxOut outputs = 2; + * @generated from protobuf field: repeated signrpc.TxOut outputs = 2 */ outputs: TxOut[]; /** * An optional label for the transaction, limited to 500 characters. * - * @generated from protobuf field: string label = 3; + * @generated from protobuf field: string label = 3 */ label: string; /** * The minimum number of confirmations each one of your outputs used for * the transaction must satisfy. * - * @generated from protobuf field: int32 min_confs = 4; + * @generated from protobuf field: int32 min_confs = 4 */ minConfs: number; /** * Whether unconfirmed outputs should be used as inputs for the transaction. * - * @generated from protobuf field: bool spend_unconfirmed = 5; + * @generated from protobuf field: bool spend_unconfirmed = 5 */ spendUnconfirmed: boolean; /** * The strategy to use for selecting coins during sending the outputs. * - * @generated from protobuf field: lnrpc.CoinSelectionStrategy coin_selection_strategy = 6; + * @generated from protobuf field: lnrpc.CoinSelectionStrategy coin_selection_strategy = 6 */ coinSelectionStrategy: CoinSelectionStrategy; } @@ -834,7 +833,7 @@ export interface SendOutputsResponse { * * The serialized transaction sent out on the network. * - * @generated from protobuf field: bytes raw_tx = 1; + * @generated from protobuf field: bytes raw_tx = 1 */ rawTx: Uint8Array; } @@ -846,7 +845,7 @@ export interface EstimateFeeRequest { * * The number of confirmations to shoot for when estimating the fee. * - * @generated from protobuf field: int32 conf_target = 1; + * @generated from protobuf field: int32 conf_target = 1 */ confTarget: number; } @@ -859,13 +858,13 @@ export interface EstimateFeeResponse { * The amount of satoshis per kw that should be used in order to reach the * confirmation target in the request. * - * @generated from protobuf field: int64 sat_per_kw = 1; + * @generated from protobuf field: int64 sat_per_kw = 1 */ satPerKw: bigint; /** * The current minimum relay fee based on our chain backend in sat/kw. * - * @generated from protobuf field: int64 min_relay_fee_sat_per_kw = 2; + * @generated from protobuf field: int64 min_relay_fee_sat_per_kw = 2 */ minRelayFeeSatPerKw: bigint; } @@ -876,19 +875,19 @@ export interface PendingSweep { /** * The outpoint of the output we're attempting to sweep. * - * @generated from protobuf field: lnrpc.OutPoint outpoint = 1; + * @generated from protobuf field: lnrpc.OutPoint outpoint = 1 */ outpoint?: OutPoint; /** * The witness type of the output we're attempting to sweep. * - * @generated from protobuf field: walletrpc.WitnessType witness_type = 2; + * @generated from protobuf field: walletrpc.WitnessType witness_type = 2 */ witnessType: WitnessType; /** * The value of the output we're attempting to sweep. * - * @generated from protobuf field: uint32 amount_sat = 3; + * @generated from protobuf field: uint32 amount_sat = 3 */ amountSat: number; /** @@ -899,13 +898,13 @@ export interface PendingSweep { * created, so it's possible for this to be 0 before this. * * @deprecated - * @generated from protobuf field: uint32 sat_per_byte = 4 [deprecated = true]; + * @generated from protobuf field: uint32 sat_per_byte = 4 [deprecated = true] */ satPerByte: number; /** * The number of broadcast attempts we've made to sweep the output. * - * @generated from protobuf field: uint32 broadcast_attempts = 5; + * @generated from protobuf field: uint32 broadcast_attempts = 5 */ broadcastAttempts: number; /** @@ -915,7 +914,7 @@ export interface PendingSweep { * sweep transaction of the output. * * @deprecated - * @generated from protobuf field: uint32 next_broadcast_height = 6 [deprecated = true]; + * @generated from protobuf field: uint32 next_broadcast_height = 6 [deprecated = true] */ nextBroadcastHeight: number; /** @@ -925,7 +924,7 @@ export interface PendingSweep { * immediately. * * @deprecated - * @generated from protobuf field: bool force = 7 [deprecated = true]; + * @generated from protobuf field: bool force = 7 [deprecated = true] */ force: boolean; /** @@ -935,7 +934,7 @@ export interface PendingSweep { * used by the sweeper. * * @deprecated - * @generated from protobuf field: uint32 requested_conf_target = 8 [deprecated = true]; + * @generated from protobuf field: uint32 requested_conf_target = 8 [deprecated = true] */ requestedConfTarget: number; /** @@ -943,7 +942,7 @@ export interface PendingSweep { * The requested fee rate, expressed in sat/vbyte, for this output. * * @deprecated - * @generated from protobuf field: uint32 requested_sat_per_byte = 9 [deprecated = true]; + * @generated from protobuf field: uint32 requested_sat_per_byte = 9 [deprecated = true] */ requestedSatPerByte: number; /** @@ -952,21 +951,21 @@ export interface PendingSweep { * The fee rate is only determined once a sweeping transaction for the output * is created, so it's possible for this to be 0 before this. * - * @generated from protobuf field: uint64 sat_per_vbyte = 10; + * @generated from protobuf field: uint64 sat_per_vbyte = 10 */ satPerVbyte: bigint; /** * The requested starting fee rate, expressed in sat/vbyte, for this * output. When not requested, this field will be 0. * - * @generated from protobuf field: uint64 requested_sat_per_vbyte = 11; + * @generated from protobuf field: uint64 requested_sat_per_vbyte = 11 */ requestedSatPerVbyte: bigint; /** * * Whether this input will be swept immediately. * - * @generated from protobuf field: bool immediate = 12; + * @generated from protobuf field: bool immediate = 12 */ immediate: boolean; /** @@ -974,16 +973,24 @@ export interface PendingSweep { * The budget for this sweep, expressed in satoshis. This is the maximum amount * that can be spent as fees to sweep this output. * - * @generated from protobuf field: uint64 budget = 13; + * @generated from protobuf field: uint64 budget = 13 */ budget: bigint; /** * * The deadline height used for this output when perform fee bumping. * - * @generated from protobuf field: uint32 deadline_height = 14; + * @generated from protobuf field: uint32 deadline_height = 14 */ deadlineHeight: number; + /** + * + * The block height which the input's locktime will expire at. Zero if the + * input has no locktime. + * + * @generated from protobuf field: uint32 maturity_height = 15 + */ + maturityHeight: number; } /** * @generated from protobuf message walletrpc.PendingSweepsRequest @@ -998,7 +1005,7 @@ export interface PendingSweepsResponse { * * The set of outputs currently being swept by lnd's central batching engine. * - * @generated from protobuf field: repeated walletrpc.PendingSweep pending_sweeps = 1; + * @generated from protobuf field: repeated walletrpc.PendingSweep pending_sweeps = 1 */ pendingSweeps: PendingSweep[]; } @@ -1009,15 +1016,14 @@ export interface BumpFeeRequest { /** * The input we're attempting to bump the fee of. * - * @generated from protobuf field: lnrpc.OutPoint outpoint = 1; + * @generated from protobuf field: lnrpc.OutPoint outpoint = 1 */ outpoint?: OutPoint; /** - * Optional. The deadline in number of blocks that the input should be spent - * within. When not set, for new inputs, the default value (1008) is used; - * for existing inputs, their current values will be retained. + * Optional. The conf target the underlying fee estimator will use to + * estimate the starting fee rate for the fee function. * - * @generated from protobuf field: uint32 target_conf = 2; + * @generated from protobuf field: uint32 target_conf = 2 */ targetConf: number; /** @@ -1027,7 +1033,7 @@ export interface BumpFeeRequest { * with. * * @deprecated - * @generated from protobuf field: uint32 sat_per_byte = 3 [deprecated = true]; + * @generated from protobuf field: uint32 sat_per_byte = 3 [deprecated = true] */ satPerByte: number; /** @@ -1037,7 +1043,7 @@ export interface BumpFeeRequest { * immediately. * * @deprecated - * @generated from protobuf field: bool force = 4 [deprecated = true]; + * @generated from protobuf field: bool force = 4 [deprecated = true] */ force: boolean; /** @@ -1047,15 +1053,15 @@ export interface BumpFeeRequest { * fee function as its starting fee rate. When not set, the sweeper will use * the estimated fee rate using the `target_conf` as the starting fee rate. * - * @generated from protobuf field: uint64 sat_per_vbyte = 5; + * @generated from protobuf field: uint64 sat_per_vbyte = 5 */ satPerVbyte: bigint; /** * * Optional. Whether this input will be swept immediately. When set to true, - * the sweeper will sweep this input without waiting for the next batch. + * the sweeper will sweep this input without waiting for the next block. * - * @generated from protobuf field: bool immediate = 6; + * @generated from protobuf field: bool immediate = 6 */ immediate: boolean; /** @@ -1067,9 +1073,18 @@ export interface BumpFeeRequest { * budget for fee bumping; for existing inputs, their current budgets will be * retained. * - * @generated from protobuf field: uint64 budget = 7; + * @generated from protobuf field: uint64 budget = 7 */ budget: bigint; + /** + * Optional. The deadline delta in number of blocks that the output + * should be spent within. This translates internally to the width of the + * fee function that the sweeper will use to bump the fee rate. When the + * deadline is reached, ALL the budget will be spent as fees. + * + * @generated from protobuf field: uint32 deadline_delta = 8 + */ + deadlineDelta: number; } /** * @generated from protobuf message walletrpc.BumpFeeResponse @@ -1078,7 +1093,7 @@ export interface BumpFeeResponse { /** * The status of the bump fee operation. * - * @generated from protobuf field: string status = 1; + * @generated from protobuf field: string status = 1 */ status: string; } @@ -1090,14 +1105,15 @@ export interface BumpForceCloseFeeRequest { * The channel point which force close transaction we are attempting to * bump the fee rate for. * - * @generated from protobuf field: lnrpc.ChannelPoint chan_point = 1; + * @generated from protobuf field: lnrpc.ChannelPoint chan_point = 1 */ chanPoint?: ChannelPoint; /** * Optional. The deadline delta in number of blocks that the anchor output - * should be spent within to bump the closing transaction. + * should be spent within to bump the closing transaction. When the + * deadline is reached, ALL the budget will be spent as fees * - * @generated from protobuf field: uint32 deadline_delta = 2; + * @generated from protobuf field: uint32 deadline_delta = 2 */ deadlineDelta: number; /** @@ -1107,7 +1123,7 @@ export interface BumpForceCloseFeeRequest { * the sweeper will use the estimated fee rate using the target_conf as the * starting fee rate. * - * @generated from protobuf field: uint64 starting_feerate = 3; + * @generated from protobuf field: uint64 starting_feerate = 3 */ startingFeerate: bigint; /** @@ -1117,7 +1133,7 @@ export interface BumpForceCloseFeeRequest { * trigger new batch transactions including the sweeping of the anchor output * related to the selected force close transaction. * - * @generated from protobuf field: bool immediate = 4; + * @generated from protobuf field: bool immediate = 4 */ immediate: boolean; /** @@ -1128,9 +1144,16 @@ export interface BumpForceCloseFeeRequest { * this value has to be set to an appropriate amount to pay for the cpfp * transaction of the force closed channel otherwise the fee bumping will fail. * - * @generated from protobuf field: uint64 budget = 5; + * @generated from protobuf field: uint64 budget = 5 */ budget: bigint; + /** + * Optional. The conf target the underlying fee estimator will use to + * estimate the starting fee rate for the fee function. + * + * @generated from protobuf field: uint32 target_conf = 6 + */ + targetConf: number; } /** * @generated from protobuf message walletrpc.BumpForceCloseFeeResponse @@ -1139,7 +1162,7 @@ export interface BumpForceCloseFeeResponse { /** * The status of the force close fee bump operation. * - * @generated from protobuf field: string status = 1; + * @generated from protobuf field: string status = 1 */ status: string; } @@ -1153,7 +1176,7 @@ export interface ListSweepsRequest { * will be returned. Note that some sweeps that LND publishes will have been * replaced-by-fee, so will not be included in this output. * - * @generated from protobuf field: bool verbose = 1; + * @generated from protobuf field: bool verbose = 1 */ verbose: boolean; /** @@ -1162,7 +1185,7 @@ export interface ListSweepsRequest { * result will start from the earliest sweep. If set to -1 the result will * only include unconfirmed sweeps (at the time of the call). * - * @generated from protobuf field: int32 start_height = 2; + * @generated from protobuf field: int32 start_height = 2 */ startHeight: number; } @@ -1176,13 +1199,13 @@ export interface ListSweepsResponse { sweeps: { oneofKind: "transactionDetails"; /** - * @generated from protobuf field: lnrpc.TransactionDetails transaction_details = 1; + * @generated from protobuf field: lnrpc.TransactionDetails transaction_details = 1 */ transactionDetails: TransactionDetails; } | { oneofKind: "transactionIds"; /** - * @generated from protobuf field: walletrpc.ListSweepsResponse.TransactionIDs transaction_ids = 2; + * @generated from protobuf field: walletrpc.ListSweepsResponse.TransactionIDs transaction_ids = 2 */ transactionIds: ListSweepsResponse_TransactionIDs; } | { @@ -1199,7 +1222,7 @@ export interface ListSweepsResponse_TransactionIDs { * sweeps that our node has broadcast. Note that these transactions may * not have confirmed yet, we record sweeps on broadcast, not confirmation. * - * @generated from protobuf field: repeated string transaction_ids = 1; + * @generated from protobuf field: repeated string transaction_ids = 1 */ transactionIds: string[]; } @@ -1211,19 +1234,19 @@ export interface LabelTransactionRequest { * The txid of the transaction to label. Note: When using gRPC, the bytes * must be in little-endian (reverse) order. * - * @generated from protobuf field: bytes txid = 1; + * @generated from protobuf field: bytes txid = 1 */ txid: Uint8Array; /** * The label to add to the transaction, limited to 500 characters. * - * @generated from protobuf field: string label = 2; + * @generated from protobuf field: string label = 2 */ label: string; /** * Whether to overwrite the existing label, if it is present. * - * @generated from protobuf field: bool overwrite = 3; + * @generated from protobuf field: bool overwrite = 3 */ overwrite: boolean; } @@ -1234,7 +1257,7 @@ export interface LabelTransactionResponse { /** * The status of the label operation. * - * @generated from protobuf field: string status = 1; + * @generated from protobuf field: string status = 1 */ status: string; } @@ -1258,7 +1281,7 @@ export interface FundPsbtRequest { * of all outputs to pay a miner fee with the specified fee rate. A change * output is added to the PSBT if necessary. * - * @generated from protobuf field: bytes psbt = 1; + * @generated from protobuf field: bytes psbt = 1 */ psbt: Uint8Array; } | { @@ -1267,7 +1290,7 @@ export interface FundPsbtRequest { * * Use the outputs and optional inputs from this raw template. * - * @generated from protobuf field: walletrpc.TxTemplate raw = 2; + * @generated from protobuf field: walletrpc.TxTemplate raw = 2 */ raw: TxTemplate; } | { @@ -1291,7 +1314,7 @@ export interface FundPsbtRequest { * output, given there is any non-dust change). This can be identified by * the returned locked UTXOs being empty. * - * @generated from protobuf field: walletrpc.PsbtCoinSelect coin_select = 9; + * @generated from protobuf field: walletrpc.PsbtCoinSelect coin_select = 9 */ coinSelect: PsbtCoinSelect; } | { @@ -1306,7 +1329,7 @@ export interface FundPsbtRequest { * * The target number of blocks that the transaction should be confirmed in. * - * @generated from protobuf field: uint32 target_conf = 3; + * @generated from protobuf field: uint32 target_conf = 3 */ targetConf: number; } | { @@ -1316,7 +1339,7 @@ export interface FundPsbtRequest { * The fee rate, expressed in sat/vbyte, that should be used to spend the * input with. * - * @generated from protobuf field: uint64 sat_per_vbyte = 4; + * @generated from protobuf field: uint64 sat_per_vbyte = 4 */ satPerVbyte: bigint; } | { @@ -1326,7 +1349,7 @@ export interface FundPsbtRequest { * The fee rate, expressed in sat/kWU, that should be used to spend the * input with. * - * @generated from protobuf field: uint64 sat_per_kw = 11; + * @generated from protobuf field: uint64 sat_per_kw = 11 */ satPerKw: bigint; } | { @@ -1337,20 +1360,20 @@ export interface FundPsbtRequest { * The name of the account to fund the PSBT with. If empty, the default wallet * account is used. * - * @generated from protobuf field: string account = 5; + * @generated from protobuf field: string account = 5 */ account: string; /** * The minimum number of confirmations each one of your outputs used for * the transaction must satisfy. * - * @generated from protobuf field: int32 min_confs = 6; + * @generated from protobuf field: int32 min_confs = 6 */ minConfs: number; /** * Whether unconfirmed outputs should be used as inputs for the transaction. * - * @generated from protobuf field: bool spend_unconfirmed = 7; + * @generated from protobuf field: bool spend_unconfirmed = 7 */ spendUnconfirmed: boolean; /** @@ -1359,21 +1382,37 @@ export interface FundPsbtRequest { * accounts, no change type should be provided as the coin selection key * scope will always be used to generate the change address. * - * @generated from protobuf field: walletrpc.ChangeAddressType change_type = 8; + * @generated from protobuf field: walletrpc.ChangeAddressType change_type = 8 */ changeType: ChangeAddressType; /** * The strategy to use for selecting coins during funding the PSBT. * - * @generated from protobuf field: lnrpc.CoinSelectionStrategy coin_selection_strategy = 10; + * @generated from protobuf field: lnrpc.CoinSelectionStrategy coin_selection_strategy = 10 */ coinSelectionStrategy: CoinSelectionStrategy; /** * The max fee to total output amount ratio that this psbt should adhere to. * - * @generated from protobuf field: double max_fee_ratio = 12; + * @generated from protobuf field: double max_fee_ratio = 12 */ maxFeeRatio: number; + /** + * The custom lock ID to use for the inputs in the funded PSBT. The value + * if set must be exactly 32 bytes long. If empty, the default lock ID will + * be used. + * + * @generated from protobuf field: bytes custom_lock_id = 13 + */ + customLockId: Uint8Array; + /** + * If set, then the inputs in the funded PSBT will be locked for the + * specified duration. The lock duration is specified in seconds. If not + * set, the default lock duration will be used. + * + * @generated from protobuf field: uint64 lock_expiration_seconds = 14 + */ + lockExpirationSeconds: bigint; } /** * @generated from protobuf message walletrpc.FundPsbtResponse @@ -1383,14 +1422,14 @@ export interface FundPsbtResponse { * * The funded but not yet signed PSBT packet. * - * @generated from protobuf field: bytes funded_psbt = 1; + * @generated from protobuf field: bytes funded_psbt = 1 */ fundedPsbt: Uint8Array; /** * * The index of the added change output or -1 if no change was left over. * - * @generated from protobuf field: int32 change_output_index = 2; + * @generated from protobuf field: int32 change_output_index = 2 */ changeOutputIndex: number; /** @@ -1399,7 +1438,7 @@ export interface FundPsbtResponse { * packet. Only inputs added to the PSBT by this RPC are locked, inputs that * were already present in the PSBT are not locked. * - * @generated from protobuf field: repeated walletrpc.UtxoLease locked_utxos = 3; + * @generated from protobuf field: repeated walletrpc.UtxoLease locked_utxos = 3 */ lockedUtxos: UtxoLease[]; } @@ -1417,14 +1456,14 @@ export interface TxTemplate { * If no inputs are specified, coin selection will be performed instead and * inputs of sufficient value will be added to the resulting PSBT. * - * @generated from protobuf field: repeated lnrpc.OutPoint inputs = 1; + * @generated from protobuf field: repeated lnrpc.OutPoint inputs = 1 */ inputs: OutPoint[]; /** * * A map of all addresses and the amounts to send to in the funded PSBT. * - * @generated from protobuf field: map outputs = 2; + * @generated from protobuf field: map outputs = 2 */ outputs: { [key: string]: bigint; @@ -1446,7 +1485,7 @@ export interface PsbtCoinSelect { * PSBT must already be locked (if they belong to this node), only newly added * inputs will be locked by this RPC. * - * @generated from protobuf field: bytes psbt = 1; + * @generated from protobuf field: bytes psbt = 1 */ psbt: Uint8Array; /** @@ -1462,7 +1501,7 @@ export interface PsbtCoinSelect { * the PSBT, set the "add" field below instead. The type of change output * added is defined by change_type in the parent message. * - * @generated from protobuf field: int32 existing_output_index = 2; + * @generated from protobuf field: int32 existing_output_index = 2 */ existingOutputIndex: number; } | { @@ -1472,7 +1511,7 @@ export interface PsbtCoinSelect { * Add a new change output to the PSBT using the change_type specified in * the parent message. * - * @generated from protobuf field: bool add = 3; + * @generated from protobuf field: bool add = 3 */ add: boolean; } | { @@ -1487,34 +1526,34 @@ export interface UtxoLease { * * A 32 byte random ID that identifies the lease. * - * @generated from protobuf field: bytes id = 1; + * @generated from protobuf field: bytes id = 1 */ id: Uint8Array; /** * The identifying outpoint of the output being leased. * - * @generated from protobuf field: lnrpc.OutPoint outpoint = 2; + * @generated from protobuf field: lnrpc.OutPoint outpoint = 2 */ outpoint?: OutPoint; /** * * The absolute expiration of the output lease represented as a unix timestamp. * - * @generated from protobuf field: uint64 expiration = 3; + * @generated from protobuf field: uint64 expiration = 3 */ expiration: bigint; /** * * The public key script of the leased output. * - * @generated from protobuf field: bytes pk_script = 4; + * @generated from protobuf field: bytes pk_script = 4 */ pkScript: Uint8Array; /** * * The value of the leased output in satoshis. * - * @generated from protobuf field: uint64 value = 5; + * @generated from protobuf field: uint64 value = 5 */ value: bigint; } @@ -1527,7 +1566,7 @@ export interface SignPsbtRequest { * The PSBT that should be signed. The PSBT must contain all required inputs, * outputs, UTXO data and custom fields required to identify the signing key. * - * @generated from protobuf field: bytes funded_psbt = 1; + * @generated from protobuf field: bytes funded_psbt = 1 */ fundedPsbt: Uint8Array; } @@ -1538,13 +1577,13 @@ export interface SignPsbtResponse { /** * The signed transaction in PSBT format. * - * @generated from protobuf field: bytes signed_psbt = 1; + * @generated from protobuf field: bytes signed_psbt = 1 */ signedPsbt: Uint8Array; /** * The indices of signed inputs. * - * @generated from protobuf field: repeated uint32 signed_inputs = 2; + * @generated from protobuf field: repeated uint32 signed_inputs = 2 */ signedInputs: number[]; } @@ -1558,7 +1597,7 @@ export interface FinalizePsbtRequest { * required inputs, outputs, UTXO data and partial signatures of all other * signers. * - * @generated from protobuf field: bytes funded_psbt = 1; + * @generated from protobuf field: bytes funded_psbt = 1 */ fundedPsbt: Uint8Array; /** @@ -1566,7 +1605,7 @@ export interface FinalizePsbtRequest { * The name of the account to finalize the PSBT with. If empty, the default * wallet account is used. * - * @generated from protobuf field: string account = 5; + * @generated from protobuf field: string account = 5 */ account: string; } @@ -1577,13 +1616,13 @@ export interface FinalizePsbtResponse { /** * The fully signed and finalized transaction in PSBT format. * - * @generated from protobuf field: bytes signed_psbt = 1; + * @generated from protobuf field: bytes signed_psbt = 1 */ signedPsbt: Uint8Array; /** * The fully signed and finalized transaction in the raw wire format. * - * @generated from protobuf field: bytes raw_final_tx = 2; + * @generated from protobuf field: bytes raw_final_tx = 2 */ rawFinalTx: Uint8Array; } @@ -1599,7 +1638,7 @@ export interface ListLeasesResponse { /** * The list of currently leased utxos. * - * @generated from protobuf field: repeated walletrpc.UtxoLease locked_utxos = 1; + * @generated from protobuf field: repeated walletrpc.UtxoLease locked_utxos = 1 */ lockedUtxos: UtxoLease[]; } @@ -1986,8 +2025,11 @@ class ListUnspentRequest$Type extends MessageType { ]); } create(value?: PartialMessage): ListUnspentRequest { - const message = { minConfs: 0, maxConfs: 0, account: "", unconfirmedOnly: false }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.minConfs = 0; + message.maxConfs = 0; + message.account = ""; + message.unconfirmedOnly = false; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -2047,12 +2089,12 @@ export const ListUnspentRequest = new ListUnspentRequest$Type(); class ListUnspentResponse$Type extends MessageType { constructor() { super("walletrpc.ListUnspentResponse", [ - { no: 1, name: "utxos", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => Utxo } + { no: 1, name: "utxos", kind: "message", repeat: 2 /*RepeatType.UNPACKED*/, T: () => Utxo } ]); } create(value?: PartialMessage): ListUnspentResponse { - const message = { utxos: [] }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.utxos = []; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -2100,8 +2142,9 @@ class LeaseOutputRequest$Type extends MessageType { ]); } create(value?: PartialMessage): LeaseOutputRequest { - const message = { id: new Uint8Array(0), expirationSeconds: 0n }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.id = new Uint8Array(0); + message.expirationSeconds = 0n; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -2159,8 +2202,8 @@ class LeaseOutputResponse$Type extends MessageType { ]); } create(value?: PartialMessage): LeaseOutputResponse { - const message = { expiration: 0n }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.expiration = 0n; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -2207,8 +2250,8 @@ class ReleaseOutputRequest$Type extends MessageType { ]); } create(value?: PartialMessage): ReleaseOutputRequest { - const message = { id: new Uint8Array(0) }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.id = new Uint8Array(0); if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -2260,8 +2303,8 @@ class ReleaseOutputResponse$Type extends MessageType { ]); } create(value?: PartialMessage): ReleaseOutputResponse { - const message = { status: "" }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.status = ""; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -2308,8 +2351,9 @@ class KeyReq$Type extends MessageType { ]); } create(value?: PartialMessage): KeyReq { - const message = { keyFingerPrint: 0, keyFamily: 0 }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.keyFingerPrint = 0; + message.keyFamily = 0; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -2363,8 +2407,10 @@ class AddrRequest$Type extends MessageType { ]); } create(value?: PartialMessage): AddrRequest { - const message = { account: "", type: 0, change: false }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.account = ""; + message.type = 0; + message.change = false; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -2422,8 +2468,8 @@ class AddrResponse$Type extends MessageType { ]); } create(value?: PartialMessage): AddrResponse { - const message = { addr: "" }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.addr = ""; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -2476,8 +2522,15 @@ class Account$Type extends MessageType { ]); } create(value?: PartialMessage): Account { - const message = { name: "", addressType: 0, extendedPublicKey: "", masterKeyFingerprint: new Uint8Array(0), derivationPath: "", externalKeyCount: 0, internalKeyCount: 0, watchOnly: false }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.name = ""; + message.addressType = 0; + message.extendedPublicKey = ""; + message.masterKeyFingerprint = new Uint8Array(0); + message.derivationPath = ""; + message.externalKeyCount = 0; + message.internalKeyCount = 0; + message.watchOnly = false; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -2569,8 +2622,12 @@ class AddressProperty$Type extends MessageType { ]); } create(value?: PartialMessage): AddressProperty { - const message = { address: "", isInternal: false, balance: 0n, derivationPath: "", publicKey: new Uint8Array(0) }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.address = ""; + message.isInternal = false; + message.balance = 0n; + message.derivationPath = ""; + message.publicKey = new Uint8Array(0); if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -2639,12 +2696,15 @@ class AccountWithAddresses$Type extends MessageType { { no: 1, name: "name", kind: "scalar", T: 9 /*ScalarType.STRING*/ }, { no: 2, name: "address_type", kind: "enum", T: () => ["walletrpc.AddressType", AddressType] }, { no: 3, name: "derivation_path", kind: "scalar", T: 9 /*ScalarType.STRING*/ }, - { no: 4, name: "addresses", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => AddressProperty } + { no: 4, name: "addresses", kind: "message", repeat: 2 /*RepeatType.UNPACKED*/, T: () => AddressProperty } ]); } create(value?: PartialMessage): AccountWithAddresses { - const message = { name: "", addressType: 0, derivationPath: "", addresses: [] }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.name = ""; + message.addressType = 0; + message.derivationPath = ""; + message.addresses = []; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -2709,8 +2769,9 @@ class ListAccountsRequest$Type extends MessageType { ]); } create(value?: PartialMessage): ListAccountsRequest { - const message = { name: "", addressType: 0 }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.name = ""; + message.addressType = 0; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -2758,12 +2819,12 @@ export const ListAccountsRequest = new ListAccountsRequest$Type(); class ListAccountsResponse$Type extends MessageType { constructor() { super("walletrpc.ListAccountsResponse", [ - { no: 1, name: "accounts", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => Account } + { no: 1, name: "accounts", kind: "message", repeat: 2 /*RepeatType.UNPACKED*/, T: () => Account } ]); } create(value?: PartialMessage): ListAccountsResponse { - const message = { accounts: [] }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.accounts = []; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -2809,8 +2870,8 @@ class RequiredReserveRequest$Type extends MessageType { ]); } create(value?: PartialMessage): RequiredReserveRequest { - const message = { additionalPublicChannels: 0 }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.additionalPublicChannels = 0; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -2856,8 +2917,8 @@ class RequiredReserveResponse$Type extends MessageType ]); } create(value?: PartialMessage): RequiredReserveResponse { - const message = { requiredReserve: 0n }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.requiredReserve = 0n; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -2904,8 +2965,9 @@ class ListAddressesRequest$Type extends MessageType { ]); } create(value?: PartialMessage): ListAddressesRequest { - const message = { accountName: "", showCustomAccounts: false }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.accountName = ""; + message.showCustomAccounts = false; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -2953,12 +3015,12 @@ export const ListAddressesRequest = new ListAddressesRequest$Type(); class ListAddressesResponse$Type extends MessageType { constructor() { super("walletrpc.ListAddressesResponse", [ - { no: 1, name: "account_with_addresses", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => AccountWithAddresses } + { no: 1, name: "account_with_addresses", kind: "message", repeat: 2 /*RepeatType.UNPACKED*/, T: () => AccountWithAddresses } ]); } create(value?: PartialMessage): ListAddressesResponse { - const message = { accountWithAddresses: [] }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.accountWithAddresses = []; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -3004,8 +3066,8 @@ class GetTransactionRequest$Type extends MessageType { ]); } create(value?: PartialMessage): GetTransactionRequest { - const message = { txid: "" }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.txid = ""; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -3052,8 +3114,9 @@ class SignMessageWithAddrRequest$Type extends MessageType): SignMessageWithAddrRequest { - const message = { msg: new Uint8Array(0), addr: "" }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.msg = new Uint8Array(0); + message.addr = ""; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -3105,8 +3168,8 @@ class SignMessageWithAddrResponse$Type extends MessageType): SignMessageWithAddrResponse { - const message = { signature: "" }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.signature = ""; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -3154,8 +3217,10 @@ class VerifyMessageWithAddrRequest$Type extends MessageType): VerifyMessageWithAddrRequest { - const message = { msg: new Uint8Array(0), signature: "", addr: "" }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.msg = new Uint8Array(0); + message.signature = ""; + message.addr = ""; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -3214,8 +3279,9 @@ class VerifyMessageWithAddrResponse$Type extends MessageType): VerifyMessageWithAddrResponse { - const message = { valid: false, pubkey: new Uint8Array(0) }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.valid = false; + message.pubkey = new Uint8Array(0); if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -3271,8 +3337,12 @@ class ImportAccountRequest$Type extends MessageType { ]); } create(value?: PartialMessage): ImportAccountRequest { - const message = { name: "", extendedPublicKey: "", masterKeyFingerprint: new Uint8Array(0), addressType: 0, dryRun: false }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.name = ""; + message.extendedPublicKey = ""; + message.masterKeyFingerprint = new Uint8Array(0); + message.addressType = 0; + message.dryRun = false; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -3344,8 +3414,9 @@ class ImportAccountResponse$Type extends MessageType { ]); } create(value?: PartialMessage): ImportAccountResponse { - const message = { dryRunExternalAddrs: [], dryRunInternalAddrs: [] }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.dryRunExternalAddrs = []; + message.dryRunInternalAddrs = []; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -3404,8 +3475,9 @@ class ImportPublicKeyRequest$Type extends MessageType { ]); } create(value?: PartialMessage): ImportPublicKeyRequest { - const message = { publicKey: new Uint8Array(0), addressType: 0 }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.publicKey = new Uint8Array(0); + message.addressType = 0; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -3457,8 +3529,8 @@ class ImportPublicKeyResponse$Type extends MessageType ]); } create(value?: PartialMessage): ImportPublicKeyResponse { - const message = { status: "" }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.status = ""; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -3508,8 +3580,9 @@ class ImportTapscriptRequest$Type extends MessageType { ]); } create(value?: PartialMessage): ImportTapscriptRequest { - const message = { internalPublicKey: new Uint8Array(0), script: { oneofKind: undefined } }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.internalPublicKey = new Uint8Array(0); + message.script = { oneofKind: undefined }; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -3587,12 +3660,12 @@ export const ImportTapscriptRequest = new ImportTapscriptRequest$Type(); class TapscriptFullTree$Type extends MessageType { constructor() { super("walletrpc.TapscriptFullTree", [ - { no: 1, name: "all_leaves", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => TapLeaf } + { no: 1, name: "all_leaves", kind: "message", repeat: 2 /*RepeatType.UNPACKED*/, T: () => TapLeaf } ]); } create(value?: PartialMessage): TapscriptFullTree { - const message = { allLeaves: [] }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.allLeaves = []; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -3639,8 +3712,9 @@ class TapLeaf$Type extends MessageType { ]); } create(value?: PartialMessage): TapLeaf { - const message = { leafVersion: 0, script: new Uint8Array(0) }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.leafVersion = 0; + message.script = new Uint8Array(0); if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -3693,8 +3767,8 @@ class TapscriptPartialReveal$Type extends MessageType { ]); } create(value?: PartialMessage): TapscriptPartialReveal { - const message = { fullInclusionProof: new Uint8Array(0) }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.fullInclusionProof = new Uint8Array(0); if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -3746,8 +3820,8 @@ class ImportTapscriptResponse$Type extends MessageType ]); } create(value?: PartialMessage): ImportTapscriptResponse { - const message = { p2TrAddress: "" }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.p2TrAddress = ""; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -3757,7 +3831,7 @@ class ImportTapscriptResponse$Type extends MessageType while (reader.pos < end) { let [fieldNo, wireType] = reader.tag(); switch (fieldNo) { - case /* string p2tr_address = 1 [json_name = "p2trAddress"];*/ 1: + case /* string p2tr_address */ 1: message.p2TrAddress = reader.string(); break; default: @@ -3772,7 +3846,7 @@ class ImportTapscriptResponse$Type extends MessageType return message; } internalBinaryWrite(message: ImportTapscriptResponse, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter { - /* string p2tr_address = 1 [json_name = "p2trAddress"]; */ + /* string p2tr_address = 1; */ if (message.p2TrAddress !== "") writer.tag(1, WireType.LengthDelimited).string(message.p2TrAddress); let u = options.writeUnknownFields; @@ -3794,8 +3868,9 @@ class Transaction$Type extends MessageType { ]); } create(value?: PartialMessage): Transaction { - const message = { txHex: new Uint8Array(0), label: "" }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.txHex = new Uint8Array(0); + message.label = ""; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -3847,8 +3922,8 @@ class PublishResponse$Type extends MessageType { ]); } create(value?: PartialMessage): PublishResponse { - const message = { publishError: "" }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.publishError = ""; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -3894,8 +3969,8 @@ class RemoveTransactionResponse$Type extends MessageType): RemoveTransactionResponse { - const message = { status: "" }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.status = ""; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -3938,7 +4013,7 @@ class SendOutputsRequest$Type extends MessageType { constructor() { super("walletrpc.SendOutputsRequest", [ { no: 1, name: "sat_per_kw", kind: "scalar", T: 3 /*ScalarType.INT64*/, L: 0 /*LongType.BIGINT*/ }, - { no: 2, name: "outputs", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => TxOut }, + { no: 2, name: "outputs", kind: "message", repeat: 2 /*RepeatType.UNPACKED*/, T: () => TxOut }, { no: 3, name: "label", kind: "scalar", T: 9 /*ScalarType.STRING*/ }, { no: 4, name: "min_confs", kind: "scalar", T: 5 /*ScalarType.INT32*/ }, { no: 5, name: "spend_unconfirmed", kind: "scalar", T: 8 /*ScalarType.BOOL*/ }, @@ -3946,8 +4021,13 @@ class SendOutputsRequest$Type extends MessageType { ]); } create(value?: PartialMessage): SendOutputsRequest { - const message = { satPerKw: 0n, outputs: [], label: "", minConfs: 0, spendUnconfirmed: false, coinSelectionStrategy: 0 }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.satPerKw = 0n; + message.outputs = []; + message.label = ""; + message.minConfs = 0; + message.spendUnconfirmed = false; + message.coinSelectionStrategy = 0; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -4023,8 +4103,8 @@ class SendOutputsResponse$Type extends MessageType { ]); } create(value?: PartialMessage): SendOutputsResponse { - const message = { rawTx: new Uint8Array(0) }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.rawTx = new Uint8Array(0); if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -4070,8 +4150,8 @@ class EstimateFeeRequest$Type extends MessageType { ]); } create(value?: PartialMessage): EstimateFeeRequest { - const message = { confTarget: 0 }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.confTarget = 0; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -4118,8 +4198,9 @@ class EstimateFeeResponse$Type extends MessageType { ]); } create(value?: PartialMessage): EstimateFeeResponse { - const message = { satPerKw: 0n, minRelayFeeSatPerKw: 0n }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.satPerKw = 0n; + message.minRelayFeeSatPerKw = 0n; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -4180,12 +4261,26 @@ class PendingSweep$Type extends MessageType { { no: 11, name: "requested_sat_per_vbyte", kind: "scalar", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ }, { no: 12, name: "immediate", kind: "scalar", T: 8 /*ScalarType.BOOL*/ }, { no: 13, name: "budget", kind: "scalar", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ }, - { no: 14, name: "deadline_height", kind: "scalar", T: 13 /*ScalarType.UINT32*/ } + { no: 14, name: "deadline_height", kind: "scalar", T: 13 /*ScalarType.UINT32*/ }, + { no: 15, name: "maturity_height", kind: "scalar", T: 13 /*ScalarType.UINT32*/ } ]); } create(value?: PartialMessage): PendingSweep { - const message = { witnessType: 0, amountSat: 0, satPerByte: 0, broadcastAttempts: 0, nextBroadcastHeight: 0, force: false, requestedConfTarget: 0, requestedSatPerByte: 0, satPerVbyte: 0n, requestedSatPerVbyte: 0n, immediate: false, budget: 0n, deadlineHeight: 0 }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.witnessType = 0; + message.amountSat = 0; + message.satPerByte = 0; + message.broadcastAttempts = 0; + message.nextBroadcastHeight = 0; + message.force = false; + message.requestedConfTarget = 0; + message.requestedSatPerByte = 0; + message.satPerVbyte = 0n; + message.requestedSatPerVbyte = 0n; + message.immediate = false; + message.budget = 0n; + message.deadlineHeight = 0; + message.maturityHeight = 0; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -4204,22 +4299,22 @@ class PendingSweep$Type extends MessageType { case /* uint32 amount_sat */ 3: message.amountSat = reader.uint32(); break; - case /* uint32 sat_per_byte = 4 [deprecated = true];*/ 4: + case /* uint32 sat_per_byte = 4 [deprecated = true] */ 4: message.satPerByte = reader.uint32(); break; case /* uint32 broadcast_attempts */ 5: message.broadcastAttempts = reader.uint32(); break; - case /* uint32 next_broadcast_height = 6 [deprecated = true];*/ 6: + case /* uint32 next_broadcast_height = 6 [deprecated = true] */ 6: message.nextBroadcastHeight = reader.uint32(); break; - case /* bool force = 7 [deprecated = true];*/ 7: + case /* bool force = 7 [deprecated = true] */ 7: message.force = reader.bool(); break; - case /* uint32 requested_conf_target = 8 [deprecated = true];*/ 8: + case /* uint32 requested_conf_target = 8 [deprecated = true] */ 8: message.requestedConfTarget = reader.uint32(); break; - case /* uint32 requested_sat_per_byte = 9 [deprecated = true];*/ 9: + case /* uint32 requested_sat_per_byte = 9 [deprecated = true] */ 9: message.requestedSatPerByte = reader.uint32(); break; case /* uint64 sat_per_vbyte */ 10: @@ -4237,6 +4332,9 @@ class PendingSweep$Type extends MessageType { case /* uint32 deadline_height */ 14: message.deadlineHeight = reader.uint32(); break; + case /* uint32 maturity_height */ 15: + message.maturityHeight = reader.uint32(); + break; default: let u = options.readUnknownField; if (u === "throw") @@ -4291,6 +4389,9 @@ class PendingSweep$Type extends MessageType { /* uint32 deadline_height = 14; */ if (message.deadlineHeight !== 0) writer.tag(14, WireType.Varint).uint32(message.deadlineHeight); + /* uint32 maturity_height = 15; */ + if (message.maturityHeight !== 0) + writer.tag(15, WireType.Varint).uint32(message.maturityHeight); let u = options.writeUnknownFields; if (u !== false) (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer); @@ -4307,14 +4408,26 @@ class PendingSweepsRequest$Type extends MessageType { super("walletrpc.PendingSweepsRequest", []); } create(value?: PartialMessage): PendingSweepsRequest { - const message = {}; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); if (value !== undefined) reflectionMergePartial(this, message, value); return message; } internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: PendingSweepsRequest): PendingSweepsRequest { - return target ?? this.create(); + let message = target ?? this.create(), end = reader.pos + length; + while (reader.pos < end) { + let [fieldNo, wireType] = reader.tag(); + switch (fieldNo) { + default: + let u = options.readUnknownField; + if (u === "throw") + throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`); + let d = reader.skip(wireType); + if (u !== false) + (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d); + } + } + return message; } internalBinaryWrite(message: PendingSweepsRequest, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter { let u = options.writeUnknownFields; @@ -4331,12 +4444,12 @@ export const PendingSweepsRequest = new PendingSweepsRequest$Type(); class PendingSweepsResponse$Type extends MessageType { constructor() { super("walletrpc.PendingSweepsResponse", [ - { no: 1, name: "pending_sweeps", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => PendingSweep } + { no: 1, name: "pending_sweeps", kind: "message", repeat: 2 /*RepeatType.UNPACKED*/, T: () => PendingSweep } ]); } create(value?: PartialMessage): PendingSweepsResponse { - const message = { pendingSweeps: [] }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.pendingSweeps = []; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -4384,12 +4497,19 @@ class BumpFeeRequest$Type extends MessageType { { no: 4, name: "force", kind: "scalar", T: 8 /*ScalarType.BOOL*/ }, { no: 5, name: "sat_per_vbyte", kind: "scalar", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ }, { no: 6, name: "immediate", kind: "scalar", T: 8 /*ScalarType.BOOL*/ }, - { no: 7, name: "budget", kind: "scalar", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ } + { no: 7, name: "budget", kind: "scalar", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ }, + { no: 8, name: "deadline_delta", kind: "scalar", T: 13 /*ScalarType.UINT32*/ } ]); } create(value?: PartialMessage): BumpFeeRequest { - const message = { targetConf: 0, satPerByte: 0, force: false, satPerVbyte: 0n, immediate: false, budget: 0n }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.targetConf = 0; + message.satPerByte = 0; + message.force = false; + message.satPerVbyte = 0n; + message.immediate = false; + message.budget = 0n; + message.deadlineDelta = 0; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -4405,10 +4525,10 @@ class BumpFeeRequest$Type extends MessageType { case /* uint32 target_conf */ 2: message.targetConf = reader.uint32(); break; - case /* uint32 sat_per_byte = 3 [deprecated = true];*/ 3: + case /* uint32 sat_per_byte = 3 [deprecated = true] */ 3: message.satPerByte = reader.uint32(); break; - case /* bool force = 4 [deprecated = true];*/ 4: + case /* bool force = 4 [deprecated = true] */ 4: message.force = reader.bool(); break; case /* uint64 sat_per_vbyte */ 5: @@ -4420,6 +4540,9 @@ class BumpFeeRequest$Type extends MessageType { case /* uint64 budget */ 7: message.budget = reader.uint64().toBigInt(); break; + case /* uint32 deadline_delta */ 8: + message.deadlineDelta = reader.uint32(); + break; default: let u = options.readUnknownField; if (u === "throw") @@ -4453,6 +4576,9 @@ class BumpFeeRequest$Type extends MessageType { /* uint64 budget = 7; */ if (message.budget !== 0n) writer.tag(7, WireType.Varint).uint64(message.budget); + /* uint32 deadline_delta = 8; */ + if (message.deadlineDelta !== 0) + writer.tag(8, WireType.Varint).uint32(message.deadlineDelta); let u = options.writeUnknownFields; if (u !== false) (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer); @@ -4471,8 +4597,8 @@ class BumpFeeResponse$Type extends MessageType { ]); } create(value?: PartialMessage): BumpFeeResponse { - const message = { status: "" }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.status = ""; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -4518,12 +4644,17 @@ class BumpForceCloseFeeRequest$Type extends MessageType): BumpForceCloseFeeRequest { - const message = { deadlineDelta: 0, startingFeerate: 0n, immediate: false, budget: 0n }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.deadlineDelta = 0; + message.startingFeerate = 0n; + message.immediate = false; + message.budget = 0n; + message.targetConf = 0; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -4548,6 +4679,9 @@ class BumpForceCloseFeeRequest$Type extends MessageType): BumpForceCloseFeeResponse { - const message = { status: "" }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.status = ""; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -4641,8 +4778,9 @@ class ListSweepsRequest$Type extends MessageType { ]); } create(value?: PartialMessage): ListSweepsRequest { - const message = { verbose: false, startHeight: 0 }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.verbose = false; + message.startHeight = 0; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -4695,8 +4833,8 @@ class ListSweepsResponse$Type extends MessageType { ]); } create(value?: PartialMessage): ListSweepsResponse { - const message = { sweeps: { oneofKind: undefined } }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.sweeps = { oneofKind: undefined }; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -4754,8 +4892,8 @@ class ListSweepsResponse_TransactionIDs$Type extends MessageType): ListSweepsResponse_TransactionIDs { - const message = { transactionIds: [] }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.transactionIds = []; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -4803,8 +4941,10 @@ class LabelTransactionRequest$Type extends MessageType ]); } create(value?: PartialMessage): LabelTransactionRequest { - const message = { txid: new Uint8Array(0), label: "", overwrite: false }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.txid = new Uint8Array(0); + message.label = ""; + message.overwrite = false; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -4862,8 +5002,8 @@ class LabelTransactionResponse$Type extends MessageType): LabelTransactionResponse { - const message = { status: "" }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.status = ""; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -4916,12 +5056,23 @@ class FundPsbtRequest$Type extends MessageType { { no: 7, name: "spend_unconfirmed", kind: "scalar", T: 8 /*ScalarType.BOOL*/ }, { no: 8, name: "change_type", kind: "enum", T: () => ["walletrpc.ChangeAddressType", ChangeAddressType, "CHANGE_ADDRESS_TYPE_"] }, { no: 10, name: "coin_selection_strategy", kind: "enum", T: () => ["lnrpc.CoinSelectionStrategy", CoinSelectionStrategy] }, - { no: 12, name: "max_fee_ratio", kind: "scalar", T: 1 /*ScalarType.DOUBLE*/ } + { no: 12, name: "max_fee_ratio", kind: "scalar", T: 1 /*ScalarType.DOUBLE*/ }, + { no: 13, name: "custom_lock_id", kind: "scalar", T: 12 /*ScalarType.BYTES*/ }, + { no: 14, name: "lock_expiration_seconds", kind: "scalar", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ } ]); } create(value?: PartialMessage): FundPsbtRequest { - const message = { template: { oneofKind: undefined }, fees: { oneofKind: undefined }, account: "", minConfs: 0, spendUnconfirmed: false, changeType: 0, coinSelectionStrategy: 0, maxFeeRatio: 0 }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.template = { oneofKind: undefined }; + message.fees = { oneofKind: undefined }; + message.account = ""; + message.minConfs = 0; + message.spendUnconfirmed = false; + message.changeType = 0; + message.coinSelectionStrategy = 0; + message.maxFeeRatio = 0; + message.customLockId = new Uint8Array(0); + message.lockExpirationSeconds = 0n; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -4985,6 +5136,12 @@ class FundPsbtRequest$Type extends MessageType { case /* double max_fee_ratio */ 12: message.maxFeeRatio = reader.double(); break; + case /* bytes custom_lock_id */ 13: + message.customLockId = reader.bytes(); + break; + case /* uint64 lock_expiration_seconds */ 14: + message.lockExpirationSeconds = reader.uint64().toBigInt(); + break; default: let u = options.readUnknownField; if (u === "throw") @@ -5003,18 +5160,12 @@ class FundPsbtRequest$Type extends MessageType { /* walletrpc.TxTemplate raw = 2; */ if (message.template.oneofKind === "raw") TxTemplate.internalBinaryWrite(message.template.raw, writer.tag(2, WireType.LengthDelimited).fork(), options).join(); - /* walletrpc.PsbtCoinSelect coin_select = 9; */ - if (message.template.oneofKind === "coinSelect") - PsbtCoinSelect.internalBinaryWrite(message.template.coinSelect, writer.tag(9, WireType.LengthDelimited).fork(), options).join(); /* uint32 target_conf = 3; */ if (message.fees.oneofKind === "targetConf") writer.tag(3, WireType.Varint).uint32(message.fees.targetConf); /* uint64 sat_per_vbyte = 4; */ if (message.fees.oneofKind === "satPerVbyte") writer.tag(4, WireType.Varint).uint64(message.fees.satPerVbyte); - /* uint64 sat_per_kw = 11; */ - if (message.fees.oneofKind === "satPerKw") - writer.tag(11, WireType.Varint).uint64(message.fees.satPerKw); /* string account = 5; */ if (message.account !== "") writer.tag(5, WireType.LengthDelimited).string(message.account); @@ -5027,12 +5178,24 @@ class FundPsbtRequest$Type extends MessageType { /* walletrpc.ChangeAddressType change_type = 8; */ if (message.changeType !== 0) writer.tag(8, WireType.Varint).int32(message.changeType); + /* walletrpc.PsbtCoinSelect coin_select = 9; */ + if (message.template.oneofKind === "coinSelect") + PsbtCoinSelect.internalBinaryWrite(message.template.coinSelect, writer.tag(9, WireType.LengthDelimited).fork(), options).join(); /* lnrpc.CoinSelectionStrategy coin_selection_strategy = 10; */ if (message.coinSelectionStrategy !== 0) writer.tag(10, WireType.Varint).int32(message.coinSelectionStrategy); + /* uint64 sat_per_kw = 11; */ + if (message.fees.oneofKind === "satPerKw") + writer.tag(11, WireType.Varint).uint64(message.fees.satPerKw); /* double max_fee_ratio = 12; */ if (message.maxFeeRatio !== 0) writer.tag(12, WireType.Bit64).double(message.maxFeeRatio); + /* bytes custom_lock_id = 13; */ + if (message.customLockId.length) + writer.tag(13, WireType.LengthDelimited).bytes(message.customLockId); + /* uint64 lock_expiration_seconds = 14; */ + if (message.lockExpirationSeconds !== 0n) + writer.tag(14, WireType.Varint).uint64(message.lockExpirationSeconds); let u = options.writeUnknownFields; if (u !== false) (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer); @@ -5049,12 +5212,14 @@ class FundPsbtResponse$Type extends MessageType { super("walletrpc.FundPsbtResponse", [ { no: 1, name: "funded_psbt", kind: "scalar", T: 12 /*ScalarType.BYTES*/ }, { no: 2, name: "change_output_index", kind: "scalar", T: 5 /*ScalarType.INT32*/ }, - { no: 3, name: "locked_utxos", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => UtxoLease } + { no: 3, name: "locked_utxos", kind: "message", repeat: 2 /*RepeatType.UNPACKED*/, T: () => UtxoLease } ]); } create(value?: PartialMessage): FundPsbtResponse { - const message = { fundedPsbt: new Uint8Array(0), changeOutputIndex: 0, lockedUtxos: [] }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.fundedPsbt = new Uint8Array(0); + message.changeOutputIndex = 0; + message.lockedUtxos = []; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -5108,13 +5273,14 @@ export const FundPsbtResponse = new FundPsbtResponse$Type(); class TxTemplate$Type extends MessageType { constructor() { super("walletrpc.TxTemplate", [ - { no: 1, name: "inputs", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => OutPoint }, + { no: 1, name: "inputs", kind: "message", repeat: 2 /*RepeatType.UNPACKED*/, T: () => OutPoint }, { no: 2, name: "outputs", kind: "map", K: 9 /*ScalarType.STRING*/, V: { kind: "scalar", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ } } ]); } create(value?: PartialMessage): TxTemplate { - const message = { inputs: [], outputs: {} }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.inputs = []; + message.outputs = {}; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -5152,7 +5318,7 @@ class TxTemplate$Type extends MessageType { case 2: val = reader.uint64().toBigInt(); break; - default: throw new globalThis.Error("unknown map entry field for field walletrpc.TxTemplate.outputs"); + default: throw new globalThis.Error("unknown map entry field for walletrpc.TxTemplate.outputs"); } } map[key ?? ""] = val ?? 0n; @@ -5162,7 +5328,7 @@ class TxTemplate$Type extends MessageType { for (let i = 0; i < message.inputs.length; i++) OutPoint.internalBinaryWrite(message.inputs[i], writer.tag(1, WireType.LengthDelimited).fork(), options).join(); /* map outputs = 2; */ - for (let k of Object.keys(message.outputs)) + for (let k of globalThis.Object.keys(message.outputs)) writer.tag(2, WireType.LengthDelimited).fork().tag(1, WireType.LengthDelimited).string(k).tag(2, WireType.Varint).uint64(message.outputs[k]).join(); let u = options.writeUnknownFields; if (u !== false) @@ -5184,8 +5350,9 @@ class PsbtCoinSelect$Type extends MessageType { ]); } create(value?: PartialMessage): PsbtCoinSelect { - const message = { psbt: new Uint8Array(0), changeOutput: { oneofKind: undefined } }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.psbt = new Uint8Array(0); + message.changeOutput = { oneofKind: undefined }; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -5253,8 +5420,11 @@ class UtxoLease$Type extends MessageType { ]); } create(value?: PartialMessage): UtxoLease { - const message = { id: new Uint8Array(0), expiration: 0n, pkScript: new Uint8Array(0), value: 0n }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.id = new Uint8Array(0); + message.expiration = 0n; + message.pkScript = new Uint8Array(0); + message.value = 0n; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -5324,8 +5494,8 @@ class SignPsbtRequest$Type extends MessageType { ]); } create(value?: PartialMessage): SignPsbtRequest { - const message = { fundedPsbt: new Uint8Array(0) }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.fundedPsbt = new Uint8Array(0); if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -5372,8 +5542,9 @@ class SignPsbtResponse$Type extends MessageType { ]); } create(value?: PartialMessage): SignPsbtResponse { - const message = { signedPsbt: new Uint8Array(0), signedInputs: [] }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.signedPsbt = new Uint8Array(0); + message.signedInputs = []; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -5434,8 +5605,9 @@ class FinalizePsbtRequest$Type extends MessageType { ]); } create(value?: PartialMessage): FinalizePsbtRequest { - const message = { fundedPsbt: new Uint8Array(0), account: "" }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.fundedPsbt = new Uint8Array(0); + message.account = ""; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -5488,8 +5660,9 @@ class FinalizePsbtResponse$Type extends MessageType { ]); } create(value?: PartialMessage): FinalizePsbtResponse { - const message = { signedPsbt: new Uint8Array(0), rawFinalTx: new Uint8Array(0) }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.signedPsbt = new Uint8Array(0); + message.rawFinalTx = new Uint8Array(0); if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -5539,14 +5712,26 @@ class ListLeasesRequest$Type extends MessageType { super("walletrpc.ListLeasesRequest", []); } create(value?: PartialMessage): ListLeasesRequest { - const message = {}; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); if (value !== undefined) reflectionMergePartial(this, message, value); return message; } internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: ListLeasesRequest): ListLeasesRequest { - return target ?? this.create(); + let message = target ?? this.create(), end = reader.pos + length; + while (reader.pos < end) { + let [fieldNo, wireType] = reader.tag(); + switch (fieldNo) { + default: + let u = options.readUnknownField; + if (u === "throw") + throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`); + let d = reader.skip(wireType); + if (u !== false) + (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d); + } + } + return message; } internalBinaryWrite(message: ListLeasesRequest, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter { let u = options.writeUnknownFields; @@ -5563,12 +5748,12 @@ export const ListLeasesRequest = new ListLeasesRequest$Type(); class ListLeasesResponse$Type extends MessageType { constructor() { super("walletrpc.ListLeasesResponse", [ - { no: 1, name: "locked_utxos", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => UtxoLease } + { no: 1, name: "locked_utxos", kind: "message", repeat: 2 /*RepeatType.UNPACKED*/, T: () => UtxoLease } ]); } create(value?: PartialMessage): ListLeasesResponse { - const message = { lockedUtxos: [] }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.lockedUtxos = []; if (value !== undefined) reflectionMergePartial(this, message, value); return message; diff --git a/proto/lnd/walletunlocker.client.ts b/proto/lnd/walletunlocker.client.ts index a3e3d7da..9479e6e4 100644 --- a/proto/lnd/walletunlocker.client.ts +++ b/proto/lnd/walletunlocker.client.ts @@ -1,4 +1,4 @@ -// @generated by protobuf-ts 2.8.1 +// @generated by protobuf-ts 2.11.1 // @generated from protobuf file "walletunlocker.proto" (package "lnrpc", syntax proto3) // tslint:disable import type { RpcTransport } from "@protobuf-ts/runtime-rpc"; @@ -50,7 +50,7 @@ export interface IWalletUnlockerClient { * method should be used to commit the newly generated seed, and create the * wallet. * - * @generated from protobuf rpc: GenSeed(lnrpc.GenSeedRequest) returns (lnrpc.GenSeedResponse); + * @generated from protobuf rpc: GenSeed */ genSeed(input: GenSeedRequest, options?: RpcOptions): UnaryCall; /** @@ -68,7 +68,7 @@ export interface IWalletUnlockerClient { * seed, then present it to the user. Once it has been verified by the user, * the seed can be fed into this RPC in order to commit the new wallet. * - * @generated from protobuf rpc: InitWallet(lnrpc.InitWalletRequest) returns (lnrpc.InitWalletResponse); + * @generated from protobuf rpc: InitWallet */ initWallet(input: InitWalletRequest, options?: RpcOptions): UnaryCall; /** @@ -76,7 +76,7 @@ export interface IWalletUnlockerClient { * UnlockWallet is used at startup of lnd to provide a password to unlock * the wallet database. * - * @generated from protobuf rpc: UnlockWallet(lnrpc.UnlockWalletRequest) returns (lnrpc.UnlockWalletResponse); + * @generated from protobuf rpc: UnlockWallet */ unlockWallet(input: UnlockWalletRequest, options?: RpcOptions): UnaryCall; /** @@ -84,7 +84,7 @@ export interface IWalletUnlockerClient { * ChangePassword changes the password of the encrypted wallet. This will * automatically unlock the wallet database if successful. * - * @generated from protobuf rpc: ChangePassword(lnrpc.ChangePasswordRequest) returns (lnrpc.ChangePasswordResponse); + * @generated from protobuf rpc: ChangePassword */ changePassword(input: ChangePasswordRequest, options?: RpcOptions): UnaryCall; } @@ -128,7 +128,7 @@ export class WalletUnlockerClient implements IWalletUnlockerClient, ServiceInfo * method should be used to commit the newly generated seed, and create the * wallet. * - * @generated from protobuf rpc: GenSeed(lnrpc.GenSeedRequest) returns (lnrpc.GenSeedResponse); + * @generated from protobuf rpc: GenSeed */ genSeed(input: GenSeedRequest, options?: RpcOptions): UnaryCall { const method = this.methods[0], opt = this._transport.mergeOptions(options); @@ -149,7 +149,7 @@ export class WalletUnlockerClient implements IWalletUnlockerClient, ServiceInfo * seed, then present it to the user. Once it has been verified by the user, * the seed can be fed into this RPC in order to commit the new wallet. * - * @generated from protobuf rpc: InitWallet(lnrpc.InitWalletRequest) returns (lnrpc.InitWalletResponse); + * @generated from protobuf rpc: InitWallet */ initWallet(input: InitWalletRequest, options?: RpcOptions): UnaryCall { const method = this.methods[1], opt = this._transport.mergeOptions(options); @@ -160,7 +160,7 @@ export class WalletUnlockerClient implements IWalletUnlockerClient, ServiceInfo * UnlockWallet is used at startup of lnd to provide a password to unlock * the wallet database. * - * @generated from protobuf rpc: UnlockWallet(lnrpc.UnlockWalletRequest) returns (lnrpc.UnlockWalletResponse); + * @generated from protobuf rpc: UnlockWallet */ unlockWallet(input: UnlockWalletRequest, options?: RpcOptions): UnaryCall { const method = this.methods[2], opt = this._transport.mergeOptions(options); @@ -171,7 +171,7 @@ export class WalletUnlockerClient implements IWalletUnlockerClient, ServiceInfo * ChangePassword changes the password of the encrypted wallet. This will * automatically unlock the wallet database if successful. * - * @generated from protobuf rpc: ChangePassword(lnrpc.ChangePasswordRequest) returns (lnrpc.ChangePasswordResponse); + * @generated from protobuf rpc: ChangePassword */ changePassword(input: ChangePasswordRequest, options?: RpcOptions): UnaryCall { const method = this.methods[3], opt = this._transport.mergeOptions(options); diff --git a/proto/lnd/walletunlocker.ts b/proto/lnd/walletunlocker.ts index a472c857..30114cab 100644 --- a/proto/lnd/walletunlocker.ts +++ b/proto/lnd/walletunlocker.ts @@ -1,4 +1,4 @@ -// @generated by protobuf-ts 2.8.1 +// @generated by protobuf-ts 2.11.1 // @generated from protobuf file "walletunlocker.proto" (package "lnrpc", syntax proto3) // tslint:disable import { ServiceType } from "@protobuf-ts/runtime-rpc"; @@ -10,7 +10,6 @@ import type { IBinaryReader } from "@protobuf-ts/runtime"; import { UnknownFieldHandler } from "@protobuf-ts/runtime"; import type { PartialMessage } from "@protobuf-ts/runtime"; import { reflectionMergePartial } from "@protobuf-ts/runtime"; -import { MESSAGE_TYPE } from "@protobuf-ts/runtime"; import { MessageType } from "@protobuf-ts/runtime"; import { ChanBackupSnapshot } from "./lightning.js"; /** @@ -23,7 +22,7 @@ export interface GenSeedRequest { * to encrypt the generated aezeed cipher seed. When using REST, this field * must be encoded as base64. * - * @generated from protobuf field: bytes aezeed_passphrase = 1; + * @generated from protobuf field: bytes aezeed_passphrase = 1 */ aezeedPassphrase: Uint8Array; /** @@ -32,7 +31,7 @@ export interface GenSeedRequest { * specified, then a fresh set of randomness will be used to create the seed. * When using REST, this field must be encoded as base64. * - * @generated from protobuf field: bytes seed_entropy = 2; + * @generated from protobuf field: bytes seed_entropy = 2 */ seedEntropy: Uint8Array; } @@ -48,7 +47,7 @@ export interface GenSeedResponse { * Otherwise, then the daemon will attempt to recover the wallet state linked * to this cipher seed. * - * @generated from protobuf field: repeated string cipher_seed_mnemonic = 1; + * @generated from protobuf field: repeated string cipher_seed_mnemonic = 1 */ cipherSeedMnemonic: string[]; /** @@ -56,7 +55,7 @@ export interface GenSeedResponse { * enciphered_seed are the raw aezeed cipher seed bytes. This is the raw * cipher text before run through our mnemonic encoding scheme. * - * @generated from protobuf field: bytes enciphered_seed = 2; + * @generated from protobuf field: bytes enciphered_seed = 2 */ encipheredSeed: Uint8Array; } @@ -71,7 +70,7 @@ export interface InitWalletRequest { * password is required to unlock the daemon. When using REST, this field * must be encoded as base64. * - * @generated from protobuf field: bytes wallet_password = 1; + * @generated from protobuf field: bytes wallet_password = 1 */ walletPassword: Uint8Array; /** @@ -80,7 +79,7 @@ export interface InitWalletRequest { * cipher seed obtained by the user. This may have been generated by the * GenSeed method, or be an existing seed. * - * @generated from protobuf field: repeated string cipher_seed_mnemonic = 2; + * @generated from protobuf field: repeated string cipher_seed_mnemonic = 2 */ cipherSeedMnemonic: string[]; /** @@ -89,7 +88,7 @@ export interface InitWalletRequest { * to encrypt the generated aezeed cipher seed. When using REST, this field * must be encoded as base64. * - * @generated from protobuf field: bytes aezeed_passphrase = 3; + * @generated from protobuf field: bytes aezeed_passphrase = 3 */ aezeedPassphrase: Uint8Array; /** @@ -100,7 +99,7 @@ export interface InitWalletRequest { * window of zero indicates that no addresses should be recovered, such after * the first initialization of the wallet. * - * @generated from protobuf field: int32 recovery_window = 4; + * @generated from protobuf field: int32 recovery_window = 4 */ recoveryWindow: number; /** @@ -112,7 +111,7 @@ export interface InitWalletRequest { * funds, lnd begin to carry out the data loss recovery protocol in order to * recover the funds in each channel from a remote force closed transaction. * - * @generated from protobuf field: lnrpc.ChanBackupSnapshot channel_backups = 5; + * @generated from protobuf field: lnrpc.ChanBackupSnapshot channel_backups = 5 */ channelBackups?: ChanBackupSnapshot; /** @@ -122,7 +121,7 @@ export interface InitWalletRequest { * admin macaroon returned in the response MUST be stored by the caller of the * RPC as otherwise all access to the daemon will be lost! * - * @generated from protobuf field: bool stateless_init = 6; + * @generated from protobuf field: bool stateless_init = 6 */ statelessInit: boolean; /** @@ -140,7 +139,7 @@ export interface InitWalletRequest { * extended_master_key_birthday_timestamp or a "safe" default value will be * used. * - * @generated from protobuf field: string extended_master_key = 7; + * @generated from protobuf field: string extended_master_key = 7 */ extendedMasterKey: string; /** @@ -153,7 +152,7 @@ export interface InitWalletRequest { * which case lnd will start scanning from the first SegWit block (481824 on * mainnet). * - * @generated from protobuf field: uint64 extended_master_key_birthday_timestamp = 8; + * @generated from protobuf field: uint64 extended_master_key_birthday_timestamp = 8 */ extendedMasterKeyBirthdayTimestamp: bigint; /** @@ -164,7 +163,7 @@ export interface InitWalletRequest { * any of the keys and _needs_ to be run with a remote signer that has the * corresponding private keys and can serve signing RPC requests. * - * @generated from protobuf field: lnrpc.WatchOnly watch_only = 9; + * @generated from protobuf field: lnrpc.WatchOnly watch_only = 9 */ watchOnly?: WatchOnly; /** @@ -173,7 +172,7 @@ export interface InitWalletRequest { * provided when initializing the wallet rather than letting lnd generate one * on its own. * - * @generated from protobuf field: bytes macaroon_root_key = 10; + * @generated from protobuf field: bytes macaroon_root_key = 10 */ macaroonRootKey: Uint8Array; } @@ -189,7 +188,7 @@ export interface InitWalletResponse { * caller. Otherwise a copy of this macaroon is also persisted on disk by the * daemon, together with other macaroon files. * - * @generated from protobuf field: bytes admin_macaroon = 1; + * @generated from protobuf field: bytes admin_macaroon = 1 */ adminMacaroon: Uint8Array; } @@ -205,7 +204,7 @@ export interface WatchOnly { * should be left at its default value of 0 in which case lnd will start * scanning from the first SegWit block (481824 on mainnet). * - * @generated from protobuf field: uint64 master_key_birthday_timestamp = 1; + * @generated from protobuf field: uint64 master_key_birthday_timestamp = 1 */ masterKeyBirthdayTimestamp: bigint; /** @@ -215,7 +214,7 @@ export interface WatchOnly { * required by some hardware wallets for proper identification and signing. The * bytes must be in big-endian order. * - * @generated from protobuf field: bytes master_key_fingerprint = 2; + * @generated from protobuf field: bytes master_key_fingerprint = 2 */ masterKeyFingerprint: Uint8Array; /** @@ -226,7 +225,7 @@ export interface WatchOnly { * scope (m/1017'/'/'), where account is the key family as * defined in `keychain/derivation.go` (currently indices 0 to 9). * - * @generated from protobuf field: repeated lnrpc.WatchOnlyAccount accounts = 3; + * @generated from protobuf field: repeated lnrpc.WatchOnlyAccount accounts = 3 */ accounts: WatchOnlyAccount[]; } @@ -239,7 +238,7 @@ export interface WatchOnlyAccount { * Purpose is the first number in the derivation path, must be either 49, 84 * or 1017. * - * @generated from protobuf field: uint32 purpose = 1; + * @generated from protobuf field: uint32 purpose = 1 */ purpose: number; /** @@ -248,7 +247,7 @@ export interface WatchOnlyAccount { * for purposes 49 and 84. It only needs to be set to 1 for purpose 1017 on * testnet or regtest. * - * @generated from protobuf field: uint32 coin_type = 2; + * @generated from protobuf field: uint32 coin_type = 2 */ coinType: number; /** @@ -259,14 +258,14 @@ export interface WatchOnlyAccount { * one account for each of the key families defined in `keychain/derivation.go` * (currently indices 0 to 9) * - * @generated from protobuf field: uint32 account = 3; + * @generated from protobuf field: uint32 account = 3 */ account: number; /** * * The extended public key at depth 3 for the given account. * - * @generated from protobuf field: string xpub = 4; + * @generated from protobuf field: string xpub = 4 */ xpub: string; } @@ -280,7 +279,7 @@ export interface UnlockWalletRequest { * will be required to decrypt on-disk material that the daemon requires to * function properly. When using REST, this field must be encoded as base64. * - * @generated from protobuf field: bytes wallet_password = 1; + * @generated from protobuf field: bytes wallet_password = 1 */ walletPassword: Uint8Array; /** @@ -291,7 +290,7 @@ export interface UnlockWalletRequest { * window of zero indicates that no addresses should be recovered, such after * the first initialization of the wallet. * - * @generated from protobuf field: int32 recovery_window = 2; + * @generated from protobuf field: int32 recovery_window = 2 */ recoveryWindow: number; /** @@ -303,7 +302,7 @@ export interface UnlockWalletRequest { * funds, lnd begin to carry out the data loss recovery protocol in order to * recover the funds in each channel from a remote force closed transaction. * - * @generated from protobuf field: lnrpc.ChanBackupSnapshot channel_backups = 3; + * @generated from protobuf field: lnrpc.ChanBackupSnapshot channel_backups = 3 */ channelBackups?: ChanBackupSnapshot; /** @@ -311,7 +310,7 @@ export interface UnlockWalletRequest { * stateless_init is an optional argument instructing the daemon NOT to create * any *.macaroon files in its file system. * - * @generated from protobuf field: bool stateless_init = 4; + * @generated from protobuf field: bool stateless_init = 4 */ statelessInit: boolean; } @@ -329,7 +328,7 @@ export interface ChangePasswordRequest { * current_password should be the current valid passphrase used to unlock the * daemon. When using REST, this field must be encoded as base64. * - * @generated from protobuf field: bytes current_password = 1; + * @generated from protobuf field: bytes current_password = 1 */ currentPassword: Uint8Array; /** @@ -337,7 +336,7 @@ export interface ChangePasswordRequest { * new_password should be the new passphrase that will be needed to unlock the * daemon. When using REST, this field must be encoded as base64. * - * @generated from protobuf field: bytes new_password = 2; + * @generated from protobuf field: bytes new_password = 2 */ newPassword: Uint8Array; /** @@ -347,7 +346,7 @@ export interface ChangePasswordRequest { * admin macaroon returned in the response MUST be stored by the caller of the * RPC as otherwise all access to the daemon will be lost! * - * @generated from protobuf field: bool stateless_init = 3; + * @generated from protobuf field: bool stateless_init = 3 */ statelessInit: boolean; /** @@ -356,7 +355,7 @@ export interface ChangePasswordRequest { * rotate the macaroon root key when set to true. This will invalidate all * previously generated macaroons. * - * @generated from protobuf field: bool new_macaroon_root_key = 4; + * @generated from protobuf field: bool new_macaroon_root_key = 4 */ newMacaroonRootKey: boolean; } @@ -373,7 +372,7 @@ export interface ChangePasswordResponse { * safely by the caller. Otherwise a copy of this macaroon is also persisted on * disk by the daemon, together with other macaroon files. * - * @generated from protobuf field: bytes admin_macaroon = 1; + * @generated from protobuf field: bytes admin_macaroon = 1 */ adminMacaroon: Uint8Array; } @@ -386,8 +385,9 @@ class GenSeedRequest$Type extends MessageType { ]); } create(value?: PartialMessage): GenSeedRequest { - const message = { aezeedPassphrase: new Uint8Array(0), seedEntropy: new Uint8Array(0) }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.aezeedPassphrase = new Uint8Array(0); + message.seedEntropy = new Uint8Array(0); if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -440,8 +440,9 @@ class GenSeedResponse$Type extends MessageType { ]); } create(value?: PartialMessage): GenSeedResponse { - const message = { cipherSeedMnemonic: [], encipheredSeed: new Uint8Array(0) }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.cipherSeedMnemonic = []; + message.encipheredSeed = new Uint8Array(0); if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -502,8 +503,15 @@ class InitWalletRequest$Type extends MessageType { ]); } create(value?: PartialMessage): InitWalletRequest { - const message = { walletPassword: new Uint8Array(0), cipherSeedMnemonic: [], aezeedPassphrase: new Uint8Array(0), recoveryWindow: 0, statelessInit: false, extendedMasterKey: "", extendedMasterKeyBirthdayTimestamp: 0n, macaroonRootKey: new Uint8Array(0) }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.walletPassword = new Uint8Array(0); + message.cipherSeedMnemonic = []; + message.aezeedPassphrase = new Uint8Array(0); + message.recoveryWindow = 0; + message.statelessInit = false; + message.extendedMasterKey = ""; + message.extendedMasterKeyBirthdayTimestamp = 0n; + message.macaroonRootKey = new Uint8Array(0); if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -603,8 +611,8 @@ class InitWalletResponse$Type extends MessageType { ]); } create(value?: PartialMessage): InitWalletResponse { - const message = { adminMacaroon: new Uint8Array(0) }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.adminMacaroon = new Uint8Array(0); if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -648,12 +656,14 @@ class WatchOnly$Type extends MessageType { super("lnrpc.WatchOnly", [ { no: 1, name: "master_key_birthday_timestamp", kind: "scalar", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ }, { no: 2, name: "master_key_fingerprint", kind: "scalar", T: 12 /*ScalarType.BYTES*/ }, - { no: 3, name: "accounts", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => WatchOnlyAccount } + { no: 3, name: "accounts", kind: "message", repeat: 2 /*RepeatType.UNPACKED*/, T: () => WatchOnlyAccount } ]); } create(value?: PartialMessage): WatchOnly { - const message = { masterKeyBirthdayTimestamp: 0n, masterKeyFingerprint: new Uint8Array(0), accounts: [] }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.masterKeyBirthdayTimestamp = 0n; + message.masterKeyFingerprint = new Uint8Array(0); + message.accounts = []; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -714,8 +724,11 @@ class WatchOnlyAccount$Type extends MessageType { ]); } create(value?: PartialMessage): WatchOnlyAccount { - const message = { purpose: 0, coinType: 0, account: 0, xpub: "" }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.purpose = 0; + message.coinType = 0; + message.account = 0; + message.xpub = ""; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -782,8 +795,10 @@ class UnlockWalletRequest$Type extends MessageType { ]); } create(value?: PartialMessage): UnlockWalletRequest { - const message = { walletPassword: new Uint8Array(0), recoveryWindow: 0, statelessInit: false }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.walletPassword = new Uint8Array(0); + message.recoveryWindow = 0; + message.statelessInit = false; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -845,14 +860,26 @@ class UnlockWalletResponse$Type extends MessageType { super("lnrpc.UnlockWalletResponse", []); } create(value?: PartialMessage): UnlockWalletResponse { - const message = {}; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); if (value !== undefined) reflectionMergePartial(this, message, value); return message; } internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: UnlockWalletResponse): UnlockWalletResponse { - return target ?? this.create(); + let message = target ?? this.create(), end = reader.pos + length; + while (reader.pos < end) { + let [fieldNo, wireType] = reader.tag(); + switch (fieldNo) { + default: + let u = options.readUnknownField; + if (u === "throw") + throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`); + let d = reader.skip(wireType); + if (u !== false) + (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d); + } + } + return message; } internalBinaryWrite(message: UnlockWalletResponse, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter { let u = options.writeUnknownFields; @@ -876,8 +903,11 @@ class ChangePasswordRequest$Type extends MessageType { ]); } create(value?: PartialMessage): ChangePasswordRequest { - const message = { currentPassword: new Uint8Array(0), newPassword: new Uint8Array(0), statelessInit: false, newMacaroonRootKey: false }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.currentPassword = new Uint8Array(0); + message.newPassword = new Uint8Array(0); + message.statelessInit = false; + message.newMacaroonRootKey = false; if (value !== undefined) reflectionMergePartial(this, message, value); return message; @@ -941,8 +971,8 @@ class ChangePasswordResponse$Type extends MessageType { ]); } create(value?: PartialMessage): ChangePasswordResponse { - const message = { adminMacaroon: new Uint8Array(0) }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + const message = globalThis.Object.create((this.messagePrototype!)); + message.adminMacaroon = new Uint8Array(0); if (value !== undefined) reflectionMergePartial(this, message, value); return message; diff --git a/proto/others/invoices.proto b/proto/others/invoices.proto index fb4f0ca6..26c603a5 100644 --- a/proto/others/invoices.proto +++ b/proto/others/invoices.proto @@ -1,11 +1,29 @@ syntax = "proto3"; -import "lightning.proto"; - package invoicesrpc; +import "lightning.proto"; + option go_package = "github.com/lightningnetwork/lnd/lnrpc/invoicesrpc"; +/* + * Comments in this file will be directly parsed into the API + * Documentation as descriptions of the associated method, message, or field. + * These descriptions should go right above the definition of the object, and + * can be in either block or // comment format. + * + * An RPC method can be matched to an lncli command by placing a line in the + * beginning of the description in exactly the following format: + * lncli: `methodname` + * + * Failure to specify the exact name of the command will cause documentation + * generation to fail. + * + * More information on how exactly the gRPC documentation is generated from + * this proto file can be found here: + * https://github.com/lightninglabs/lightning-api + */ + // Invoices is a service that can be used to create, accept, settle and cancel // invoices. service Invoices { @@ -17,30 +35,39 @@ service Invoices { rpc SubscribeSingleInvoice (SubscribeSingleInvoiceRequest) returns (stream lnrpc.Invoice); - /* + /* lncli: `cancelinvoice` CancelInvoice cancels a currently open invoice. If the invoice is already canceled, this call will succeed. If the invoice is already settled, it will fail. */ rpc CancelInvoice (CancelInvoiceMsg) returns (CancelInvoiceResp); - /* + /* lncli: `addholdinvoice` AddHoldInvoice creates a hold invoice. It ties the invoice to the hash supplied in the request. */ rpc AddHoldInvoice (AddHoldInvoiceRequest) returns (AddHoldInvoiceResp); - /* + /* lncli: `settleinvoice` SettleInvoice settles an accepted invoice. If the invoice is already settled, this call will succeed. */ rpc SettleInvoice (SettleInvoiceMsg) returns (SettleInvoiceResp); /* - LookupInvoiceV2 attempts to look up at invoice. An invoice can be refrenced + LookupInvoiceV2 attempts to look up at invoice. An invoice can be referenced using either its payment hash, payment address, or set ID. */ rpc LookupInvoiceV2 (LookupInvoiceMsg) returns (lnrpc.Invoice); + + /* + HtlcModifier is a bidirectional streaming RPC that allows a client to + intercept and modify the HTLCs that attempt to settle the given invoice. The + server will send HTLCs of invoices to the client and the client can modify + some aspects of the HTLC in order to pass the invoice acceptance tests. + */ + rpc HtlcModifier (stream HtlcModifyResponse) + returns (stream HtlcModifyRequest); } message CancelInvoiceMsg { @@ -84,7 +111,7 @@ message AddHoldInvoiceRequest { */ bytes description_hash = 4; - // Payment request expiry time in seconds. Default is 3600 (1 hour). + // Payment request expiry time in seconds. Default is 86400 (24 hours). int64 expiry = 5; // Fallback on-chain address. @@ -120,8 +147,9 @@ message AddHoldInvoiceResp { uint64 add_index = 2; /* - The payment address of the generated invoice. This value should be used - in all payments for this invoice as we require it for end to end + The payment address of the generated invoice. This is also called + the payment secret in specifications (e.g. BOLT 11). This value should + be used in all payments for this invoice as we require it for end to end security. */ bytes payment_addr = 3; @@ -172,4 +200,52 @@ message LookupInvoiceMsg { } LookupModifier lookup_modifier = 4; +} + +// CircuitKey is a unique identifier for an HTLC. +message CircuitKey { + // The id of the channel that the is part of this circuit. + uint64 chan_id = 1; + + // The index of the incoming htlc in the incoming channel. + uint64 htlc_id = 2; +} + +message HtlcModifyRequest { + // The invoice the intercepted HTLC is attempting to settle. The HTLCs in + // the invoice are only HTLCs that have already been accepted or settled, + // not including the current intercepted HTLC. + lnrpc.Invoice invoice = 1; + + // The unique identifier of the HTLC of this intercepted HTLC. + CircuitKey exit_htlc_circuit_key = 2; + + // The amount in milli-satoshi that the exit HTLC is attempting to pay. + uint64 exit_htlc_amt = 3; + + // The absolute expiry height of the exit HTLC. + uint32 exit_htlc_expiry = 4; + + // The current block height. + uint32 current_height = 5; + + // The wire message custom records of the exit HTLC. + map exit_htlc_wire_custom_records = 6; +} + +message HtlcModifyResponse { + // The circuit key of the HTLC that the client wants to modify. + CircuitKey circuit_key = 1; + + // The modified amount in milli-satoshi that the exit HTLC is paying. This + // value can be different from the actual on-chain HTLC amount, in case the + // HTLC carries other valuable items, as can be the case with custom channel + // types. + optional uint64 amt_paid = 2; + + // This flag indicates whether the HTLCs associated with the invoices should + // be cancelled. The interceptor client may set this field if some + // unexpected behavior is encountered. Setting this will ignore the amt_paid + // field. + bool cancel_set = 3; } \ No newline at end of file diff --git a/proto/others/lightning.proto b/proto/others/lightning.proto index 4f83b7d4..0304add6 100644 --- a/proto/others/lightning.proto +++ b/proto/others/lightning.proto @@ -274,12 +274,14 @@ service Lightning { } /* - SendPaymentSync is the synchronous non-streaming version of SendPayment. - This RPC is intended to be consumed by clients of the REST proxy. - Additionally, this RPC expects the destination's public key and the payment - hash (if any) to be encoded as hex strings. + Deprecated, use routerrpc.SendPaymentV2. SendPaymentSync is the synchronous + non-streaming version of SendPayment. This RPC is intended to be consumed by + clients of the REST proxy. Additionally, this RPC expects the destination's + public key and the payment hash (if any) to be encoded as hex strings. */ - rpc SendPaymentSync (SendRequest) returns (SendResponse); + rpc SendPaymentSync (SendRequest) returns (SendResponse) { + option deprecated = true; + } /* lncli: `sendtoroute` Deprecated, use routerrpc.SendToRouteV2. SendToRoute is a bi-directional @@ -293,10 +295,13 @@ service Lightning { } /* - SendToRouteSync is a synchronous version of SendToRoute. It Will block - until the payment either fails or succeeds. + Deprecated, use routerrpc.SendToRouteV2. SendToRouteSync is a synchronous + version of SendToRoute. It Will block until the payment either fails or + succeeds. */ - rpc SendToRouteSync (SendToRouteRequest) returns (SendResponse); + rpc SendToRouteSync (SendToRouteRequest) returns (SendResponse) { + option deprecated = true; + } /* lncli: `addinvoice` AddInvoice attempts to add a new invoice to the invoice database. Any @@ -643,6 +648,8 @@ message SendCustomMessageRequest { } message SendCustomMessageResponse { + // The status of the send operation. + string status = 1; } message Utxo { @@ -755,11 +762,35 @@ message GetTransactionsRequest { // An optional filter to only include transactions relevant to an account. string account = 3; + + /* + The index of a transaction that will be used in a query to determine which + transaction should be returned in the response. + */ + uint32 index_offset = 4; + + /* + The maximal number of transactions returned in the response to this query. + This value should be set to 0 to return all transactions. + */ + uint32 max_transactions = 5; } message TransactionDetails { // The list of transactions relevant to the wallet. repeated Transaction transactions = 1; + + /* + The index of the last item in the set of returned transactions. This can be + used to seek further, pagination style. + */ + uint64 last_index = 2; + + /* + The index of the last item in the set of returned transactions. This can be + used to seek backwards, pagination style. + */ + uint64 first_index = 3; } message FeeLimit { @@ -1317,6 +1348,8 @@ message ConnectPeerRequest { uint64 timeout = 3; } message ConnectPeerResponse { + // The status of the connect operation. + string status = 1; } message DisconnectPeerRequest { @@ -1324,6 +1357,8 @@ message DisconnectPeerRequest { string pub_key = 1; } message DisconnectPeerResponse { + // The status of the disconnect operation. + string status = 1; } message HTLC { @@ -1346,6 +1381,13 @@ message HTLC { // Index identifying the htlc on the forwarding channel. uint64 forwarding_htlc_index = 7; + + /* + Whether the HTLC is locked in. An HTLC is considered locked in when the + remote party has sent us the `revoke_and_ack` to irrevocably commit this + HTLC. + */ + bool locked_in = 8; } enum CommitmentType { @@ -1388,8 +1430,14 @@ enum CommitmentType { A channel that uses musig2 for the funding output, and the new tapscript features where relevant. */ - // TODO(roasbeef): need script enforce mirror type for the above as well? SIMPLE_TAPROOT = 5; + + /* + Identical to the SIMPLE_TAPROOT channel type, but with extra functionality. + This channel type also commits to additional meta data in the tapscript + leaves for the scripts in a channel. + */ + SIMPLE_TAPROOT_OVERLAY = 6; } message ChannelConstraints { @@ -1592,6 +1640,11 @@ message Channel { the channel's operation. */ string memo = 36; + + /* + Custom channel data that might be populated in custom channels. + */ + bytes custom_channel_data = 37; } message ListChannelsRequest { @@ -1705,6 +1758,10 @@ message ChannelCloseSummary { // The confirmed SCID for a zero-conf channel. uint64 zero_conf_confirmed_scid = 15 [jstype = JS_STRING]; + + // The TLV encoded custom channel data records for this output, which might + // be set for custom channels. + bytes custom_channel_data = 16; } enum ResolutionType { @@ -1955,8 +2012,8 @@ message GetInfoResponse { bool synced_to_graph = 18; /* - Whether the current node is connected to testnet. This field is - deprecated and the network field should be used instead + Whether the current node is connected to testnet or testnet4. This field is + deprecated and the network field should be used instead. */ bool testnet = 10 [deprecated = true]; @@ -2028,10 +2085,38 @@ message ChannelOpenUpdate { ChannelPoint channel_point = 1; } +message CloseOutput { + // The amount in satoshi of this close output. This amount is the final + // commitment balance of the channel and the actual amount paid out on chain + // might be smaller due to subtracted fees. + int64 amount_sat = 1; + + // The pkScript of the close output. + bytes pk_script = 2; + + // Whether this output is for the local or remote node. + bool is_local = 3; + + // The TLV encoded custom channel data records for this output, which might + // be set for custom channels. + bytes custom_channel_data = 4; +} + message ChannelCloseUpdate { bytes closing_txid = 1; bool success = 2; + + // The local channel close output. If the local channel balance was dust to + // begin with, this output will not be set. + CloseOutput local_close_output = 3; + + // The remote channel close output. If the remote channel balance was dust + // to begin with, this output will not be set. + CloseOutput remote_close_output = 4; + + // Any additional outputs that might be added for custom channel types. + repeated CloseOutput additional_outputs = 5; } message CloseChannelRequest { @@ -2072,9 +2157,13 @@ message CloseChannelRequest { // NOTE: This field is only respected if we're the initiator of the channel. uint64 max_fee_per_vbyte = 7; - // If true, then the rpc call will not block while it awaits a closing txid. - // Consequently this RPC call will not return a closing txid if this value - // is set. + // If true, then the rpc call will not block while it awaits a closing txid + // to be broadcasted to the mempool. To obtain the closing tx one has to + // listen to the stream for the particular updates. Moreover if a coop close + // is specified and this flag is set to true the coop closing flow will be + // initiated even if HTLCs are active on the channel. The channel will wait + // until all HTLCs are resolved and then start the coop closing process. The + // channel will be disabled in the meantime and will disallow any new HTLCs. bool no_wait = 8; } @@ -2089,9 +2178,15 @@ message CloseStatusUpdate { message PendingUpdate { bytes txid = 1; uint32 output_index = 2; + int64 fee_per_vbyte = 3; + bool local_close_tx = 4; } message InstantUpdate { + // The number of pending HTLCs that are currently active on the channel. + // These HTLCs need to be resolved before the channel can be closed + // cooperatively. + int32 num_pending_htlcs = 1; } message ReadyForPsbtFunding { @@ -2709,6 +2804,11 @@ message PendingChannelsResponse { impacts the channel's operation. */ string memo = 13; + + /* + Custom channel data that might be populated in custom channels. + */ + bytes custom_channel_data = 34; } message PendingOpenChannel { @@ -2880,6 +2980,7 @@ message ChannelEventUpdate { ChannelPoint inactive_channel = 4; PendingUpdate pending_open_channel = 6; ChannelPoint fully_resolved_channel = 7; + ChannelPoint channel_funding_timeout = 8; } enum UpdateType { @@ -2889,6 +2990,7 @@ message ChannelEventUpdate { INACTIVE_CHANNEL = 3; PENDING_OPEN_CHANNEL = 4; FULLY_RESOLVED_CHANNEL = 5; + CHANNEL_FUNDING_TIMEOUT = 6; } UpdateType type = 5; @@ -2968,6 +3070,12 @@ message ChannelBalanceResponse { // Sum of channels pending remote balances. Amount pending_open_remote_balance = 8; + + /* + Custom channel data that might be populated if there are custom channels + present. + */ + bytes custom_channel_data = 9; } message QueryRoutesRequest { @@ -3293,6 +3401,20 @@ message Route { The total amount in millisatoshis. */ int64 total_amt_msat = 6; + + /* + The actual on-chain amount that was sent out to the first hop. This value is + only different from the total_amt_msat field if this is a custom channel + payment and the value transported in the HTLC is different from the BTC + amount in the HTLC. If this value is zero, then this is an old payment that + didn't have this value yet and can be ignored. + */ + int64 first_hop_amount_msat = 7; + + /* + Custom channel data that might be populated in custom channels. + */ + bytes custom_channel_data = 8; } message NodeInfoRequest { @@ -3478,6 +3600,8 @@ message NetworkInfo { message StopRequest { } message StopResponse { + // The status of the stop operation. + string status = 1; } message GraphTopologySubscription { @@ -3922,6 +4046,11 @@ message InvoiceHTLC { // Details relevant to AMP HTLCs, only populated if this is an AMP HTLC. AMP amp = 11; + + /* + Custom channel data that might be populated in custom channels. + */ + bytes custom_channel_data = 12; } // Details specific to AMP HTLCs. @@ -4162,6 +4291,12 @@ message Payment { uint64 payment_index = 15; PaymentFailureReason failure_reason = 16; + + /* + The custom TLV records that were sent to the first hop as part of the HTLC + wire message for this payment. + */ + map first_hop_custom_records = 17; } message HTLCAttempt { @@ -4291,9 +4426,13 @@ message DeleteAllPaymentsRequest { } message DeletePaymentResponse { + // The status of the delete operation. + string status = 1; } message DeleteAllPaymentsResponse { + // The status of the delete operation. + string status = 1; } message AbandonChannelRequest { @@ -4310,6 +4449,8 @@ message AbandonChannelRequest { } message AbandonChannelResponse { + // The status of the abandon operation. + string status = 1; } message DebugLevelRequest { @@ -4469,6 +4610,15 @@ message PolicyUpdateRequest { // Optional inbound fee. If unset, the previously set value will be // retained [EXPERIMENTAL]. InboundFee inbound_fee = 10; + + // Under unknown circumstances a channel can exist with a missing edge in + // the graph database. This can cause an 'edge not found' error when calling + // `getchaninfo` and/or cause the default channel policy to be used during + // forwards. Setting this flag will recreate the edge if not found, allowing + // updating this channel policy and fixing the missing edge problem for this + // channel permanently. For fields not set in this command, the default + // policy will be created. + bool create_missing_edge = 11; } enum UpdateFailure { @@ -4562,6 +4712,14 @@ message ForwardingEvent { // The peer alias of the outgoing channel. string peer_alias_out = 13; + // The ID of the incoming HTLC in the payment circuit. This field is + // optional and is unset for forwarding events happened before v0.20. + optional uint64 incoming_htlc_id = 14; + + // The ID of the outgoing HTLC in the payment circuit. This field is + // optional and may be unset for legacy forwarding events. + optional uint64 outgoing_htlc_id = 15; + // TODO(roasbeef): add settlement latency? // * use FPE on the chan id? // * also list failures? @@ -4649,12 +4807,15 @@ message RestoreChanBackupRequest { } } message RestoreBackupResponse { + // The number of channels successfully restored. + uint32 num_restored = 1; } message ChannelBackupSubscription { } message VerifyChanBackupResponse { + repeated string chan_points = 1; } message MacaroonPermission { @@ -4977,6 +5138,22 @@ message RPCMiddlewareRequest { intercept message. */ uint64 msg_id = 7; + + /* + The metadata pairs that were sent along with the original gRPC request via + the golang context.Context using explicit [gRPC + metadata](https://grpc.io/docs/guides/metadata/). Context values are not + propagated via gRPC and so we send any pairs along explicitly here so that + the interceptor can access them. + */ + map metadata_pairs = 9; +} + +message MetadataValues { + /* + The set of metadata values that correspond to the metadata key. + */ + repeated string values = 1; } message StreamAuth { diff --git a/proto/others/router.proto b/proto/others/router.proto index 16cb769f..503ecb3f 100644 --- a/proto/others/router.proto +++ b/proto/others/router.proto @@ -1,22 +1,43 @@ syntax = "proto3"; -import "lightning.proto"; - package routerrpc; +import "lightning.proto"; + option go_package = "github.com/lightningnetwork/lnd/lnrpc/routerrpc"; +/* + * Comments in this file will be directly parsed into the API + * Documentation as descriptions of the associated method, message, or field. + * These descriptions should go right above the definition of the object, and + * can be in either block or // comment format. + * + * An RPC method can be matched to an lncli command by placing a line in the + * beginning of the description in exactly the following format: + * lncli: `methodname` + * + * Failure to specify the exact name of the command will cause documentation + * generation to fail. + * + * More information on how exactly the gRPC documentation is generated from + * this proto file can be found here: + * https://github.com/lightninglabs/lightning-api + */ + // Router is a service that offers advanced interaction with the router // subsystem of the daemon. service Router { /* SendPaymentV2 attempts to route a payment described by the passed PaymentRequest to the final destination. The call returns a stream of - payment updates. + payment updates. When using this RPC, make sure to set a fee limit, as the + default routing fee limit is 0 sats. Without a non-zero fee limit only + routes without fees will be attempted which often fails with + FAILURE_REASON_NO_ROUTE. */ rpc SendPaymentV2 (SendPaymentRequest) returns (stream lnrpc.Payment); - /* + /* lncli: `trackpayment` TrackPaymentV2 returns an update stream for the payment identified by the payment hash. */ @@ -57,21 +78,21 @@ service Router { */ rpc SendToRouteV2 (SendToRouteRequest) returns (lnrpc.HTLCAttempt); - /* + /* lncli: `resetmc` ResetMissionControl clears all mission control state and starts with a clean slate. */ rpc ResetMissionControl (ResetMissionControlRequest) returns (ResetMissionControlResponse); - /* + /* lncli: `querymc` QueryMissionControl exposes the internal mission control state to callers. It is a development feature. */ rpc QueryMissionControl (QueryMissionControlRequest) returns (QueryMissionControlResponse); - /* + /* lncli: `importmc` XImportMissionControl is an experimental API that imports the state provided to the internal mission control's state, using all results which are more recent than our existing values. These values will only be imported @@ -80,30 +101,36 @@ service Router { rpc XImportMissionControl (XImportMissionControlRequest) returns (XImportMissionControlResponse); - /* + /* lncli: `getmccfg` GetMissionControlConfig returns mission control's current config. */ rpc GetMissionControlConfig (GetMissionControlConfigRequest) returns (GetMissionControlConfigResponse); - /* + /* lncli: `setmccfg` SetMissionControlConfig will set mission control's config, if the config provided is valid. */ rpc SetMissionControlConfig (SetMissionControlConfigRequest) returns (SetMissionControlConfigResponse); - /* - QueryProbability returns the current success probability estimate for a - given node pair and amount. + /* lncli: `queryprob` + Deprecated. QueryProbability returns the current success probability + estimate for a given node pair and amount. The call returns a zero success + probability if no channel is available or if the amount violates min/max + HTLC constraints. */ rpc QueryProbability (QueryProbabilityRequest) returns (QueryProbabilityResponse); - /* + /* lncli: `buildroute` BuildRoute builds a fully specified route based on a list of hop public keys. It retrieves the relevant channel policies from the graph in order to calculate the correct fees and time locks. + Note that LND will use its default final_cltv_delta if no value is supplied. + Make sure to add the correct final_cltv_delta depending on the invoice + restriction. Moreover the caller has to make sure to provide the + payment_addr if the route is paying an invoice which signaled it. */ rpc BuildRoute (BuildRouteRequest) returns (BuildRouteResponse); @@ -141,7 +168,7 @@ service Router { rpc HtlcInterceptor (stream ForwardHtlcInterceptResponse) returns (stream ForwardHtlcInterceptRequest); - /* + /* lncli: `updatechanstatus` UpdateChanStatus attempts to manually set the state of a channel (enabled, disabled, or auto). A manual "disable" request will cause the channel to stay disabled until a subsequent manual request of either @@ -149,6 +176,25 @@ service Router { */ rpc UpdateChanStatus (UpdateChanStatusRequest) returns (UpdateChanStatusResponse); + + /* + XAddLocalChanAliases is an experimental API that creates a set of new + channel SCID alias mappings. The final total set of aliases in the manager + after the add operation is returned. This is only a locally stored alias, + and will not be communicated to the channel peer via any message. Therefore, + routing over such an alias will only work if the peer also calls this same + RPC on their end. If an alias already exists, an error is returned + */ + rpc XAddLocalChanAliases (AddAliasesRequest) returns (AddAliasesResponse); + + /* + XDeleteLocalChanAliases is an experimental API that deletes a set of alias + mappings. The final total set of aliases in the manager after the delete + operation is returned. The deletion will not be communicated to the channel + peer via any message. + */ + rpc XDeleteLocalChanAliases (DeleteAliasesRequest) + returns (DeleteAliasesResponse); } message SendPaymentRequest { @@ -162,13 +208,6 @@ message SendPaymentRequest { */ int64 amt = 2; - /* - Number of millisatoshis to send. - - The fields amt and amt_msat are mutually exclusive. - */ - int64 amt_msat = 12; - // The hash to use within the payment's HTLC bytes payment_hash = 3; @@ -178,9 +217,6 @@ message SendPaymentRequest { */ int32 final_cltv_delta = 4; - // An optional payment addr to be included within the last hop of the route. - bytes payment_addr = 20; - /* A bare-bones invoice for a payment within the Lightning Network. With the details of the invoice, the sender has all the data necessary to send a @@ -191,10 +227,11 @@ message SendPaymentRequest { string payment_request = 5; /* - An upper limit on the amount of time we should spend when attempting to - fulfill the payment. This is expressed in seconds. If we cannot make a - successful payment within this time frame, an error will be returned. - This field must be non-zero. + An optional limit, expressed in seconds, on the time to wait before + attempting the first HTLC. Once HTLCs are in flight, the payment will + not be aborted until the HTLCs are either settled or failed. If the field + is not set or is explicitly set to zero, the default value of 60 seconds + will be applied. */ int32 timeout_seconds = 6; @@ -208,17 +245,6 @@ message SendPaymentRequest { */ int64 fee_limit_sat = 7; - /* - The maximum number of millisatoshis that will be paid as a fee of the - payment. If this field is left to the default value of 0, only zero-fee - routes will be considered. This usually means single hop routes connecting - directly to the destination. To send the payment without a fee limit, use - max int here. - - The fields fee_limit_sat and fee_limit_msat are mutually exclusive. - */ - int64 fee_limit_msat = 13; - /* Deprecated, use outgoing_chan_ids. The channel id of the channel that must be taken to the first hop. If zero, any channel may be used (unless @@ -227,19 +253,8 @@ message SendPaymentRequest { uint64 outgoing_chan_id = 8 [jstype = JS_STRING, deprecated = true]; /* - The channel ids of the channels are allowed for the first hop. If empty, - any channel may be used. - */ - repeated uint64 outgoing_chan_ids = 19; - - /* - The pubkey of the last hop of the route. If empty, any hop may be used. - */ - bytes last_hop_pubkey = 14; - - /* - An optional maximum total time lock for the route. This should not exceed - lnd's `--max-cltv-expiry` setting. If zero, then the value of + An optional maximum total time lock for the route. This should not + exceed lnd's `--max-cltv-expiry` setting. If zero, then the value of `--max-cltv-expiry` is enforced. */ int32 cltv_limit = 9; @@ -258,6 +273,29 @@ message SendPaymentRequest { */ map dest_custom_records = 11; + /* + Number of millisatoshis to send. + + The fields amt and amt_msat are mutually exclusive. + */ + int64 amt_msat = 12; + + /* + The maximum number of millisatoshis that will be paid as a fee of the + payment. If this field is left to the default value of 0, only zero-fee + routes will be considered. This usually means single hop routes connecting + directly to the destination. To send the payment without a fee limit, use + max int here. + + The fields fee_limit_sat and fee_limit_msat are mutually exclusive. + */ + int64 fee_limit_msat = 13; + + /* + The pubkey of the last hop of the route. If empty, any hop may be used. + */ + bytes last_hop_pubkey = 14; + // If set, circular payments to self are permitted. bool allow_self_payment = 15; @@ -282,6 +320,18 @@ message SendPaymentRequest { */ bool no_inflight_updates = 18; + /* + The channel ids of the channels are allowed for the first hop. If empty, + any channel may be used. + */ + repeated uint64 outgoing_chan_ids = 19; + + /* + An optional payment addr to be included within the last hop of the route. + This is also called payment secret in specifications (e.g. BOLT 11). + */ + bytes payment_addr = 20; + /* The largest payment split that should be attempted when making a payment if splitting is necessary. Setting this value will effectively cause lnd to @@ -300,6 +350,24 @@ message SendPaymentRequest { only, to 1 to optimize for reliability only or a value inbetween for a mix. */ double time_pref = 23; + + /* + If set, the payment loop can be interrupted by manually canceling the + payment context, even before the payment timeout is reached. Note that the + payment may still succeed after cancellation, as in-flight attempts can + still settle afterwards. Canceling will only prevent further attempts from + being sent. + */ + bool cancelable = 24; + + /* + An optional field that can be used to pass an arbitrary set of TLV records + to the first hop peer of this payment. This can be used to pass application + specific data during the payment attempt. Record types are required to be in + the custom range >= 65536. When using REST, the values must be encoded as + base64. + */ + map first_hop_custom_records = 25; } message TrackPaymentRequest { @@ -323,14 +391,39 @@ message TrackPaymentsRequest { message RouteFeeRequest { /* - The destination once wishes to obtain a routing fee quote to. + The destination one wishes to obtain a routing fee quote to. If set, this + parameter requires the amt_sat parameter also to be set. This parameter + combination triggers a graph based routing fee estimation as opposed to a + payment probe based estimate in case a payment request is provided. The + graph based estimation is an algorithm that is executed on the in memory + graph. Hence its runtime is significantly shorter than a payment probe + estimation that sends out actual payments to the network. */ bytes dest = 1; /* - The amount one wishes to send to the target destination. + The amount one wishes to send to the target destination. It is only to be + used in combination with the dest parameter. */ int64 amt_sat = 2; + + /* + A payment request of the target node that the route fee request is intended + for. Its parameters are input to probe payments that estimate routing fees. + The timeout parameter can be specified to set a maximum time on the probing + attempt. Cannot be used in combination with dest and amt_sat. + */ + string payment_request = 3; + + /* + A user preference of how long a probe payment should maximally be allowed to + take, denoted in seconds. The probing payment loop is aborted if this + timeout is reached. Note that the probing process itself can take longer + than the timeout if the HTLC becomes delayed or stuck. Canceling the context + of this call will not cancel the payment loop, the duration is only + controlled by the timeout parameter. + */ + uint32 timeout = 4; } message RouteFeeResponse { @@ -346,6 +439,12 @@ message RouteFeeResponse { value. */ int64 time_lock_delay = 2; + + /* + An indication whether a probing payment succeeded or whether and why it + failed. FAILURE_REASON_NONE indicates success. + */ + lnrpc.PaymentFailureReason failure_reason = 5; } message SendToRouteRequest { @@ -362,6 +461,15 @@ message SendToRouteRequest { routes, incorrect payment details, or insufficient funds. */ bool skip_temp_err = 3; + + /* + An optional field that can be used to pass an arbitrary set of TLV records + to the first hop peer of this payment. This can be used to pass application + specific data during the payment attempt. Record types are required to be in + the custom range >= 65536. When using REST, the values must be encoded as + base64. + */ + map first_hop_custom_records = 4; } message SendToRouteResponse { @@ -465,6 +573,93 @@ message SetMissionControlConfigResponse { } message MissionControlConfig { + /* + Deprecated, use AprioriParameters. The amount of time mission control will + take to restore a penalized node or channel back to 50% success probability, + expressed in seconds. Setting this value to a higher value will penalize + failures for longer, making mission control less likely to route through + nodes and channels that we have previously recorded failures for. + */ + uint64 half_life_seconds = 1 [deprecated = true]; + + /* + Deprecated, use AprioriParameters. The probability of success mission + control should assign to hop in a route where it has no other information + available. Higher values will make mission control more willing to try hops + that we have no information about, lower values will discourage trying these + hops. + */ + float hop_probability = 2 [deprecated = true]; + + /* + Deprecated, use AprioriParameters. The importance that mission control + should place on historical results, expressed as a value in [0;1]. Setting + this value to 1 will ignore all historical payments and just use the hop + probability to assess the probability of success for each hop. A zero value + ignores hop probability completely and relies entirely on historical + results, unless none are available. + */ + float weight = 3 [deprecated = true]; + + /* + The maximum number of payment results that mission control will store. + */ + uint32 maximum_payment_results = 4; + + /* + The minimum time that must have passed since the previously recorded failure + before we raise the failure amount. + */ + uint64 minimum_failure_relax_interval = 5; + + enum ProbabilityModel { + APRIORI = 0; + BIMODAL = 1; + } + + /* + ProbabilityModel defines which probability estimator should be used in + pathfinding. Note that the bimodal estimator is experimental. + */ + ProbabilityModel model = 6; + + /* + EstimatorConfig is populated dependent on the estimator type. + */ + oneof EstimatorConfig { + AprioriParameters apriori = 7; + BimodalParameters bimodal = 8; + } +} + +message BimodalParameters { + /* + NodeWeight defines how strongly other previous forwardings on channels of a + router should be taken into account when computing a channel's probability + to route. The allowed values are in the range [0, 1], where a value of 0 + means that only direct information about a channel is taken into account. + */ + double node_weight = 1; + + /* + ScaleMsat describes the scale over which channels statistically have some + liquidity left. The value determines how quickly the bimodal distribution + drops off from the edges of a channel. A larger value (compared to typical + channel capacities) means that the drop off is slow and that channel + balances are distributed more uniformly. A small value leads to the + assumption of very unbalanced channels. + */ + uint64 scale_msat = 2; + + /* + DecayTime describes the information decay of knowledge about previous + successes and failures in channels. The smaller the decay time, the quicker + we forget about past forwardings. + */ + uint64 decay_time = 3; +} + +message AprioriParameters { /* The amount of time mission control will take to restore a penalized node or channel back to 50% success probability, expressed in seconds. Setting @@ -480,7 +675,7 @@ message MissionControlConfig { control more willing to try hops that we have no information about, lower values will discourage trying these hops. */ - float hop_probability = 2; + double hop_probability = 2; /* The importance that mission control should place on historical results, @@ -490,18 +685,15 @@ message MissionControlConfig { completely and relies entirely on historical results, unless none are available. */ - float weight = 3; + double weight = 3; /* - The maximum number of payment results that mission control will store. + The fraction of a channel's capacity that we consider to have liquidity. For + amounts that come close to or exceed the fraction, an additional penalty is + applied. A value of 1.0 disables the capacity factor. Allowed values are in + [0.75, 1.0]. */ - uint32 maximum_payment_results = 4; - - /* - The minimum time that must have passed since the previously recorded failure - before we raise the failure amount. - */ - uint64 minimum_failure_relax_interval = 5; + double capacity_fraction = 4; } message QueryProbabilityRequest { @@ -548,8 +740,20 @@ message BuildRouteRequest { */ repeated bytes hop_pubkeys = 4; - // An optional payment addr to be included within the last hop of the route. + /* + An optional payment addr to be included within the last hop of the route. + This is also called payment secret in specifications (e.g. BOLT 11). + */ bytes payment_addr = 5; + + /* + An optional field that can be used to pass an arbitrary set of TLV records + to the first hop peer of this payment. This can be used to pass application + specific data during the payment attempt. Record types are required to be in + the custom range >= 65536. When using REST, the values must be encoded as + base64. + */ + map first_hop_custom_records = 6; } message BuildRouteResponse { @@ -806,12 +1010,17 @@ message ForwardHtlcInterceptRequest { // The block height at which this htlc will be auto-failed to prevent the // channel from force-closing. int32 auto_fail_height = 10; + + // The custom records of the peer's incoming p2p wire message. + map in_wire_custom_records = 11; } /** ForwardHtlcInterceptResponse enables the caller to resolve a previously hold forward. The caller can choose either to: - `Resume`: Execute the default behavior (usually forward). +- `ResumeModified`: Execute the default behavior (usually forward) with HTLC + field modifications. - `Reject`: Fail the htlc backwards. - `Settle`: Settle this htlc with a given preimage. */ @@ -842,12 +1051,40 @@ message ForwardHtlcInterceptResponse { // For backwards-compatibility reasons, TEMPORARY_CHANNEL_FAILURE is the // default value for this field. lnrpc.Failure.FailureCode failure_code = 5; + + // The amount that was set on the p2p wire message of the incoming HTLC. + // This field is ignored if the action is not RESUME_MODIFIED or the amount + // is zero. + uint64 in_amount_msat = 6; + + // The amount to set on the p2p wire message of the resumed HTLC. This field + // is ignored if the action is not RESUME_MODIFIED or the amount is zero. + uint64 out_amount_msat = 7; + + // Any custom records that should be set on the p2p wire message message of + // the resumed HTLC. This field is ignored if the action is not + // RESUME_MODIFIED. + // + // This map will merge with the existing set of custom records (if any), + // replacing any conflicting types. Note that there currently is no support + // for deleting existing custom records (they can only be replaced). + map out_wire_custom_records = 8; } enum ResolveHoldForwardAction { + // SETTLE is an action that is used to settle an HTLC instead of forwarding + // it. SETTLE = 0; + + // FAIL is an action that is used to fail an HTLC backwards. FAIL = 1; + + // RESUME is an action that is used to resume a forward HTLC. RESUME = 2; + + // RESUME_MODIFIED is an action that is used to resume a hold forward HTLC + // with modifications specified during interception. + RESUME_MODIFIED = 3; } message UpdateChanStatusRequest { @@ -863,4 +1100,20 @@ enum ChanStatusAction { } message UpdateChanStatusResponse { +} + +message AddAliasesRequest { + repeated lnrpc.AliasMap alias_maps = 1; +} + +message AddAliasesResponse { + repeated lnrpc.AliasMap alias_maps = 1; +} + +message DeleteAliasesRequest { + repeated lnrpc.AliasMap alias_maps = 1; +} + +message DeleteAliasesResponse { + repeated lnrpc.AliasMap alias_maps = 1; } \ No newline at end of file diff --git a/proto/others/walletkit.proto b/proto/others/walletkit.proto index 5ecb18a9..fc81f591 100644 --- a/proto/others/walletkit.proto +++ b/proto/others/walletkit.proto @@ -1172,6 +1172,12 @@ message PendingSweep { The deadline height used for this output when perform fee bumping. */ uint32 deadline_height = 14; + + /* + The block height which the input's locktime will expire at. Zero if the + input has no locktime. + */ + uint32 maturity_height = 15; } message PendingSweepsRequest { @@ -1188,9 +1194,8 @@ message BumpFeeRequest { // The input we're attempting to bump the fee of. lnrpc.OutPoint outpoint = 1; - // Optional. The deadline in number of blocks that the input should be spent - // within. When not set, for new inputs, the default value (1008) is used; - // for existing inputs, their current values will be retained. + // Optional. The conf target the underlying fee estimator will use to + // estimate the starting fee rate for the fee function. uint32 target_conf = 2; /* @@ -1217,7 +1222,7 @@ message BumpFeeRequest { /* Optional. Whether this input will be swept immediately. When set to true, - the sweeper will sweep this input without waiting for the next batch. + the sweeper will sweep this input without waiting for the next block. */ bool immediate = 6; @@ -1230,6 +1235,12 @@ message BumpFeeRequest { retained. */ uint64 budget = 7; + + // Optional. The deadline delta in number of blocks that the output + // should be spent within. This translates internally to the width of the + // fee function that the sweeper will use to bump the fee rate. When the + // deadline is reached, ALL the budget will be spent as fees. + uint32 deadline_delta = 8; } message BumpFeeResponse { @@ -1243,7 +1254,8 @@ message BumpForceCloseFeeRequest { lnrpc.ChannelPoint chan_point = 1; // Optional. The deadline delta in number of blocks that the anchor output - // should be spent within to bump the closing transaction. + // should be spent within to bump the closing transaction. When the + // deadline is reached, ALL the budget will be spent as fees uint32 deadline_delta = 2; /* @@ -1270,6 +1282,10 @@ message BumpForceCloseFeeRequest { transaction of the force closed channel otherwise the fee bumping will fail. */ uint64 budget = 5; + + // Optional. The conf target the underlying fee estimator will use to + // estimate the starting fee rate for the fee function. + uint32 target_conf = 6; } message BumpForceCloseFeeResponse { @@ -1426,6 +1442,16 @@ message FundPsbtRequest { // The max fee to total output amount ratio that this psbt should adhere to. double max_fee_ratio = 12; + + // The custom lock ID to use for the inputs in the funded PSBT. The value + // if set must be exactly 32 bytes long. If empty, the default lock ID will + // be used. + bytes custom_lock_id = 13; + + // If set, then the inputs in the funded PSBT will be locked for the + // specified duration. The lock duration is specified in seconds. If not + // set, the default lock duration will be used. + uint64 lock_expiration_seconds = 14; } message FundPsbtResponse { /* diff --git a/proto/service/structs.proto b/proto/service/structs.proto index 3d64ef67..c98e6607 100644 --- a/proto/service/structs.proto +++ b/proto/service/structs.proto @@ -926,6 +926,10 @@ message InvoiceSwapOperation { optional UserOperation operation_payment = 2; optional string failure_reason = 3; optional int64 completed_at_unix = 6; + + optional string refund_address = 7; + optional int64 refund_at_unix = 8; + optional string refund_tx_id = 9; } message InvoiceSwapsList { diff --git a/src/extensions/README.md b/src/extensions/README.md new file mode 100644 index 00000000..2f4e0b15 --- /dev/null +++ b/src/extensions/README.md @@ -0,0 +1,731 @@ +# Lightning.Pub Extension System + +A modular extension system that allows third-party functionality to be added to Lightning.Pub without modifying core code. + +## Table of Contents + +- [Overview](#overview) +- [Architecture](#architecture) +- [Creating an Extension](#creating-an-extension) +- [Extension Lifecycle](#extension-lifecycle) +- [ExtensionContext API](#extensioncontext-api) +- [Database Isolation](#database-isolation) +- [RPC Methods](#rpc-methods) +- [HTTP Routes](#http-routes) +- [Event Handling](#event-handling) +- [Configuration](#configuration) +- [Examples](#examples) + +--- + +## Overview + +The extension system provides: + +- **Modularity**: Extensions are self-contained modules with their own code and data +- **Isolation**: Each extension gets its own SQLite database +- **Integration**: Extensions can register RPC methods, handle events, and interact with Lightning.Pub's payment and Nostr systems +- **Lifecycle Management**: Automatic discovery, loading, and graceful shutdown + +### Built-in Extensions + +| Extension | Description | +|-----------|-------------| +| `marketplace` | NIP-15 Nostr marketplace for selling products via Lightning | +| `withdraw` | LNURL-withdraw (LUD-03) for vouchers, faucets, and gifts | + +--- + +## Architecture + +``` +┌─────────────────────────────────────────────────────────────────┐ +│ Lightning.Pub │ +├─────────────────────────────────────────────────────────────────┤ +│ Extension Loader │ +│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ +│ │ Extension A │ │ Extension B │ │ Extension C │ ... │ +│ │ ┌───────┐ │ │ ┌───────┐ │ │ ┌───────┐ │ │ +│ │ │Context│ │ │ │Context│ │ │ │Context│ │ │ +│ │ └───────┘ │ │ └───────┘ │ │ └───────┘ │ │ +│ │ ┌───────┐ │ │ ┌───────┐ │ │ ┌───────┐ │ │ +│ │ │ DB │ │ │ │ DB │ │ │ │ DB │ │ │ +│ │ └───────┘ │ │ └───────┘ │ │ └───────┘ │ │ +│ └─────────────┘ └─────────────┘ └─────────────┘ │ +├─────────────────────────────────────────────────────────────────┤ +│ Payment Manager │ Nostr Transport │ Application Manager │ +└─────────────────────────────────────────────────────────────────┘ +``` + +### Key Components + +| Component | File | Description | +|-----------|------|-------------| +| `ExtensionLoader` | `loader.ts` | Discovers, loads, and manages extensions | +| `ExtensionContext` | `context.ts` | Bridge between extensions and Lightning.Pub | +| `ExtensionDatabase` | `database.ts` | Isolated SQLite database per extension | + +--- + +## Creating an Extension + +### Directory Structure + +``` +src/extensions/ +└── my-extension/ + ├── index.ts # Main entry point (required) + ├── types.ts # TypeScript interfaces + ├── migrations.ts # Database migrations + └── managers/ # Business logic + └── myManager.ts +``` + +### Minimal Extension + +```typescript +// src/extensions/my-extension/index.ts + +import { Extension, ExtensionInfo, ExtensionContext, ExtensionDatabase } from '../types.js' + +export default class MyExtension implements Extension { + readonly info: ExtensionInfo = { + id: 'my-extension', // Must match directory name + name: 'My Extension', + version: '1.0.0', + description: 'Does something useful', + author: 'Your Name', + minPubVersion: '1.0.0' // Minimum Lightning.Pub version + } + + async initialize(ctx: ExtensionContext, db: ExtensionDatabase): Promise { + // Run migrations + await db.execute(` + CREATE TABLE IF NOT EXISTS my_table ( + id TEXT PRIMARY KEY, + data TEXT + ) + `) + + // Register RPC methods + ctx.registerMethod('my-extension.doSomething', async (req, appId) => { + return { result: 'done' } + }) + + ctx.log('info', 'Extension initialized') + } + + async shutdown(): Promise { + // Cleanup resources + } +} +``` + +### Extension Interface + +```typescript +interface Extension { + // Required: Extension metadata + readonly info: ExtensionInfo + + // Required: Called once when extension is loaded + initialize(ctx: ExtensionContext, db: ExtensionDatabase): Promise + + // Optional: Called when Lightning.Pub shuts down + shutdown?(): Promise + + // Optional: Health check for monitoring + healthCheck?(): Promise +} + +interface ExtensionInfo { + id: string // Unique identifier (lowercase, no spaces) + name: string // Display name + version: string // Semver version + description: string // Short description + author: string // Author name + minPubVersion?: string // Minimum Lightning.Pub version + dependencies?: string[] // Other extension IDs required +} +``` + +--- + +## Extension Lifecycle + +``` +┌──────────────┐ +│ Discover │ Scan extensions directory for index.ts files +└──────┬───────┘ + │ + ▼ +┌──────────────┐ +│ Load │ Import module, instantiate class +└──────┬───────┘ + │ + ▼ +┌──────────────┐ +│ Initialize │ Create database, call initialize() +└──────┬───────┘ + │ + ▼ +┌──────────────┐ +│ Ready │ Extension is active, handling requests +└──────┬───────┘ + │ + ▼ (on shutdown) +┌──────────────┐ +│ Shutdown │ Call shutdown(), close database +└──────────────┘ +``` + +### States + +| State | Description | +|-------|-------------| +| `loading` | Extension is being loaded | +| `ready` | Extension is active and healthy | +| `error` | Initialization failed | +| `stopped` | Extension has been shut down | + +--- + +## ExtensionContext API + +The `ExtensionContext` is passed to your extension during initialization. It provides access to Lightning.Pub functionality. + +### Application Management + +```typescript +// Get information about an application +const app = await ctx.getApplication(applicationId) +// Returns: { id, name, nostr_public, balance_sats } | null +``` + +### Payment Operations + +```typescript +// Create a Lightning invoice +const invoice = await ctx.createInvoice(amountSats, { + memo: 'Payment for service', + expiry: 3600, // seconds + metadata: { order_id: '123' } // Returned in payment callback +}) +// Returns: { id, paymentRequest, paymentHash, expiry } + +// Pay a Lightning invoice +const result = await ctx.payInvoice(applicationId, bolt11Invoice, maxFeeSats) +// Returns: { paymentHash, feeSats } +``` + +### Nostr Operations + +```typescript +// Send encrypted DM (NIP-44) +const eventId = await ctx.sendEncryptedDM(applicationId, recipientPubkey, content) + +// Publish a Nostr event (signed by application's key) +const eventId = await ctx.publishNostrEvent({ + kind: 30017, + pubkey: appPubkey, + created_at: Math.floor(Date.now() / 1000), + tags: [['d', 'identifier']], + content: JSON.stringify(data) +}) +``` + +### RPC Method Registration + +```typescript +// Register a method that can be called via RPC +ctx.registerMethod('my-extension.methodName', async (request, applicationId, userPubkey?) => { + // request: The RPC request payload + // applicationId: The calling application's ID + // userPubkey: The user's Nostr pubkey (if authenticated) + + return { result: 'success' } +}) +``` + +### Event Subscriptions + +```typescript +// Subscribe to payment received events +ctx.onPaymentReceived(async (payment) => { + // payment: { invoiceId, paymentHash, amountSats, metadata } + + if (payment.metadata?.extension === 'my-extension') { + // Handle payment for this extension + } +}) + +// Subscribe to incoming Nostr events +ctx.onNostrEvent(async (event, applicationId) => { + // event: { id, pubkey, kind, tags, content, created_at } + // applicationId: The application this event is for + + if (event.kind === 4) { // DM + // Handle incoming message + } +}) +``` + +### Logging + +```typescript +ctx.log('debug', 'Detailed debugging info') +ctx.log('info', 'Normal operation info') +ctx.log('warn', 'Warning message') +ctx.log('error', 'Error occurred', errorObject) +``` + +--- + +## Database Isolation + +Each extension gets its own SQLite database file at: +``` +{databaseDir}/{extension-id}.db +``` + +### Database Interface + +```typescript +interface ExtensionDatabase { + // Execute write queries (INSERT, UPDATE, DELETE, CREATE) + execute(sql: string, params?: any[]): Promise<{ changes?: number; lastId?: number }> + + // Execute read queries (SELECT) + query(sql: string, params?: any[]): Promise + + // Run multiple statements in a transaction + transaction(fn: () => Promise): Promise +} +``` + +### Migration Pattern + +```typescript +// migrations.ts + +export interface Migration { + version: number + name: string + up: (db: ExtensionDatabase) => Promise +} + +export const migrations: Migration[] = [ + { + version: 1, + name: 'create_initial_tables', + up: async (db) => { + await db.execute(` + CREATE TABLE items ( + id TEXT PRIMARY KEY, + name TEXT NOT NULL, + created_at INTEGER NOT NULL + ) + `) + } + }, + { + version: 2, + name: 'add_status_column', + up: async (db) => { + await db.execute(`ALTER TABLE items ADD COLUMN status TEXT DEFAULT 'active'`) + } + } +] + +// Run migrations in initialize() +export async function runMigrations(db: ExtensionDatabase): Promise { + const result = await db.query<{ value: string }>( + `SELECT value FROM _extension_meta WHERE key = 'migration_version'` + ).catch(() => []) + + const currentVersion = result.length > 0 ? parseInt(result[0].value, 10) : 0 + + for (const migration of migrations) { + if (migration.version > currentVersion) { + console.log(`Running migration ${migration.version}: ${migration.name}`) + await migration.up(db) + await db.execute( + `INSERT INTO _extension_meta (key, value) VALUES ('migration_version', ?) + ON CONFLICT(key) DO UPDATE SET value = excluded.value`, + [String(migration.version)] + ) + } + } +} +``` + +--- + +## RPC Methods + +Extensions register RPC methods that can be called by clients. + +### Naming Convention + +Methods should be namespaced with the extension ID: +``` +{extension-id}.{methodName} +``` + +Examples: +- `marketplace.createStall` +- `withdraw.createLink` + +### Method Handler Signature + +```typescript +type RpcMethodHandler = ( + request: any, // The request payload + applicationId: string, // The calling application + userPubkey?: string // The authenticated user (if any) +) => Promise +``` + +### Example + +```typescript +ctx.registerMethod('my-extension.createItem', async (req, appId, userPubkey) => { + // Validate request + if (!req.name) { + throw new Error('Name is required') + } + + // Create item + const item = await this.manager.create(appId, req) + + // Return response + return { item } +}) +``` + +--- + +## HTTP Routes + +Some extensions need HTTP endpoints (e.g., LNURL protocol). Extensions can define routes that the main application mounts. + +### Defining Routes + +```typescript +interface HttpRoute { + method: 'GET' | 'POST' + path: string + handler: (req: HttpRequest) => Promise +} + +interface HttpRequest { + params: Record // URL path params + query: Record // Query string params + body?: any // POST body + headers: Record +} + +interface HttpResponse { + status: number + body: any + headers?: Record +} +``` + +### Example + +```typescript +class MyExtension implements Extension { + getHttpRoutes(): HttpRoute[] { + return [ + { + method: 'GET', + path: '/api/v1/my-extension/:id', + handler: async (req) => { + const item = await this.getItem(req.params.id) + return { + status: 200, + body: item, + headers: { 'Content-Type': 'application/json' } + } + } + } + ] + } +} +``` + +--- + +## Event Handling + +### Payment Callbacks + +When you create an invoice with metadata, you'll receive that metadata back in the payment callback: + +```typescript +// Creating invoice with metadata +const invoice = await ctx.createInvoice(1000, { + metadata: { + extension: 'my-extension', + order_id: 'order-123' + } +}) + +// Handling payment +ctx.onPaymentReceived(async (payment) => { + if (payment.metadata?.extension === 'my-extension') { + const orderId = payment.metadata.order_id + await this.handlePayment(orderId, payment) + } +}) +``` + +### Nostr Events + +Subscribe to Nostr events for your application: + +```typescript +ctx.onNostrEvent(async (event, applicationId) => { + // Filter by event kind + if (event.kind === 4) { // Encrypted DM + await this.handleDirectMessage(event, applicationId) + } +}) +``` + +--- + +## Configuration + +### Loader Configuration + +```typescript +interface ExtensionLoaderConfig { + extensionsDir: string // Directory containing extensions + databaseDir: string // Directory for extension databases + enabledExtensions?: string[] // Whitelist (if set, only these load) + disabledExtensions?: string[] // Blacklist +} +``` + +### Usage + +```typescript +import { createExtensionLoader } from './extensions' + +const loader = createExtensionLoader({ + extensionsDir: './src/extensions', + databaseDir: './data/extensions', + disabledExtensions: ['experimental-ext'] +}, mainHandler) + +await loader.loadAll() + +// Call extension methods +const result = await loader.callMethod( + 'marketplace.createStall', + { name: 'My Shop', currency: 'sat', shipping_zones: [] }, + applicationId, + userPubkey +) + +// Dispatch events +loader.dispatchPaymentReceived(paymentData) +loader.dispatchNostrEvent(event, applicationId) + +// Shutdown +await loader.shutdown() +``` + +--- + +## Examples + +### Example: Simple Counter Extension + +```typescript +// src/extensions/counter/index.ts + +import { Extension, ExtensionInfo, ExtensionContext, ExtensionDatabase } from '../types.js' + +export default class CounterExtension implements Extension { + readonly info: ExtensionInfo = { + id: 'counter', + name: 'Simple Counter', + version: '1.0.0', + description: 'A simple counter for each application', + author: 'Example' + } + + private db!: ExtensionDatabase + + async initialize(ctx: ExtensionContext, db: ExtensionDatabase): Promise { + this.db = db + + await db.execute(` + CREATE TABLE IF NOT EXISTS counters ( + application_id TEXT PRIMARY KEY, + count INTEGER NOT NULL DEFAULT 0 + ) + `) + + ctx.registerMethod('counter.increment', async (req, appId) => { + await db.execute( + `INSERT INTO counters (application_id, count) VALUES (?, 1) + ON CONFLICT(application_id) DO UPDATE SET count = count + 1`, + [appId] + ) + const result = await db.query<{ count: number }>( + 'SELECT count FROM counters WHERE application_id = ?', + [appId] + ) + return { count: result[0]?.count || 0 } + }) + + ctx.registerMethod('counter.get', async (req, appId) => { + const result = await db.query<{ count: number }>( + 'SELECT count FROM counters WHERE application_id = ?', + [appId] + ) + return { count: result[0]?.count || 0 } + }) + + ctx.registerMethod('counter.reset', async (req, appId) => { + await db.execute( + 'UPDATE counters SET count = 0 WHERE application_id = ?', + [appId] + ) + return { count: 0 } + }) + } +} +``` + +### Example: Payment-Triggered Extension + +```typescript +// src/extensions/donations/index.ts + +import { Extension, ExtensionContext, ExtensionDatabase } from '../types.js' + +export default class DonationsExtension implements Extension { + readonly info = { + id: 'donations', + name: 'Donations', + version: '1.0.0', + description: 'Accept donations with thank-you messages', + author: 'Example' + } + + private db!: ExtensionDatabase + private ctx!: ExtensionContext + + async initialize(ctx: ExtensionContext, db: ExtensionDatabase): Promise { + this.db = db + this.ctx = ctx + + await db.execute(` + CREATE TABLE IF NOT EXISTS donations ( + id TEXT PRIMARY KEY, + application_id TEXT NOT NULL, + amount_sats INTEGER NOT NULL, + donor_pubkey TEXT, + message TEXT, + created_at INTEGER NOT NULL + ) + `) + + // Create donation invoice + ctx.registerMethod('donations.createInvoice', async (req, appId) => { + const invoice = await ctx.createInvoice(req.amount_sats, { + memo: req.message || 'Donation', + metadata: { + extension: 'donations', + donor_pubkey: req.donor_pubkey, + message: req.message + } + }) + return { invoice: invoice.paymentRequest } + }) + + // Handle successful payments + ctx.onPaymentReceived(async (payment) => { + if (payment.metadata?.extension !== 'donations') return + + // Record donation + await db.execute( + `INSERT INTO donations (id, application_id, amount_sats, donor_pubkey, message, created_at) + VALUES (?, ?, ?, ?, ?, ?)`, + [ + payment.paymentHash, + payment.metadata.application_id, + payment.amountSats, + payment.metadata.donor_pubkey, + payment.metadata.message, + Math.floor(Date.now() / 1000) + ] + ) + + // Send thank-you DM if donor has pubkey + if (payment.metadata.donor_pubkey) { + await ctx.sendEncryptedDM( + payment.metadata.application_id, + payment.metadata.donor_pubkey, + `Thank you for your donation of ${payment.amountSats} sats!` + ) + } + }) + + // List donations + ctx.registerMethod('donations.list', async (req, appId) => { + const donations = await db.query( + `SELECT * FROM donations WHERE application_id = ? ORDER BY created_at DESC LIMIT ?`, + [appId, req.limit || 50] + ) + return { donations } + }) + } +} +``` + +--- + +## Best Practices + +1. **Namespace your methods**: Always prefix RPC methods with your extension ID +2. **Use migrations**: Never modify existing migration files; create new ones +3. **Handle errors gracefully**: Throw descriptive errors, don't return error objects +4. **Clean up in shutdown**: Close connections, cancel timers, etc. +5. **Log appropriately**: Use debug for verbose info, error for failures +6. **Validate inputs**: Check request parameters before processing +7. **Use transactions**: For multi-step database operations +8. **Document your API**: Include types and descriptions for RPC methods + +--- + +## Troubleshooting + +### Extension not loading + +1. Check that directory name matches `info.id` +2. Verify `index.ts` has a default export +3. Check for TypeScript/import errors in logs + +### Database errors + +1. Check migration syntax +2. Verify column types match queries +3. Look for migration version conflicts + +### RPC method not found + +1. Verify method is registered in `initialize()` +2. Check method name includes extension prefix +3. Ensure extension status is `ready` + +### Payment callbacks not firing + +1. Verify `metadata.extension` matches your extension ID +2. Check that `onPaymentReceived` is registered in `initialize()` +3. Confirm invoice was created through the extension diff --git a/src/extensions/context.ts b/src/extensions/context.ts new file mode 100644 index 00000000..b1c6e8d6 --- /dev/null +++ b/src/extensions/context.ts @@ -0,0 +1,309 @@ +import { + ExtensionContext, + ExtensionDatabase, + ExtensionInfo, + ApplicationInfo, + CreateInvoiceOptions, + CreatedInvoice, + PaymentReceivedData, + NostrEvent, + UnsignedNostrEvent, + RpcMethodHandler, + LnurlPayInfo +} from './types.js' + +/** + * Main Handler interface (from Lightning.Pub) + * This is a minimal interface - the actual MainHandler has more methods + */ +export interface MainHandlerInterface { + // Application management + applicationManager: { + getById(id: string): Promise + } + + // Payment operations + paymentManager: { + createInvoice(params: { + applicationId: string + amountSats: number + memo?: string + expiry?: number + metadata?: Record + }): Promise<{ + id: string + paymentRequest: string + paymentHash: string + expiry: number + }> + + payInvoice(params: { + applicationId: string + paymentRequest: string + maxFeeSats?: number + }): Promise<{ + paymentHash: string + feeSats: number + }> + + /** + * Get LNURL-pay info for a user by their Nostr pubkey + * This enables Lightning Address (LUD-16) and zap (NIP-57) support + */ + getLnurlPayInfoByPubkey(pubkeyHex: string, options?: { + metadata?: string + description?: string + }): Promise + } + + // Nostr operations + sendNostrEvent(event: any): Promise + sendEncryptedDM(applicationId: string, recipientPubkey: string, content: string): Promise +} + +/** + * Callback registries for extension events + */ +interface CallbackRegistries { + paymentReceived: Array<(payment: PaymentReceivedData) => Promise> + nostrEvent: Array<(event: NostrEvent, applicationId: string) => Promise> +} + +/** + * Registered RPC method + */ +interface RegisteredMethod { + extensionId: string + handler: RpcMethodHandler +} + +/** + * Extension Context Implementation + * + * Provides the interface for extensions to interact with Lightning.Pub. + * Each extension gets its own context instance. + */ +export class ExtensionContextImpl implements ExtensionContext { + private callbacks: CallbackRegistries = { + paymentReceived: [], + nostrEvent: [] + } + + constructor( + private extensionInfo: ExtensionInfo, + private database: ExtensionDatabase, + private mainHandler: MainHandlerInterface, + private methodRegistry: Map + ) {} + + /** + * Get information about an application + */ + async getApplication(applicationId: string): Promise { + try { + const app = await this.mainHandler.applicationManager.getById(applicationId) + if (!app) return null + + return { + id: app.id, + name: app.name, + nostr_public: app.nostr_public, + balance_sats: app.balance || 0 + } + } catch (e) { + this.log('error', `Failed to get application ${applicationId}:`, e) + return null + } + } + + /** + * Create a Lightning invoice + */ + async createInvoice(amountSats: number, options: CreateInvoiceOptions = {}): Promise { + // Note: In practice, this needs an applicationId. Extensions typically + // get this from the RPC request context. For now, we'll need to handle + // this in the actual implementation. + throw new Error('createInvoice requires applicationId from request context') + } + + /** + * Create invoice with explicit application ID + * This is the internal method used by extensions + */ + async createInvoiceForApp( + applicationId: string, + amountSats: number, + options: CreateInvoiceOptions = {} + ): Promise { + const result = await this.mainHandler.paymentManager.createInvoice({ + applicationId, + amountSats, + memo: options.memo, + expiry: options.expiry, + metadata: { + ...options.metadata, + extension: this.extensionInfo.id + } + }) + + return { + id: result.id, + paymentRequest: result.paymentRequest, + paymentHash: result.paymentHash, + expiry: result.expiry + } + } + + /** + * Pay a Lightning invoice + */ + async payInvoice( + applicationId: string, + paymentRequest: string, + maxFeeSats?: number + ): Promise<{ paymentHash: string; feeSats: number }> { + return this.mainHandler.paymentManager.payInvoice({ + applicationId, + paymentRequest, + maxFeeSats + }) + } + + /** + * Send an encrypted DM via Nostr + */ + async sendEncryptedDM( + applicationId: string, + recipientPubkey: string, + content: string + ): Promise { + return this.mainHandler.sendEncryptedDM(applicationId, recipientPubkey, content) + } + + /** + * Publish a Nostr event + */ + async publishNostrEvent(event: UnsignedNostrEvent): Promise { + return this.mainHandler.sendNostrEvent(event) + } + + /** + * Get LNURL-pay info for a user by pubkey + * Enables Lightning Address and zap support + */ + async getLnurlPayInfo(pubkeyHex: string, options?: { + metadata?: string + description?: string + }): Promise { + return this.mainHandler.paymentManager.getLnurlPayInfoByPubkey(pubkeyHex, options) + } + + /** + * Subscribe to payment received callbacks + */ + onPaymentReceived(callback: (payment: PaymentReceivedData) => Promise): void { + this.callbacks.paymentReceived.push(callback) + } + + /** + * Subscribe to incoming Nostr events + */ + onNostrEvent(callback: (event: NostrEvent, applicationId: string) => Promise): void { + this.callbacks.nostrEvent.push(callback) + } + + /** + * Register an RPC method + */ + registerMethod(name: string, handler: RpcMethodHandler): void { + const fullName = name.startsWith(`${this.extensionInfo.id}.`) + ? name + : `${this.extensionInfo.id}.${name}` + + if (this.methodRegistry.has(fullName)) { + throw new Error(`RPC method ${fullName} already registered`) + } + + this.methodRegistry.set(fullName, { + extensionId: this.extensionInfo.id, + handler + }) + + this.log('debug', `Registered RPC method: ${fullName}`) + } + + /** + * Get the extension's database + */ + getDatabase(): ExtensionDatabase { + return this.database + } + + /** + * Log a message + */ + log(level: 'debug' | 'info' | 'warn' | 'error', message: string, ...args: any[]): void { + const prefix = `[Extension:${this.extensionInfo.id}]` + switch (level) { + case 'debug': + console.debug(prefix, message, ...args) + break + case 'info': + console.info(prefix, message, ...args) + break + case 'warn': + console.warn(prefix, message, ...args) + break + case 'error': + console.error(prefix, message, ...args) + break + } + } + + // ===== Internal Methods (called by ExtensionLoader) ===== + + /** + * Dispatch payment received event to extension callbacks + */ + async dispatchPaymentReceived(payment: PaymentReceivedData): Promise { + for (const callback of this.callbacks.paymentReceived) { + try { + await callback(payment) + } catch (e) { + this.log('error', 'Error in payment callback:', e) + } + } + } + + /** + * Dispatch Nostr event to extension callbacks + */ + async dispatchNostrEvent(event: NostrEvent, applicationId: string): Promise { + for (const callback of this.callbacks.nostrEvent) { + try { + await callback(event, applicationId) + } catch (e) { + this.log('error', 'Error in Nostr event callback:', e) + } + } + } + + /** + * Get registered callbacks for external access + */ + getCallbacks(): CallbackRegistries { + return this.callbacks + } +} + +/** + * Create an extension context + */ +export function createExtensionContext( + extensionInfo: ExtensionInfo, + database: ExtensionDatabase, + mainHandler: MainHandlerInterface, + methodRegistry: Map +): ExtensionContextImpl { + return new ExtensionContextImpl(extensionInfo, database, mainHandler, methodRegistry) +} diff --git a/src/extensions/database.ts b/src/extensions/database.ts new file mode 100644 index 00000000..6f300c36 --- /dev/null +++ b/src/extensions/database.ts @@ -0,0 +1,148 @@ +import Database from 'better-sqlite3' +import path from 'path' +import fs from 'fs' +import { ExtensionDatabase } from './types.js' + +/** + * Extension Database Implementation + * + * Provides isolated SQLite database access for each extension. + * Uses better-sqlite3 for synchronous, high-performance access. + */ +export class ExtensionDatabaseImpl implements ExtensionDatabase { + private db: Database.Database + private extensionId: string + + constructor(extensionId: string, databaseDir: string) { + this.extensionId = extensionId + + // Ensure database directory exists + if (!fs.existsSync(databaseDir)) { + fs.mkdirSync(databaseDir, { recursive: true }) + } + + // Create database file for this extension + const dbPath = path.join(databaseDir, `${extensionId}.db`) + this.db = new Database(dbPath) + + // Enable WAL mode for better concurrency + this.db.pragma('journal_mode = WAL') + + // Enable foreign keys + this.db.pragma('foreign_keys = ON') + + // Create metadata table for tracking migrations + this.db.exec(` + CREATE TABLE IF NOT EXISTS _extension_meta ( + key TEXT PRIMARY KEY, + value TEXT NOT NULL + ) + `) + } + + /** + * Execute a write query (INSERT, UPDATE, DELETE, CREATE, etc.) + */ + async execute(sql: string, params: any[] = []): Promise<{ changes?: number; lastId?: number }> { + try { + const stmt = this.db.prepare(sql) + const result = stmt.run(...params) + + return { + changes: result.changes, + lastId: result.lastInsertRowid as number + } + } catch (e) { + console.error(`[Extension:${this.extensionId}] Database execute error:`, e) + throw e + } + } + + /** + * Execute a read query (SELECT) + */ + async query(sql: string, params: any[] = []): Promise { + try { + const stmt = this.db.prepare(sql) + return stmt.all(...params) as T[] + } catch (e) { + console.error(`[Extension:${this.extensionId}] Database query error:`, e) + throw e + } + } + + /** + * Execute multiple statements in a transaction + */ + async transaction(fn: () => Promise): Promise { + const runTransaction = this.db.transaction(() => { + // Note: better-sqlite3 transactions are synchronous + // We wrap the async function but it executes synchronously + return fn() + }) + + return runTransaction() as T + } + + /** + * Get a metadata value + */ + async getMeta(key: string): Promise { + const rows = await this.query<{ value: string }>( + 'SELECT value FROM _extension_meta WHERE key = ?', + [key] + ) + return rows.length > 0 ? rows[0].value : null + } + + /** + * Set a metadata value + */ + async setMeta(key: string, value: string): Promise { + await this.execute( + `INSERT INTO _extension_meta (key, value) VALUES (?, ?) + ON CONFLICT(key) DO UPDATE SET value = excluded.value`, + [key, value] + ) + } + + /** + * Get current migration version + */ + async getMigrationVersion(): Promise { + const version = await this.getMeta('migration_version') + return version ? parseInt(version, 10) : 0 + } + + /** + * Set migration version + */ + async setMigrationVersion(version: number): Promise { + await this.setMeta('migration_version', String(version)) + } + + /** + * Close the database connection + */ + close(): void { + this.db.close() + } + + /** + * Get the underlying database for advanced operations + * (Use with caution - bypasses isolation) + */ + getUnderlyingDb(): Database.Database { + return this.db + } +} + +/** + * Create an extension database instance + */ +export function createExtensionDatabase( + extensionId: string, + databaseDir: string +): ExtensionDatabaseImpl { + return new ExtensionDatabaseImpl(extensionId, databaseDir) +} diff --git a/src/extensions/index.ts b/src/extensions/index.ts new file mode 100644 index 00000000..208b7c86 --- /dev/null +++ b/src/extensions/index.ts @@ -0,0 +1,56 @@ +/** + * Lightning.Pub Extension System + * + * This module provides the extension infrastructure for Lightning.Pub. + * Extensions can add functionality like marketplaces, subscriptions, + * tipping, and more. + * + * Usage: + * + * ```typescript + * import { createExtensionLoader, ExtensionLoaderConfig } from './extensions' + * + * const config: ExtensionLoaderConfig = { + * extensionsDir: './extensions', + * databaseDir: './data/extensions' + * } + * + * const loader = createExtensionLoader(config, mainHandler) + * await loader.loadAll() + * + * // Call extension methods + * const result = await loader.callMethod( + * 'marketplace.createStall', + * { name: 'My Shop', currency: 'sat', shipping_zones: [...] }, + * applicationId + * ) + * ``` + */ + +// Export types +export { + Extension, + ExtensionInfo, + ExtensionContext, + ExtensionDatabase, + ExtensionModule, + ExtensionConstructor, + LoadedExtension, + ExtensionLoaderConfig, + ApplicationInfo, + CreateInvoiceOptions, + CreatedInvoice, + PaymentReceivedData, + NostrEvent, + UnsignedNostrEvent, + RpcMethodHandler +} from './types.js' + +// Export loader +export { ExtensionLoader, createExtensionLoader } from './loader.js' + +// Export database utilities +export { ExtensionDatabaseImpl, createExtensionDatabase } from './database.js' + +// Export context utilities +export { ExtensionContextImpl, createExtensionContext, MainHandlerInterface } from './context.js' diff --git a/src/extensions/loader.ts b/src/extensions/loader.ts new file mode 100644 index 00000000..9fc453c0 --- /dev/null +++ b/src/extensions/loader.ts @@ -0,0 +1,406 @@ +import path from 'path' +import fs from 'fs' +import { + Extension, + ExtensionInfo, + ExtensionModule, + LoadedExtension, + ExtensionLoaderConfig, + RpcMethodHandler, + PaymentReceivedData, + NostrEvent +} from './types.js' +import { ExtensionDatabaseImpl, createExtensionDatabase } from './database.js' +import { ExtensionContextImpl, createExtensionContext, MainHandlerInterface } from './context.js' + +/** + * Registered RPC method entry + */ +interface RegisteredMethod { + extensionId: string + handler: RpcMethodHandler +} + +/** + * Extension Loader + * + * Discovers, loads, and manages Lightning.Pub extensions. + * Provides lifecycle management and event dispatching. + */ +export class ExtensionLoader { + private config: ExtensionLoaderConfig + private mainHandler: MainHandlerInterface + private extensions: Map = new Map() + private contexts: Map = new Map() + private methodRegistry: Map = new Map() + private initialized = false + + constructor(config: ExtensionLoaderConfig, mainHandler: MainHandlerInterface) { + this.config = config + this.mainHandler = mainHandler + } + + /** + * Discover and load all extensions + */ + async loadAll(): Promise { + if (this.initialized) { + throw new Error('Extension loader already initialized') + } + + console.log('[Extensions] Loading extensions from:', this.config.extensionsDir) + + // Ensure directories exist + if (!fs.existsSync(this.config.extensionsDir)) { + console.log('[Extensions] Extensions directory does not exist, creating...') + fs.mkdirSync(this.config.extensionsDir, { recursive: true }) + this.initialized = true + return + } + + if (!fs.existsSync(this.config.databaseDir)) { + fs.mkdirSync(this.config.databaseDir, { recursive: true }) + } + + // Discover extensions + const extensionDirs = await this.discoverExtensions() + console.log(`[Extensions] Found ${extensionDirs.length} extension(s)`) + + // Load extensions in dependency order + const loadOrder = await this.resolveDependencies(extensionDirs) + + for (const extDir of loadOrder) { + try { + await this.loadExtension(extDir) + } catch (e) { + console.error(`[Extensions] Failed to load extension from ${extDir}:`, e) + } + } + + this.initialized = true + console.log(`[Extensions] Loaded ${this.extensions.size} extension(s)`) + } + + /** + * Discover extension directories + */ + private async discoverExtensions(): Promise { + const entries = fs.readdirSync(this.config.extensionsDir, { withFileTypes: true }) + const extensionDirs: string[] = [] + + for (const entry of entries) { + if (!entry.isDirectory()) continue + + const extDir = path.join(this.config.extensionsDir, entry.name) + const indexPath = path.join(extDir, 'index.ts') + const indexJsPath = path.join(extDir, 'index.js') + + // Check for index file + if (fs.existsSync(indexPath) || fs.existsSync(indexJsPath)) { + // Check enabled/disabled lists + if (this.config.disabledExtensions?.includes(entry.name)) { + console.log(`[Extensions] Skipping disabled extension: ${entry.name}`) + continue + } + + if (this.config.enabledExtensions && + !this.config.enabledExtensions.includes(entry.name)) { + console.log(`[Extensions] Skipping non-enabled extension: ${entry.name}`) + continue + } + + extensionDirs.push(extDir) + } + } + + return extensionDirs + } + + /** + * Resolve extension dependencies and return load order + */ + private async resolveDependencies(extensionDirs: string[]): Promise { + // For now, simple alphabetical order + // TODO: Implement proper dependency resolution with topological sort + return extensionDirs.sort() + } + + /** + * Load a single extension + */ + private async loadExtension(extensionDir: string): Promise { + const dirName = path.basename(extensionDir) + console.log(`[Extensions] Loading extension: ${dirName}`) + + // Determine index file path + let indexPath = path.join(extensionDir, 'index.js') + if (!fs.existsSync(indexPath)) { + indexPath = path.join(extensionDir, 'index.ts') + } + + // Dynamic import + const moduleUrl = `file://${indexPath}` + const module = await import(moduleUrl) as ExtensionModule + + if (!module.default) { + throw new Error(`Extension ${dirName} has no default export`) + } + + // Instantiate extension + const ExtensionClass = module.default + const instance = new ExtensionClass() as Extension + + if (!instance.info) { + throw new Error(`Extension ${dirName} has no info property`) + } + + const info = instance.info + + // Validate extension ID matches directory name + if (info.id !== dirName) { + console.warn( + `[Extensions] Extension ID '${info.id}' doesn't match directory '${dirName}'` + ) + } + + // Check for duplicate + if (this.extensions.has(info.id)) { + throw new Error(`Extension ${info.id} already loaded`) + } + + // Create isolated database + const database = createExtensionDatabase(info.id, this.config.databaseDir) + + // Create context + const context = createExtensionContext( + info, + database, + this.mainHandler, + this.methodRegistry + ) + + // Track as loading + const loaded: LoadedExtension = { + info, + instance, + database, + status: 'loading', + loadedAt: Date.now() + } + this.extensions.set(info.id, loaded) + this.contexts.set(info.id, context) + + try { + // Initialize extension + await instance.initialize(context, database) + + loaded.status = 'ready' + console.log(`[Extensions] Extension ${info.id} v${info.version} loaded successfully`) + } catch (e) { + loaded.status = 'error' + loaded.error = e as Error + console.error(`[Extensions] Extension ${info.id} initialization failed:`, e) + throw e + } + } + + /** + * Unload a specific extension + */ + async unloadExtension(extensionId: string): Promise { + const loaded = this.extensions.get(extensionId) + if (!loaded) { + throw new Error(`Extension ${extensionId} not found`) + } + + console.log(`[Extensions] Unloading extension: ${extensionId}`) + + try { + // Call shutdown if available + if (loaded.instance.shutdown) { + await loaded.instance.shutdown() + } + + loaded.status = 'stopped' + } catch (e) { + console.error(`[Extensions] Error during ${extensionId} shutdown:`, e) + } + + // Close database + if (loaded.database instanceof ExtensionDatabaseImpl) { + loaded.database.close() + } + + // Remove registered methods + for (const [name, method] of this.methodRegistry.entries()) { + if (method.extensionId === extensionId) { + this.methodRegistry.delete(name) + } + } + + // Remove from maps + this.extensions.delete(extensionId) + this.contexts.delete(extensionId) + } + + /** + * Shutdown all extensions + */ + async shutdown(): Promise { + console.log('[Extensions] Shutting down all extensions...') + + for (const extensionId of this.extensions.keys()) { + try { + await this.unloadExtension(extensionId) + } catch (e) { + console.error(`[Extensions] Error unloading ${extensionId}:`, e) + } + } + + console.log('[Extensions] All extensions shut down') + } + + /** + * Get a loaded extension + */ + getExtension(extensionId: string): LoadedExtension | undefined { + return this.extensions.get(extensionId) + } + + /** + * Get all loaded extensions + */ + getAllExtensions(): LoadedExtension[] { + return Array.from(this.extensions.values()) + } + + /** + * Check if an extension is loaded and ready + */ + isReady(extensionId: string): boolean { + const ext = this.extensions.get(extensionId) + return ext?.status === 'ready' + } + + /** + * Get all registered RPC methods + */ + getRegisteredMethods(): Map { + return this.methodRegistry + } + + /** + * Call an extension RPC method + */ + async callMethod( + methodName: string, + request: any, + applicationId: string, + userPubkey?: string + ): Promise { + const method = this.methodRegistry.get(methodName) + if (!method) { + throw new Error(`Unknown method: ${methodName}`) + } + + const ext = this.extensions.get(method.extensionId) + if (!ext || ext.status !== 'ready') { + throw new Error(`Extension ${method.extensionId} not ready`) + } + + return method.handler(request, applicationId, userPubkey) + } + + /** + * Check if a method exists + */ + hasMethod(methodName: string): boolean { + return this.methodRegistry.has(methodName) + } + + /** + * Dispatch payment received event to all extensions + */ + async dispatchPaymentReceived(payment: PaymentReceivedData): Promise { + for (const context of this.contexts.values()) { + try { + await context.dispatchPaymentReceived(payment) + } catch (e) { + console.error('[Extensions] Error dispatching payment:', e) + } + } + } + + /** + * Dispatch Nostr event to all extensions + */ + async dispatchNostrEvent(event: NostrEvent, applicationId: string): Promise { + for (const context of this.contexts.values()) { + try { + await context.dispatchNostrEvent(event, applicationId) + } catch (e) { + console.error('[Extensions] Error dispatching Nostr event:', e) + } + } + } + + /** + * Run health checks on all extensions + */ + async healthCheck(): Promise> { + const results = new Map() + + for (const [id, ext] of this.extensions.entries()) { + if (ext.status !== 'ready') { + results.set(id, false) + continue + } + + try { + if (ext.instance.healthCheck) { + results.set(id, await ext.instance.healthCheck()) + } else { + results.set(id, true) + } + } catch (e) { + results.set(id, false) + } + } + + return results + } + + /** + * Get extension status summary + */ + getStatus(): { + total: number + ready: number + error: number + extensions: Array<{ id: string; name: string; version: string; status: string }> + } { + const extensions = this.getAllExtensions().map(ext => ({ + id: ext.info.id, + name: ext.info.name, + version: ext.info.version, + status: ext.status + })) + + return { + total: extensions.length, + ready: extensions.filter(e => e.status === 'ready').length, + error: extensions.filter(e => e.status === 'error').length, + extensions + } + } +} + +/** + * Create an extension loader instance + */ +export function createExtensionLoader( + config: ExtensionLoaderConfig, + mainHandler: MainHandlerInterface +): ExtensionLoader { + return new ExtensionLoader(config, mainHandler) +} diff --git a/src/extensions/types.ts b/src/extensions/types.ts new file mode 100644 index 00000000..2027fb09 --- /dev/null +++ b/src/extensions/types.ts @@ -0,0 +1,285 @@ +/** + * Extension System Core Types + * + * These types define the contract between Lightning.Pub and extensions. + */ + +/** + * Extension metadata + */ +export interface ExtensionInfo { + id: string // Unique identifier (lowercase, no spaces) + name: string // Display name + version: string // Semver version + description: string // Short description + author: string // Author name or organization + minPubVersion?: string // Minimum Lightning.Pub version required + dependencies?: string[] // Other extension IDs this depends on +} + +/** + * Extension database interface + * Provides isolated database access for each extension + */ +export interface ExtensionDatabase { + /** + * Execute a write query (INSERT, UPDATE, DELETE, CREATE, etc.) + */ + execute(sql: string, params?: any[]): Promise<{ changes?: number; lastId?: number }> + + /** + * Execute a read query (SELECT) + */ + query(sql: string, params?: any[]): Promise + + /** + * Execute multiple statements in a transaction + */ + transaction(fn: () => Promise): Promise +} + +/** + * Application info provided to extensions + */ +export interface ApplicationInfo { + id: string + name: string + nostr_public: string // Application's Nostr pubkey (hex) + balance_sats: number +} + +/** + * Invoice creation options + */ +export interface CreateInvoiceOptions { + memo?: string + expiry?: number // Seconds until expiry + metadata?: Record // Custom metadata for callbacks +} + +/** + * Created invoice result + */ +export interface CreatedInvoice { + id: string // Internal invoice ID + paymentRequest: string // BOLT11 invoice string + paymentHash: string // Payment hash (hex) + expiry: number // Expiry timestamp +} + +/** + * Payment received callback data + */ +export interface PaymentReceivedData { + invoiceId: string + paymentHash: string + amountSats: number + metadata?: Record +} + +/** + * LNURL-pay info response (LUD-06/LUD-16) + * Used for Lightning Address and zap support + */ +export interface LnurlPayInfo { + tag: 'payRequest' + callback: string // URL to call with amount + minSendable: number // Minimum msats + maxSendable: number // Maximum msats + metadata: string // JSON-encoded metadata array + allowsNostr?: boolean // Whether zaps are supported + nostrPubkey?: string // Pubkey for zap receipts (hex) +} + +/** + * Nostr event structure (minimal) + */ +export interface NostrEvent { + id: string + pubkey: string + created_at: number + kind: number + tags: string[][] + content: string + sig?: string +} + +/** + * Unsigned Nostr event for publishing + */ +export interface UnsignedNostrEvent { + kind: number + pubkey: string + created_at: number + tags: string[][] + content: string +} + +/** + * RPC method handler function + */ +export type RpcMethodHandler = ( + request: any, + applicationId: string, + userPubkey?: string +) => Promise + +/** + * Extension context - interface provided to extensions for interacting with Lightning.Pub + */ +export interface ExtensionContext { + /** + * Get information about an application + */ + getApplication(applicationId: string): Promise + + /** + * Create a Lightning invoice + */ + createInvoice(amountSats: number, options?: CreateInvoiceOptions): Promise + + /** + * Pay a Lightning invoice (requires sufficient balance) + */ + payInvoice(applicationId: string, paymentRequest: string, maxFeeSats?: number): Promise<{ + paymentHash: string + feeSats: number + }> + + /** + * Send an encrypted DM via Nostr (NIP-44) + */ + sendEncryptedDM(applicationId: string, recipientPubkey: string, content: string): Promise + + /** + * Publish a Nostr event (signed by application's key) + */ + publishNostrEvent(event: UnsignedNostrEvent): Promise + + /** + * Get LNURL-pay info for a user (by pubkey) + * Used to enable Lightning Address support (LUD-16) and zaps (NIP-57) + */ + getLnurlPayInfo(pubkeyHex: string, options?: { + metadata?: string // Custom metadata JSON + description?: string // Human-readable description + }): Promise + + /** + * Subscribe to payment received callbacks + */ + onPaymentReceived(callback: (payment: PaymentReceivedData) => Promise): void + + /** + * Subscribe to incoming Nostr events for the application + */ + onNostrEvent(callback: (event: NostrEvent, applicationId: string) => Promise): void + + /** + * Register an RPC method + */ + registerMethod(name: string, handler: RpcMethodHandler): void + + /** + * Get the extension's isolated database + */ + getDatabase(): ExtensionDatabase + + /** + * Log a message (prefixed with extension ID) + */ + log(level: 'debug' | 'info' | 'warn' | 'error', message: string, ...args: any[]): void +} + +/** + * HTTP route handler types + * Used by extensions that expose HTTP endpoints (e.g. LNURL, .well-known) + */ +export interface HttpRequest { + method: string + path: string + params: Record + query: Record + headers: Record + body?: any +} + +export interface HttpResponse { + status: number + body: any + headers?: Record +} + +export interface HttpRoute { + method: 'GET' | 'POST' + path: string + handler: (req: HttpRequest) => Promise +} + +/** + * Extension interface - what extensions must implement + */ +export interface Extension { + /** + * Extension metadata + */ + readonly info: ExtensionInfo + + /** + * Initialize the extension + * Called once when the extension is loaded + */ + initialize(ctx: ExtensionContext, db: ExtensionDatabase): Promise + + /** + * Shutdown the extension + * Called when Lightning.Pub is shutting down + */ + shutdown?(): Promise + + /** + * Health check + * Return true if extension is healthy + */ + healthCheck?(): Promise + + /** + * Get HTTP routes exposed by this extension + * The main HTTP server will mount these routes + */ + getHttpRoutes?(): HttpRoute[] +} + +/** + * Extension constructor type + */ +export type ExtensionConstructor = new () => Extension + +/** + * Extension module default export + */ +export interface ExtensionModule { + default: ExtensionConstructor +} + +/** + * Loaded extension state + */ +export interface LoadedExtension { + info: ExtensionInfo + instance: Extension + database: ExtensionDatabase + status: 'loading' | 'ready' | 'error' | 'stopped' + error?: Error + loadedAt: number +} + +/** + * Extension loader configuration + */ +export interface ExtensionLoaderConfig { + extensionsDir: string // Directory containing extensions + databaseDir: string // Directory for extension databases + enabledExtensions?: string[] // If set, only load these extensions + disabledExtensions?: string[] // Extensions to skip +} diff --git a/src/services/lnd/lnd.ts b/src/services/lnd/lnd.ts index 8ccc42ee..ce19eae5 100644 --- a/src/services/lnd/lnd.ts +++ b/src/services/lnd/lnd.ts @@ -207,7 +207,7 @@ export default class { cooperative: true, fundingCanceled: true, localForce: true, - remoteForce: true + remoteForce: true, }, DeadLineMetadata()) return res.response } @@ -294,6 +294,8 @@ export default class { account: "", endHeight: 0, startHeight: this.latestKnownBlockHeigh, + indexOffset: 0, + maxTransactions: 0 }, { abort: this.abortController.signal }) stream.responses.onMessage(tx => { if (tx.blockHeight > this.latestKnownBlockHeigh) { @@ -547,7 +549,7 @@ export default class { async GetTransactions(startHeight: number): Promise { this.log(DEBUG, "Getting transactions") - const res = await this.lightning.getTransactions({ startHeight, endHeight: 0, account: "", }, DeadLineMetadata()) + const res = await this.lightning.getTransactions({ startHeight, endHeight: 0, account: "", indexOffset: 0, maxTransactions: 0 }, DeadLineMetadata()) return res.response } @@ -571,6 +573,7 @@ export default class { inboundFee: undefined, feeRatePpm: policy.fee_rate_ppm, minHtlcMsatSpecified: policy.min_htlc_msat > 0, + createMissingEdge: false, }, DeadLineMetadata()) return res.response } @@ -656,7 +659,8 @@ export default class { txidBytes: Buffer.alloc(0) }, force: false, - satPerByte: 0 + satPerByte: 0, + deadlineDelta: 0 }, DeadLineMetadata()) return res.response } diff --git a/src/services/lnd/payInvoiceReq.ts b/src/services/lnd/payInvoiceReq.ts index 323448e0..3b90dd3d 100644 --- a/src/services/lnd/payInvoiceReq.ts +++ b/src/services/lnd/payInvoiceReq.ts @@ -25,5 +25,7 @@ export const PayInvoiceReq = (invoice: string, amount: number, feeLimit: number) paymentHash: Buffer.alloc(0), routeHints: [], timePref: 0, - outgoingChanId: '0' + outgoingChanId: '0', + cancelable: false, + firstHopCustomRecords: {} }) \ No newline at end of file diff --git a/src/services/lnd/swaps/swaps.ts b/src/services/lnd/swaps/swaps.ts index 0aaf9e32..0360a879 100644 --- a/src/services/lnd/swaps/swaps.ts +++ b/src/services/lnd/swaps/swaps.ts @@ -99,6 +99,9 @@ export class Swaps { quote: this.mapInvoiceSwapQuote(s), failure_reason: s.failure_reason, completed_at_unix: s.completed_at_unix || 1, + refund_address: s.refund_address, + refund_at_unix: s.refund_at_unix, + refund_tx_id: s.refund_tx_id, })) return { current_block_height: currentBlockHeight, @@ -132,6 +135,7 @@ export class Swaps { if (!result.ok) { throw new Error(result.error) } + await this.storage.paymentStorage.UpdateRefundInvoiceSwap(swapOperationId, refundAddress, result.publish.txId) if (result.publish.done) { return { published: true, txId: result.publish.txId } } @@ -169,7 +173,7 @@ export class Swaps { await this.storage.paymentStorage.FinalizeInvoiceSwap(swapOpId) this.log("invoice swap completed", { swapOpId, txId }) } else { - await this.storage.paymentStorage.FailInvoiceSwap(swapOpId, result.error, txId) + await this.storage.paymentStorage.FailInvoiceSwap(swapOpId, result.error) this.log("invoice swap failed", { swapOpId, error: result.error }) } }, () => payAddress(swap.address, swap.transaction_amount) diff --git a/src/services/main/appUserManager.ts b/src/services/main/appUserManager.ts index b9bf8742..be0ae2cb 100644 --- a/src/services/main/appUserManager.ts +++ b/src/services/main/appUserManager.ts @@ -183,14 +183,23 @@ export default class { } this.log("Deleting user", userId, "progress", i + 1, "/", toDelete.length) await this.storage.StartTransaction(async tx => { - for (const appUserId of appUserIds) { + for (let j = 0; j < appUserIds.length; j++) { + const appUserId = appUserIds[j] + this.log("Deleting app user", appUserId, "progress", j + 1, "/", appUserIds.length) + this.log("Removing user grants") await this.storage.managementStorage.removeUserGrants(appUserId, tx) + this.log("Removing user offers") await this.storage.offerStorage.DeleteUserOffers(appUserId, tx) + this.log("Removing user debit access") await this.storage.debitStorage.RemoveUserDebitAccess(appUserId, tx) + this.log("Removing user devices") await this.storage.applicationStorage.RemoveAppUserDevices(appUserId, tx) } + this.log("Removing user invoices") await this.storage.paymentStorage.RemoveUserInvoices(userId, tx) + this.log("Removing user products") await this.storage.productStorage.RemoveUserProducts(userId, tx) + this.log("Removing user ephemeral keys") await this.storage.paymentStorage.RemoveUserEphemeralKeys(userId, tx) await this.storage.paymentStorage.RemoveUserInvoicePayments(userId, tx) await this.storage.paymentStorage.RemoveUserTransactionPayments(userId, tx) diff --git a/src/services/main/applicationManager.ts b/src/services/main/applicationManager.ts index ecfc7b85..0f186e4c 100644 --- a/src/services/main/applicationManager.ts +++ b/src/services/main/applicationManager.ts @@ -194,7 +194,7 @@ export default class { const cbUrl = req.http_callback_url || receiver.callback_url || "" let zapInfo: ZapInfo | undefined = undefined if (req.invoice_req.zap) { - zapInfo = this.paymentManager.validateZapEvent(req.invoice_req.zap, req.invoice_req.amountSats) + zapInfo = this.paymentManager.validateZapEvent(req.invoice_req.zap, req.invoice_req.amountSats * 1000) } const expiry = req.invoice_req.expiry ? Math.min(req.invoice_req.expiry, defaultInvoiceExpiry) : defaultInvoiceExpiry const opts: InboundOptionals = { @@ -241,6 +241,8 @@ export default class { const paid = await this.paymentManager.PayInvoice(appUser.user.user_id, req, app, { ack: pendingOp => { this.notifyAppUserPayment(appUser, pendingOp) } }) + // Refresh appUser balance from DB so notification has accurate latest_balance + appUser.user.balance_sats = paid.latest_balance this.notifyAppUserPayment(appUser, paid.operation) getLogger({ appName: app.name })(appUser.identifier, "invoice paid", paid.amount_paid, "sats") return paid diff --git a/src/services/main/index.ts b/src/services/main/index.ts index 81de5ada..b2a09fe0 100644 --- a/src/services/main/index.ts +++ b/src/services/main/index.ts @@ -162,7 +162,7 @@ export default class { NewBlockHandler = async (height: number, skipMetrics?: boolean) => { let confirmed: (PendingTx & { confs: number; })[] let log = getLogger({}) - log("NewBlockHandler called", JSON.stringify({ height, skipMetrics })) + // log("NewBlockHandler called", JSON.stringify({ height, skipMetrics })) this.storage.paymentStorage.DeleteExpiredTransactionSwaps(height) .catch(err => log(ERROR, "failed to delete expired transaction swaps", err.message || err)) this.storage.paymentStorage.DeleteExpiredInvoiceSwaps(height) @@ -178,7 +178,9 @@ export default class { log(ERROR, "failed to check transactions after new block", err.message || err) return } - log("NewBlockHandler new confirmed transactions", confirmed.length) + if (confirmed.length > 0) { + log("NewBlockHandler new confirmed transactions", confirmed.length) + } await Promise.all(confirmed.map(async c => { if (c.type === 'outgoing') { await this.storage.paymentStorage.UpdateUserTransactionPayment(c.tx.serial_id, { confs: c.confs }) diff --git a/src/services/main/paymentManager.ts b/src/services/main/paymentManager.ts index 7d96898d..dbf20ed8 100644 --- a/src/services/main/paymentManager.ts +++ b/src/services/main/paymentManager.ts @@ -987,7 +987,9 @@ export default class { async CheckNewlyConfirmedTxs() { const pending = await this.storage.paymentStorage.GetPendingTransactions() let log = getLogger({}) - log("CheckNewlyConfirmedTxs ", pending.incoming.length, "incoming", pending.outgoing.length, "outgoing") + if (pending.incoming.length > 0 || pending.outgoing.length > 0) { + log("CheckNewlyConfirmedTxs ", pending.incoming.length, "incoming", pending.outgoing.length, "outgoing") + } const confirmedIncoming: (PendingTx & { confs: number })[] = [] const confirmedOutgoing: (PendingTx & { confs: number })[] = [] for (const tx of pending.incoming) { diff --git a/src/services/metrics/index.ts b/src/services/metrics/index.ts index 9e23b665..c4b1c923 100644 --- a/src/services/metrics/index.ts +++ b/src/services/metrics/index.ts @@ -12,12 +12,15 @@ import HtlcTracker from './htlcTracker.js' import { getLogger } from '../helpers/logger.js' import { encodeTLV, usageMetricsToTlv } from '../helpers/tlv.js' import { ChannelCloseSummary_ClosureType } from '../../../proto/lnd/lightning.js' - +const cacheTTL = 1000 * 60 * 5 // 5 minutes export default class Handler { storage: Storage lnd: LND htlcTracker: HtlcTracker + appsMetricsCache: CacheController = new CacheController() + lndForwardingMetricsCache: CacheController = new CacheController() + lndMetricsCache: CacheController = new CacheController() logger = getLogger({ component: "metrics" }) constructor(storage: Storage, lnd: LND) { this.storage = storage @@ -183,8 +186,6 @@ export default class Handler { }) } - - /* addTrackedMetric = (appId: string, method: string, metric: Uint8Array) => { if (!this.metaReady) { throw new Error("meta metrics not ready") @@ -203,13 +204,21 @@ export default class Handler { } */ async GetAppsMetrics(req: Types.AppsMetricsRequest): Promise { + const cached = this.appsMetricsCache.Get(req) + const now = Date.now() + if (cached && now - cached.createdAt < cacheTTL) { + + return cached.metrics + } const dbApps = await this.storage.applicationStorage.GetApplications() const apps = await Promise.all(dbApps.map(app => this.GetAppMetrics(req, app))) const unlinked = await this.GetAppMetrics(req, null) apps.push(unlinked) - return { + const metrics = { apps } + this.appsMetricsCache.Set(req, { metrics, createdAt: now }) + return metrics } async GetAppMetrics(req: Types.AppsMetricsRequest, app: Application | null): Promise { @@ -332,6 +341,11 @@ export default class Handler { } async GetLndForwardingMetrics(req: Types.LndMetricsRequest): Promise { + const cached = this.lndForwardingMetricsCache.Get(req) + const now = Date.now() + if (cached && now - cached.createdAt < cacheTTL) { + return cached.metrics + } const fwEvents = await this.lnd.GetForwardingHistory(0, req.from_unix, req.to_unix) let totalFees = 0 const events: Types.LndForwardingEvent[] = fwEvents.forwardingEvents.map(e => { @@ -340,14 +354,21 @@ export default class Handler { chan_id_in: e.chanIdIn, chan_id_out: e.chanIdOut, amt_in: Number(e.amtIn), amt_out: Number(e.amtOut), fee: Number(e.fee), at_unix: Number(e.timestampNs) } }) - return { + const metrics = { total_fees: totalFees, events: events } + this.lndForwardingMetricsCache.Set(req, { metrics, createdAt: now }) + return metrics } async GetLndMetrics(req: Types.LndMetricsRequest): Promise { + const cached = this.lndMetricsCache.Get(req) + const now = Date.now() + if (cached && now - cached.createdAt < cacheTTL) { + return cached.metrics + } const [chansInfo, pendingChansInfo, closedChansInfo, routing, rootOps, channelsActivity] = await Promise.all([ this.GetChannelsInfo(), this.GetPendingChannelsInfo(), @@ -392,7 +413,7 @@ export default class Handler { } })) - return { + const metrics = { nodes: [{ chain_balance: chainBalance, channel_balance: chansBalance, @@ -408,6 +429,8 @@ export default class Handler { root_ops: rootOps.map(r => ({ amount: r.operation_amount, created_at_unix: r.at_unix || 0, op_id: r.operation_identifier, op_type: mapRootOpType(r.operation_type) })), }], } + this.lndMetricsCache.Set(req, { metrics, createdAt: now }) + return metrics } async AddRootAddressPaid(address: string, txOutput: { hash: string; index: number }, amount: number) { @@ -432,4 +455,32 @@ const mapRootOpType = (opType: string): Types.OperationType => { default: throw new Error("Unknown operation type") } +} + +type CacheData = { + metrics: T + createdAt: number +} + +class CacheController { + private cache: Record> = {} + Get = (req: Types.AppsMetricsRequest): CacheData | undefined => { + const key = this.getKey(req) + return this.cache[key] + } + Set = (req: Types.AppsMetricsRequest, metrics: CacheData) => { + const key = this.getKey(req) + this.cache[key] = metrics + } + Clear = (req: Types.AppsMetricsRequest) => { + const key = this.getKey(req) + delete this.cache[key] + } + + private getKey = (req: Types.AppsMetricsRequest) => { + const start = req.from_unix || 0 + const end = req.to_unix || 0 + const includeOperations = req.include_operations ? "1" : "0" + return `${start}:${end}:${includeOperations}` + } } \ No newline at end of file diff --git a/src/services/nostr/nip44v1.ts b/src/services/nostr/nip44v1.ts index 0f37f620..1eb18046 100644 --- a/src/services/nostr/nip44v1.ts +++ b/src/services/nostr/nip44v1.ts @@ -1,14 +1,14 @@ -import { base64 } from "@scure/base"; +import { base64, hex } from "@scure/base"; import { randomBytes } from "@noble/hashes/utils"; import { streamXOR as xchacha20 } from "@stablelib/xchacha20"; -import { secp256k1 } from "@noble/curves/secp256k1"; +import { secp256k1 } from "@noble/curves/secp256k1.js"; import { sha256 } from "@noble/hashes/sha256"; export type EncryptedData = { ciphertext: Uint8Array; nonce: Uint8Array; } export const getSharedSecret = (privateKey: string, publicKey: string) => { - const key = secp256k1.getSharedSecret(privateKey, "02" + publicKey); + const key = secp256k1.getSharedSecret(hex.decode(privateKey), hex.decode("02" + publicKey)); return sha256(key.slice(1, 33)); } diff --git a/src/services/storage/db/transactionsQueue.ts b/src/services/storage/db/transactionsQueue.ts index 94c31fcd..ed07bed8 100644 --- a/src/services/storage/db/transactionsQueue.ts +++ b/src/services/storage/db/transactionsQueue.ts @@ -84,7 +84,7 @@ export default class { async execNextInQueue() { this.pendingTx = false - const next = this.transactionsQueue.pop() + const next = this.transactionsQueue.shift() if (!next) { this.doneWriting() return diff --git a/src/services/storage/entity/InvoiceSwap.ts b/src/services/storage/entity/InvoiceSwap.ts index 746756b8..1ccba147 100644 --- a/src/services/storage/entity/InvoiceSwap.ts +++ b/src/services/storage/entity/InvoiceSwap.ts @@ -80,8 +80,14 @@ export class InvoiceSwap { @Column({ default: "", type: "text" }) lockup_tx_hex: string - /* @Column({ default: "" }) - address_paid: string */ + @Column({ default: "" }) + refund_address: string + + @Column({ default: "" }) + refund_at_unix: number + + @Column({ default: "" }) + refund_tx_id: string @Column({ default: "" }) service_url: string diff --git a/src/services/storage/migrations/1773082318982-refund_swap_info.ts b/src/services/storage/migrations/1773082318982-refund_swap_info.ts new file mode 100644 index 00000000..b9058c10 --- /dev/null +++ b/src/services/storage/migrations/1773082318982-refund_swap_info.ts @@ -0,0 +1,20 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class RefundSwapInfo1773082318982 implements MigrationInterface { + name = 'RefundSwapInfo1773082318982' + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(`CREATE TABLE "temporary_invoice_swap" ("swap_operation_id" varchar PRIMARY KEY NOT NULL, "app_user_id" varchar NOT NULL, "swap_quote_id" varchar NOT NULL, "swap_tree" varchar NOT NULL, "claim_public_key" varchar NOT NULL, "payment_hash" varchar NOT NULL, "timeout_block_height" integer NOT NULL, "invoice" varchar NOT NULL, "invoice_amount" integer NOT NULL, "transaction_amount" integer NOT NULL, "swap_fee_sats" integer NOT NULL, "chain_fee_sats" integer NOT NULL, "ephemeral_public_key" varchar NOT NULL, "address" varchar NOT NULL, "ephemeral_private_key" varchar NOT NULL, "used" boolean NOT NULL DEFAULT (0), "preimage" varchar NOT NULL DEFAULT (''), "failure_reason" varchar NOT NULL DEFAULT (''), "tx_id" varchar NOT NULL DEFAULT (''), "service_url" varchar NOT NULL DEFAULT (''), "created_at" datetime NOT NULL DEFAULT (datetime('now')), "updated_at" datetime NOT NULL DEFAULT (datetime('now')), "lockup_tx_hex" text NOT NULL DEFAULT (''), "completed_at_unix" integer NOT NULL DEFAULT (0), "paid_at_unix" integer NOT NULL DEFAULT (0), "refund_address" varchar NOT NULL DEFAULT (''), "refund_at_unix" integer NOT NULL DEFAULT (''), "refund_tx_id" varchar NOT NULL DEFAULT (''))`); + await queryRunner.query(`INSERT INTO "temporary_invoice_swap"("swap_operation_id", "app_user_id", "swap_quote_id", "swap_tree", "claim_public_key", "payment_hash", "timeout_block_height", "invoice", "invoice_amount", "transaction_amount", "swap_fee_sats", "chain_fee_sats", "ephemeral_public_key", "address", "ephemeral_private_key", "used", "preimage", "failure_reason", "tx_id", "service_url", "created_at", "updated_at", "lockup_tx_hex", "completed_at_unix", "paid_at_unix") SELECT "swap_operation_id", "app_user_id", "swap_quote_id", "swap_tree", "claim_public_key", "payment_hash", "timeout_block_height", "invoice", "invoice_amount", "transaction_amount", "swap_fee_sats", "chain_fee_sats", "ephemeral_public_key", "address", "ephemeral_private_key", "used", "preimage", "failure_reason", "tx_id", "service_url", "created_at", "updated_at", "lockup_tx_hex", "completed_at_unix", "paid_at_unix" FROM "invoice_swap"`); + await queryRunner.query(`DROP TABLE "invoice_swap"`); + await queryRunner.query(`ALTER TABLE "temporary_invoice_swap" RENAME TO "invoice_swap"`); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE "invoice_swap" RENAME TO "temporary_invoice_swap"`); + await queryRunner.query(`CREATE TABLE "invoice_swap" ("swap_operation_id" varchar PRIMARY KEY NOT NULL, "app_user_id" varchar NOT NULL, "swap_quote_id" varchar NOT NULL, "swap_tree" varchar NOT NULL, "claim_public_key" varchar NOT NULL, "payment_hash" varchar NOT NULL, "timeout_block_height" integer NOT NULL, "invoice" varchar NOT NULL, "invoice_amount" integer NOT NULL, "transaction_amount" integer NOT NULL, "swap_fee_sats" integer NOT NULL, "chain_fee_sats" integer NOT NULL, "ephemeral_public_key" varchar NOT NULL, "address" varchar NOT NULL, "ephemeral_private_key" varchar NOT NULL, "used" boolean NOT NULL DEFAULT (0), "preimage" varchar NOT NULL DEFAULT (''), "failure_reason" varchar NOT NULL DEFAULT (''), "tx_id" varchar NOT NULL DEFAULT (''), "service_url" varchar NOT NULL DEFAULT (''), "created_at" datetime NOT NULL DEFAULT (datetime('now')), "updated_at" datetime NOT NULL DEFAULT (datetime('now')), "lockup_tx_hex" text NOT NULL DEFAULT (''), "completed_at_unix" integer NOT NULL DEFAULT (0), "paid_at_unix" integer NOT NULL DEFAULT (0))`); + await queryRunner.query(`INSERT INTO "invoice_swap"("swap_operation_id", "app_user_id", "swap_quote_id", "swap_tree", "claim_public_key", "payment_hash", "timeout_block_height", "invoice", "invoice_amount", "transaction_amount", "swap_fee_sats", "chain_fee_sats", "ephemeral_public_key", "address", "ephemeral_private_key", "used", "preimage", "failure_reason", "tx_id", "service_url", "created_at", "updated_at", "lockup_tx_hex", "completed_at_unix", "paid_at_unix") SELECT "swap_operation_id", "app_user_id", "swap_quote_id", "swap_tree", "claim_public_key", "payment_hash", "timeout_block_height", "invoice", "invoice_amount", "transaction_amount", "swap_fee_sats", "chain_fee_sats", "ephemeral_public_key", "address", "ephemeral_private_key", "used", "preimage", "failure_reason", "tx_id", "service_url", "created_at", "updated_at", "lockup_tx_hex", "completed_at_unix", "paid_at_unix" FROM "temporary_invoice_swap"`); + await queryRunner.query(`DROP TABLE "temporary_invoice_swap"`); + } + +} diff --git a/src/services/storage/migrations/runner.ts b/src/services/storage/migrations/runner.ts index c78af2eb..c2150831 100644 --- a/src/services/storage/migrations/runner.ts +++ b/src/services/storage/migrations/runner.ts @@ -30,6 +30,7 @@ import { InvoiceSwapsFixes1769805357459 } from './1769805357459-invoice_swaps_fi import { ApplicationUserTopicId1770038768784 } from './1770038768784-application_user_topic_id.js' import { SwapTimestamps1771347307798 } from './1771347307798-swap_timestamps.js' import { TxSwapTimestamps1771878683383 } from './1771878683383-tx_swap_timestamps.js' +import { RefundSwapInfo1773082318982 } from './1773082318982-refund_swap_info.js' import { LndMetrics1703170330183 } from './1703170330183-lnd_metrics.js' import { ChannelRouting1709316653538 } from './1709316653538-channel_routing.js' @@ -51,7 +52,7 @@ export const allMigrations = [Initial1703170309875, LspOrder1718387847693, Liqui UserAccess1759426050669, AddBlindToUserOffer1760000000000, ApplicationAvatarUrl1761000001000, AdminSettings1761683639419, TxSwap1762890527098, TxSwapAddress1764779178945, ClinkRequester1765497600000, TrackedProviderHeight1766504040000, SwapsServiceUrl1768413055036, InvoiceSwaps1769529793283, InvoiceSwapsFixes1769805357459, ApplicationUserTopicId1770038768784, SwapTimestamps1771347307798, - TxSwapTimestamps1771878683383] + TxSwapTimestamps1771878683383, RefundSwapInfo1773082318982] export const allMetricsMigrations = [LndMetrics1703170330183, ChannelRouting1709316653538, HtlcCount1724266887195, BalanceEvents1724860966825, diff --git a/src/services/storage/paymentStorage.ts b/src/services/storage/paymentStorage.ts index af96b6c5..af2de96a 100644 --- a/src/services/storage/paymentStorage.ts +++ b/src/services/storage/paymentStorage.ts @@ -655,6 +655,15 @@ export default class { return swaps.filter(s => !!s.tx_id) } + async UpdateRefundInvoiceSwap(swapOperationId: string, refundAddress: string, refundTxId: string, txId?: string) { + const now = Math.floor(Date.now() / 1000) + return this.dbs.Update('InvoiceSwap', { swap_operation_id: swapOperationId }, { + refund_address: refundAddress, + refund_at_unix: now, + refund_tx_id: refundTxId, + }, txId) + } + async GetRefundableInvoiceSwap(swapOperationId: string, txId?: string) { const swap = await this.dbs.FindOne('InvoiceSwap', { where: { swap_operation_id: swapOperationId } }, txId) if (!swap || !swap.tx_id) { From 8de5e4fd3a707c113633a66326cd96da81894674 Mon Sep 17 00:00:00 2001 From: Patrick Mulligan Date: Fri, 13 Feb 2026 13:38:13 -0500 Subject: [PATCH 54/66] feat(extensions): add LNURL-withdraw extension Implements LUD-03 (LNURL-withdraw) for creating withdraw links that allow anyone to pull funds from a Lightning wallet. Features: - Create withdraw links with min/max amounts - Quick vouchers: batch creation of single-use codes - Multi-use links with wait time between uses - Unique QR codes per use (prevents sharing exploits) - Webhook notifications on successful withdrawals - Full LNURL protocol compliance for wallet compatibility Use cases: - Faucets - Gift cards / prepaid cards - Tips / donations - User onboarding Co-Authored-By: Claude Opus 4.5 --- src/extensions/withdraw/index.ts | 304 ++++++++ .../withdraw/managers/withdrawManager.ts | 711 ++++++++++++++++++ src/extensions/withdraw/migrations.ts | 153 ++++ src/extensions/withdraw/types.ts | 261 +++++++ src/extensions/withdraw/utils/lnurl.ts | 131 ++++ 5 files changed, 1560 insertions(+) create mode 100644 src/extensions/withdraw/index.ts create mode 100644 src/extensions/withdraw/managers/withdrawManager.ts create mode 100644 src/extensions/withdraw/migrations.ts create mode 100644 src/extensions/withdraw/types.ts create mode 100644 src/extensions/withdraw/utils/lnurl.ts diff --git a/src/extensions/withdraw/index.ts b/src/extensions/withdraw/index.ts new file mode 100644 index 00000000..0b8259d6 --- /dev/null +++ b/src/extensions/withdraw/index.ts @@ -0,0 +1,304 @@ +/** + * LNURL-withdraw Extension for Lightning.Pub + * + * Implements LUD-03 (LNURL-withdraw) for creating withdraw links + * that allow anyone to pull funds from a Lightning wallet. + * + * Use cases: + * - Quick vouchers (batch single-use codes) + * - Faucets + * - Gift cards / prepaid cards + * - Tips / donations + */ + +import { + Extension, + ExtensionInfo, + ExtensionContext, + ExtensionDatabase, + CreateWithdrawLinkRequest, + UpdateWithdrawLinkRequest, + HttpRoute, + HttpRequest, + HttpResponse +} from './types.js' +import { runMigrations } from './migrations.js' +import { WithdrawManager } from './managers/withdrawManager.js' + +/** + * LNURL-withdraw Extension + */ +export default class WithdrawExtension implements Extension { + readonly info: ExtensionInfo = { + id: 'withdraw', + name: 'LNURL Withdraw', + version: '1.0.0', + description: 'Create withdraw links for vouchers, faucets, and gifts (LUD-03)', + author: 'Lightning.Pub', + minPubVersion: '1.0.0' + } + + private manager!: WithdrawManager + private baseUrl: string = '' + + /** + * Initialize the extension + */ + async initialize(ctx: ExtensionContext, db: ExtensionDatabase): Promise { + // Run migrations + await runMigrations(db) + + // Initialize manager + this.manager = new WithdrawManager(db, ctx) + + // Register RPC methods + this.registerRpcMethods(ctx) + + // Register HTTP routes for LNURL protocol + this.registerHttpRoutes(ctx) + + ctx.log('info', 'Extension initialized') + } + + /** + * Shutdown the extension + */ + async shutdown(): Promise { + // Cleanup if needed + } + + /** + * Set the base URL for LNURL generation + * This should be called by the main application after loading + */ + setBaseUrl(url: string): void { + this.baseUrl = url + this.manager.setBaseUrl(url) + } + + /** + * Get HTTP routes for this extension + * These need to be mounted by the main HTTP server + */ + getHttpRoutes(): HttpRoute[] { + return [ + // Initial LNURL request (simple link) + { + method: 'GET', + path: '/api/v1/lnurl/:unique_hash', + handler: this.handleLnurlRequest.bind(this) + }, + // Initial LNURL request (unique link with use hash) + { + method: 'GET', + path: '/api/v1/lnurl/:unique_hash/:id_unique_hash', + handler: this.handleLnurlUniqueRequest.bind(this) + }, + // LNURL callback (user submits invoice) + { + method: 'GET', + path: '/api/v1/lnurl/cb/:unique_hash', + handler: this.handleLnurlCallback.bind(this) + } + ] + } + + /** + * Register RPC methods with the extension context + */ + private registerRpcMethods(ctx: ExtensionContext): void { + // Create withdraw link + ctx.registerMethod('withdraw.createLink', async (req, appId) => { + const link = await this.manager.create(appId, req as CreateWithdrawLinkRequest) + const stats = await this.manager.getWithdrawalStats(link.id) + return { + link, + total_withdrawn_sats: stats.total_sats, + withdrawals_count: stats.count + } + }) + + // Create quick vouchers + ctx.registerMethod('withdraw.createVouchers', async (req, appId) => { + const vouchers = await this.manager.createVouchers( + appId, + req.title, + req.amount, + req.count, + req.description + ) + return { + vouchers, + total_amount_sats: req.amount * req.count + } + }) + + // Get withdraw link + ctx.registerMethod('withdraw.getLink', async (req, appId) => { + const link = await this.manager.get(req.id, appId) + if (!link) throw new Error('Withdraw link not found') + const stats = await this.manager.getWithdrawalStats(link.id) + return { + link, + total_withdrawn_sats: stats.total_sats, + withdrawals_count: stats.count + } + }) + + // List withdraw links + ctx.registerMethod('withdraw.listLinks', async (req, appId) => { + const links = await this.manager.list( + appId, + req.include_spent || false, + req.limit, + req.offset + ) + return { links } + }) + + // Update withdraw link + ctx.registerMethod('withdraw.updateLink', async (req, appId) => { + const link = await this.manager.update(req.id, appId, req as UpdateWithdrawLinkRequest) + if (!link) throw new Error('Withdraw link not found') + const stats = await this.manager.getWithdrawalStats(link.id) + return { + link, + total_withdrawn_sats: stats.total_sats, + withdrawals_count: stats.count + } + }) + + // Delete withdraw link + ctx.registerMethod('withdraw.deleteLink', async (req, appId) => { + const success = await this.manager.delete(req.id, appId) + if (!success) throw new Error('Withdraw link not found') + return { success } + }) + + // List withdrawals + ctx.registerMethod('withdraw.listWithdrawals', async (req, appId) => { + const withdrawals = await this.manager.listWithdrawals( + appId, + req.link_id, + req.limit, + req.offset + ) + return { withdrawals } + }) + + // Get withdrawal stats + ctx.registerMethod('withdraw.getStats', async (req, appId) => { + // Get all links to calculate total stats + const links = await this.manager.list(appId, true) + + let totalLinks = links.length + let activeLinks = 0 + let spentLinks = 0 + let totalWithdrawn = 0 + let totalWithdrawals = 0 + + for (const link of links) { + if (link.used >= link.uses) { + spentLinks++ + } else { + activeLinks++ + } + const stats = await this.manager.getWithdrawalStats(link.id) + totalWithdrawn += stats.total_sats + totalWithdrawals += stats.count + } + + return { + total_links: totalLinks, + active_links: activeLinks, + spent_links: spentLinks, + total_withdrawn_sats: totalWithdrawn, + total_withdrawals: totalWithdrawals + } + }) + } + + /** + * Register HTTP routes (called by extension context) + */ + private registerHttpRoutes(ctx: ExtensionContext): void { + // HTTP routes are exposed via getHttpRoutes() + // The main application is responsible for mounting them + ctx.log('debug', 'HTTP routes registered for LNURL protocol') + } + + // ========================================================================= + // HTTP Route Handlers + // ========================================================================= + + /** + * Handle initial LNURL request (simple link) + * GET /api/v1/lnurl/:unique_hash + */ + private async handleLnurlRequest(req: HttpRequest): Promise { + const { unique_hash } = req.params + + const result = await this.manager.handleLnurlRequest(unique_hash) + + return { + status: 200, + body: result, + headers: { + 'Content-Type': 'application/json' + } + } + } + + /** + * Handle initial LNURL request (unique link) + * GET /api/v1/lnurl/:unique_hash/:id_unique_hash + */ + private async handleLnurlUniqueRequest(req: HttpRequest): Promise { + const { unique_hash, id_unique_hash } = req.params + + const result = await this.manager.handleLnurlRequest(unique_hash, id_unique_hash) + + return { + status: 200, + body: result, + headers: { + 'Content-Type': 'application/json' + } + } + } + + /** + * Handle LNURL callback (user submits invoice) + * GET /api/v1/lnurl/cb/:unique_hash?k1=...&pr=...&id_unique_hash=... + */ + private async handleLnurlCallback(req: HttpRequest): Promise { + const { unique_hash } = req.params + const { k1, pr, id_unique_hash } = req.query + + if (!k1 || !pr) { + return { + status: 200, + body: { status: 'ERROR', reason: 'Missing k1 or pr parameter' }, + headers: { 'Content-Type': 'application/json' } + } + } + + const result = await this.manager.handleLnurlCallback(unique_hash, { + k1, + pr, + id_unique_hash + }) + + return { + status: 200, + body: result, + headers: { + 'Content-Type': 'application/json' + } + } + } +} + +// Export types for external use +export * from './types.js' +export { WithdrawManager } from './managers/withdrawManager.js' diff --git a/src/extensions/withdraw/managers/withdrawManager.ts b/src/extensions/withdraw/managers/withdrawManager.ts new file mode 100644 index 00000000..91677f82 --- /dev/null +++ b/src/extensions/withdraw/managers/withdrawManager.ts @@ -0,0 +1,711 @@ +/** + * Withdraw Link Manager + * + * Handles CRUD operations for withdraw links and processes withdrawals + */ + +import { + ExtensionContext, + ExtensionDatabase, + WithdrawLink, + Withdrawal, + CreateWithdrawLinkRequest, + UpdateWithdrawLinkRequest, + WithdrawLinkWithLnurl, + LnurlWithdrawResponse, + LnurlErrorResponse, + LnurlSuccessResponse, + LnurlCallbackParams +} from '../types.js' +import { + generateId, + generateK1, + generateUniqueHash, + generateUseHash, + verifyUseHash, + encodeLnurl, + buildLnurlUrl, + buildUniqueLnurlUrl, + buildCallbackUrl, + satsToMsats +} from '../utils/lnurl.js' + +/** + * Database row types + */ +interface WithdrawLinkRow { + id: string + application_id: string + title: string + description: string | null + min_withdrawable: number + max_withdrawable: number + uses: number + used: number + wait_time: number + unique_hash: string + k1: string + is_unique: number + uses_csv: string + open_time: number + webhook_url: string | null + webhook_headers: string | null + webhook_body: string | null + created_at: number + updated_at: number +} + +interface WithdrawalRow { + id: string + link_id: string + application_id: string + payment_hash: string + amount_sats: number + fee_sats: number + recipient_node: string | null + webhook_success: number | null + webhook_response: string | null + created_at: number +} + +/** + * Convert row to WithdrawLink + */ +function rowToLink(row: WithdrawLinkRow): WithdrawLink { + return { + id: row.id, + application_id: row.application_id, + title: row.title, + description: row.description || undefined, + min_withdrawable: row.min_withdrawable, + max_withdrawable: row.max_withdrawable, + uses: row.uses, + used: row.used, + wait_time: row.wait_time, + unique_hash: row.unique_hash, + k1: row.k1, + is_unique: row.is_unique === 1, + uses_csv: row.uses_csv, + open_time: row.open_time, + webhook_url: row.webhook_url || undefined, + webhook_headers: row.webhook_headers || undefined, + webhook_body: row.webhook_body || undefined, + created_at: row.created_at, + updated_at: row.updated_at + } +} + +/** + * Convert row to Withdrawal + */ +function rowToWithdrawal(row: WithdrawalRow): Withdrawal { + return { + id: row.id, + link_id: row.link_id, + application_id: row.application_id, + payment_hash: row.payment_hash, + amount_sats: row.amount_sats, + fee_sats: row.fee_sats, + recipient_node: row.recipient_node || undefined, + webhook_success: row.webhook_success === null ? undefined : row.webhook_success === 1, + webhook_response: row.webhook_response || undefined, + created_at: row.created_at + } +} + +/** + * WithdrawManager - Handles withdraw link operations + */ +export class WithdrawManager { + private baseUrl: string = '' + + constructor( + private db: ExtensionDatabase, + private ctx: ExtensionContext + ) {} + + /** + * Set the base URL for LNURL generation + */ + setBaseUrl(url: string): void { + this.baseUrl = url.replace(/\/$/, '') + } + + /** + * Add LNURL to a withdraw link + */ + private addLnurl(link: WithdrawLink): WithdrawLinkWithLnurl { + const lnurlUrl = buildLnurlUrl(this.baseUrl, link.unique_hash) + return { + ...link, + lnurl: encodeLnurl(lnurlUrl), + lnurl_url: lnurlUrl + } + } + + // ========================================================================= + // CRUD Operations + // ========================================================================= + + /** + * Create a new withdraw link + */ + async create(applicationId: string, req: CreateWithdrawLinkRequest): Promise { + // Validation + if (req.uses < 1 || req.uses > 250) { + throw new Error('Uses must be between 1 and 250') + } + if (req.min_withdrawable < 1) { + throw new Error('Min withdrawable must be at least 1 sat') + } + if (req.max_withdrawable < req.min_withdrawable) { + throw new Error('Max withdrawable must be >= min withdrawable') + } + if (req.wait_time < 0) { + throw new Error('Wait time cannot be negative') + } + + // Validate webhook JSON if provided + if (req.webhook_headers) { + try { + JSON.parse(req.webhook_headers) + } catch { + throw new Error('webhook_headers must be valid JSON') + } + } + if (req.webhook_body) { + try { + JSON.parse(req.webhook_body) + } catch { + throw new Error('webhook_body must be valid JSON') + } + } + + const now = Math.floor(Date.now() / 1000) + const id = generateId() + const usesCsv = Array.from({ length: req.uses }, (_, i) => String(i)).join(',') + + const link: WithdrawLink = { + id, + application_id: applicationId, + title: req.title.trim(), + description: req.description?.trim(), + min_withdrawable: req.min_withdrawable, + max_withdrawable: req.max_withdrawable, + uses: req.uses, + used: 0, + wait_time: req.wait_time, + unique_hash: generateUniqueHash(), + k1: generateK1(), + is_unique: req.is_unique || false, + uses_csv: usesCsv, + open_time: now, + webhook_url: req.webhook_url, + webhook_headers: req.webhook_headers, + webhook_body: req.webhook_body, + created_at: now, + updated_at: now + } + + await this.db.execute( + `INSERT INTO withdraw_links ( + id, application_id, title, description, + min_withdrawable, max_withdrawable, uses, used, wait_time, + unique_hash, k1, is_unique, uses_csv, open_time, + webhook_url, webhook_headers, webhook_body, + created_at, updated_at + ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, + [ + link.id, link.application_id, link.title, link.description || null, + link.min_withdrawable, link.max_withdrawable, link.uses, link.used, link.wait_time, + link.unique_hash, link.k1, link.is_unique ? 1 : 0, link.uses_csv, link.open_time, + link.webhook_url || null, link.webhook_headers || null, link.webhook_body || null, + link.created_at, link.updated_at + ] + ) + + return this.addLnurl(link) + } + + /** + * Create multiple vouchers (single-use withdraw links) + */ + async createVouchers( + applicationId: string, + title: string, + amount: number, + count: number, + description?: string + ): Promise { + if (count < 1 || count > 100) { + throw new Error('Count must be between 1 and 100') + } + if (amount < 1) { + throw new Error('Amount must be at least 1 sat') + } + + const vouchers: WithdrawLinkWithLnurl[] = [] + + for (let i = 0; i < count; i++) { + const voucher = await this.create(applicationId, { + title: `${title} #${i + 1}`, + description, + min_withdrawable: amount, + max_withdrawable: amount, + uses: 1, + wait_time: 0, + is_unique: false + }) + vouchers.push(voucher) + } + + return vouchers + } + + /** + * Get a withdraw link by ID + */ + async get(id: string, applicationId: string): Promise { + const rows = await this.db.query( + 'SELECT * FROM withdraw_links WHERE id = ? AND application_id = ?', + [id, applicationId] + ) + + if (rows.length === 0) return null + return this.addLnurl(rowToLink(rows[0])) + } + + /** + * Get a withdraw link by unique hash (for LNURL) + */ + async getByHash(uniqueHash: string): Promise { + const rows = await this.db.query( + 'SELECT * FROM withdraw_links WHERE unique_hash = ?', + [uniqueHash] + ) + + if (rows.length === 0) return null + return rowToLink(rows[0]) + } + + /** + * List withdraw links for an application + */ + async list( + applicationId: string, + includeSpent: boolean = false, + limit?: number, + offset?: number + ): Promise { + let sql = 'SELECT * FROM withdraw_links WHERE application_id = ?' + const params: any[] = [applicationId] + + if (!includeSpent) { + sql += ' AND used < uses' + } + + sql += ' ORDER BY created_at DESC' + + if (limit) { + sql += ' LIMIT ?' + params.push(limit) + if (offset) { + sql += ' OFFSET ?' + params.push(offset) + } + } + + const rows = await this.db.query(sql, params) + return rows.map(row => this.addLnurl(rowToLink(row))) + } + + /** + * Update a withdraw link + */ + async update( + id: string, + applicationId: string, + req: UpdateWithdrawLinkRequest + ): Promise { + const existing = await this.get(id, applicationId) + if (!existing) return null + + // Validation + if (req.uses !== undefined) { + if (req.uses < 1 || req.uses > 250) { + throw new Error('Uses must be between 1 and 250') + } + if (req.uses < existing.used) { + throw new Error('Cannot reduce uses below current used count') + } + } + + const minWith = req.min_withdrawable ?? existing.min_withdrawable + const maxWith = req.max_withdrawable ?? existing.max_withdrawable + + if (minWith < 1) { + throw new Error('Min withdrawable must be at least 1 sat') + } + if (maxWith < minWith) { + throw new Error('Max withdrawable must be >= min withdrawable') + } + + // Handle uses change + let usesCsv = existing.uses_csv + const newUses = req.uses ?? existing.uses + if (newUses !== existing.uses) { + const currentUses = usesCsv.split(',').filter(u => u !== '') + if (newUses > existing.uses) { + // Add more uses + const lastNum = currentUses.length > 0 ? parseInt(currentUses[currentUses.length - 1], 10) : -1 + for (let i = lastNum + 1; currentUses.length < (newUses - existing.used); i++) { + currentUses.push(String(i)) + } + } else { + // Remove uses (keep first N) + usesCsv = currentUses.slice(0, newUses - existing.used).join(',') + } + usesCsv = currentUses.join(',') + } + + const now = Math.floor(Date.now() / 1000) + + await this.db.execute( + `UPDATE withdraw_links SET + title = ?, description = ?, + min_withdrawable = ?, max_withdrawable = ?, + uses = ?, wait_time = ?, is_unique = ?, uses_csv = ?, + webhook_url = ?, webhook_headers = ?, webhook_body = ?, + updated_at = ? + WHERE id = ? AND application_id = ?`, + [ + req.title ?? existing.title, + req.description ?? existing.description ?? null, + minWith, maxWith, + newUses, + req.wait_time ?? existing.wait_time, + (req.is_unique ?? existing.is_unique) ? 1 : 0, + usesCsv, + req.webhook_url ?? existing.webhook_url ?? null, + req.webhook_headers ?? existing.webhook_headers ?? null, + req.webhook_body ?? existing.webhook_body ?? null, + now, + id, applicationId + ] + ) + + return this.get(id, applicationId) + } + + /** + * Delete a withdraw link + */ + async delete(id: string, applicationId: string): Promise { + const result = await this.db.execute( + 'DELETE FROM withdraw_links WHERE id = ? AND application_id = ?', + [id, applicationId] + ) + return (result.changes || 0) > 0 + } + + // ========================================================================= + // LNURL Protocol Handlers + // ========================================================================= + + /** + * Handle initial LNURL request (user scans QR) + * Returns withdraw parameters + */ + async handleLnurlRequest( + uniqueHash: string, + idUniqueHash?: string + ): Promise { + const link = await this.getByHash(uniqueHash) + + if (!link) { + return { status: 'ERROR', reason: 'Withdraw link does not exist.' } + } + + if (link.used >= link.uses) { + return { status: 'ERROR', reason: 'Withdraw link is spent.' } + } + + // For unique links, require id_unique_hash + if (link.is_unique && !idUniqueHash) { + return { status: 'ERROR', reason: 'This link requires a unique hash.' } + } + + // Verify unique hash if provided + if (idUniqueHash) { + const useNumber = verifyUseHash(link.id, link.unique_hash, link.uses_csv, idUniqueHash) + if (!useNumber) { + return { status: 'ERROR', reason: 'Invalid unique hash.' } + } + } + + const callbackUrl = buildCallbackUrl(this.baseUrl, link.unique_hash) + + return { + tag: 'withdrawRequest', + callback: idUniqueHash ? `${callbackUrl}?id_unique_hash=${idUniqueHash}` : callbackUrl, + k1: link.k1, + minWithdrawable: satsToMsats(link.min_withdrawable), + maxWithdrawable: satsToMsats(link.max_withdrawable), + defaultDescription: link.title + } + } + + /** + * Handle LNURL callback (user submits invoice) + * Pays the invoice and records the withdrawal + */ + async handleLnurlCallback( + uniqueHash: string, + params: LnurlCallbackParams + ): Promise { + const link = await this.getByHash(uniqueHash) + + if (!link) { + return { status: 'ERROR', reason: 'Withdraw link not found.' } + } + + if (link.used >= link.uses) { + return { status: 'ERROR', reason: 'Withdraw link is spent.' } + } + + if (link.k1 !== params.k1) { + return { status: 'ERROR', reason: 'Invalid k1.' } + } + + // Check wait time + const now = Math.floor(Date.now() / 1000) + if (now < link.open_time) { + const waitSecs = link.open_time - now + return { status: 'ERROR', reason: `Please wait ${waitSecs} seconds.` } + } + + // For unique links, verify and consume the use hash + if (params.id_unique_hash) { + const useNumber = verifyUseHash(link.id, link.unique_hash, link.uses_csv, params.id_unique_hash) + if (!useNumber) { + return { status: 'ERROR', reason: 'Invalid unique hash.' } + } + } else if (link.is_unique) { + return { status: 'ERROR', reason: 'Unique hash required.' } + } + + // Prevent double-spending with hash check + try { + await this.createHashCheck(params.id_unique_hash || uniqueHash, params.k1) + } catch { + return { status: 'ERROR', reason: 'Withdrawal already in progress.' } + } + + try { + // Pay the invoice + const payment = await this.ctx.payInvoice( + link.application_id, + params.pr, + link.max_withdrawable + ) + + // Record the withdrawal + await this.recordWithdrawal(link, payment.paymentHash, link.max_withdrawable, payment.feeSats) + + // Increment usage + await this.incrementUsage(link, params.id_unique_hash) + + // Clean up hash check + await this.deleteHashCheck(params.id_unique_hash || uniqueHash) + + // Dispatch webhook if configured + if (link.webhook_url) { + this.dispatchWebhook(link, payment.paymentHash, params.pr).catch(err => { + console.error('[Withdraw] Webhook error:', err) + }) + } + + return { status: 'OK' } + } catch (err: any) { + // Clean up hash check on failure + await this.deleteHashCheck(params.id_unique_hash || uniqueHash) + return { status: 'ERROR', reason: `Payment failed: ${err.message}` } + } + } + + // ========================================================================= + // Helper Methods + // ========================================================================= + + /** + * Increment link usage and update open_time + */ + private async incrementUsage(link: WithdrawLink, idUniqueHash?: string): Promise { + const now = Math.floor(Date.now() / 1000) + let usesCsv = link.uses_csv + + // Remove used hash from uses_csv if unique + if (idUniqueHash) { + const uses = usesCsv.split(',').filter(u => { + const hash = generateUseHash(link.id, link.unique_hash, u.trim()) + return hash !== idUniqueHash + }) + usesCsv = uses.join(',') + } + + await this.db.execute( + `UPDATE withdraw_links SET + used = used + 1, + open_time = ?, + uses_csv = ?, + updated_at = ? + WHERE id = ?`, + [now + link.wait_time, usesCsv, now, link.id] + ) + } + + /** + * Record a successful withdrawal + */ + private async recordWithdrawal( + link: WithdrawLink, + paymentHash: string, + amountSats: number, + feeSats: number + ): Promise { + const now = Math.floor(Date.now() / 1000) + + await this.db.execute( + `INSERT INTO withdrawals ( + id, link_id, application_id, + payment_hash, amount_sats, fee_sats, + created_at + ) VALUES (?, ?, ?, ?, ?, ?, ?)`, + [ + generateId(), + link.id, + link.application_id, + paymentHash, + amountSats, + feeSats, + now + ] + ) + } + + /** + * Create hash check to prevent double-spending + */ + private async createHashCheck(hash: string, k1: string): Promise { + const now = Math.floor(Date.now() / 1000) + await this.db.execute( + 'INSERT INTO hash_checks (hash, k1, created_at) VALUES (?, ?, ?)', + [hash, k1, now] + ) + } + + /** + * Delete hash check after completion + */ + private async deleteHashCheck(hash: string): Promise { + await this.db.execute('DELETE FROM hash_checks WHERE hash = ?', [hash]) + } + + /** + * List withdrawals + */ + async listWithdrawals( + applicationId: string, + linkId?: string, + limit?: number, + offset?: number + ): Promise { + let sql = 'SELECT * FROM withdrawals WHERE application_id = ?' + const params: any[] = [applicationId] + + if (linkId) { + sql += ' AND link_id = ?' + params.push(linkId) + } + + sql += ' ORDER BY created_at DESC' + + if (limit) { + sql += ' LIMIT ?' + params.push(limit) + if (offset) { + sql += ' OFFSET ?' + params.push(offset) + } + } + + const rows = await this.db.query(sql, params) + return rows.map(rowToWithdrawal) + } + + /** + * Get withdrawal stats for a link + */ + async getWithdrawalStats(linkId: string): Promise<{ total_sats: number; count: number }> { + const result = await this.db.query<{ total: number; count: number }>( + `SELECT COALESCE(SUM(amount_sats), 0) as total, COUNT(*) as count + FROM withdrawals WHERE link_id = ?`, + [linkId] + ) + return { + total_sats: result[0]?.total || 0, + count: result[0]?.count || 0 + } + } + + /** + * Dispatch webhook notification + */ + private async dispatchWebhook( + link: WithdrawLink, + paymentHash: string, + paymentRequest: string + ): Promise { + if (!link.webhook_url) return + + try { + const headers: Record = { + 'Content-Type': 'application/json' + } + + if (link.webhook_headers) { + Object.assign(headers, JSON.parse(link.webhook_headers)) + } + + const body = { + payment_hash: paymentHash, + payment_request: paymentRequest, + lnurlw: link.id, + body: link.webhook_body ? JSON.parse(link.webhook_body) : {} + } + + const response = await fetch(link.webhook_url, { + method: 'POST', + headers, + body: JSON.stringify(body) + }) + + // Update withdrawal record with webhook result + await this.db.execute( + `UPDATE withdrawals SET + webhook_success = ?, + webhook_response = ? + WHERE payment_hash = ?`, + [response.ok ? 1 : 0, await response.text(), paymentHash] + ) + } catch (err: any) { + await this.db.execute( + `UPDATE withdrawals SET + webhook_success = 0, + webhook_response = ? + WHERE payment_hash = ?`, + [err.message, paymentHash] + ) + } + } +} diff --git a/src/extensions/withdraw/migrations.ts b/src/extensions/withdraw/migrations.ts new file mode 100644 index 00000000..86886885 --- /dev/null +++ b/src/extensions/withdraw/migrations.ts @@ -0,0 +1,153 @@ +/** + * LNURL-withdraw Extension Database Migrations + */ + +import { ExtensionDatabase } from '../types.js' + +export interface Migration { + version: number + name: string + up: (db: ExtensionDatabase) => Promise + down?: (db: ExtensionDatabase) => Promise +} + +export const migrations: Migration[] = [ + { + version: 1, + name: 'create_withdraw_links_table', + up: async (db: ExtensionDatabase) => { + await db.execute(` + CREATE TABLE IF NOT EXISTS withdraw_links ( + id TEXT PRIMARY KEY, + application_id TEXT NOT NULL, + + -- Display + title TEXT NOT NULL, + description TEXT, + + -- Amounts (sats) + min_withdrawable INTEGER NOT NULL, + max_withdrawable INTEGER NOT NULL, + + -- Usage limits + uses INTEGER NOT NULL DEFAULT 1, + used INTEGER NOT NULL DEFAULT 0, + wait_time INTEGER NOT NULL DEFAULT 0, + + -- Security + unique_hash TEXT NOT NULL UNIQUE, + k1 TEXT NOT NULL, + is_unique INTEGER NOT NULL DEFAULT 0, + uses_csv TEXT NOT NULL DEFAULT '', + + -- Rate limiting + open_time INTEGER NOT NULL DEFAULT 0, + + -- Webhooks + webhook_url TEXT, + webhook_headers TEXT, + webhook_body TEXT, + + -- Timestamps + created_at INTEGER NOT NULL, + updated_at INTEGER NOT NULL + ) + `) + + // Index for looking up by unique_hash (LNURL) + await db.execute(` + CREATE INDEX IF NOT EXISTS idx_withdraw_links_unique_hash + ON withdraw_links(unique_hash) + `) + + // Index for listing by application + await db.execute(` + CREATE INDEX IF NOT EXISTS idx_withdraw_links_application + ON withdraw_links(application_id, created_at DESC) + `) + } + }, + { + version: 2, + name: 'create_withdrawals_table', + up: async (db: ExtensionDatabase) => { + await db.execute(` + CREATE TABLE IF NOT EXISTS withdrawals ( + id TEXT PRIMARY KEY, + link_id TEXT NOT NULL, + application_id TEXT NOT NULL, + + -- Payment details + payment_hash TEXT NOT NULL, + amount_sats INTEGER NOT NULL, + fee_sats INTEGER NOT NULL DEFAULT 0, + + -- Recipient + recipient_node TEXT, + + -- Webhook result + webhook_success INTEGER, + webhook_response TEXT, + + -- Timestamp + created_at INTEGER NOT NULL, + + FOREIGN KEY (link_id) REFERENCES withdraw_links(id) ON DELETE CASCADE + ) + `) + + // Index for listing withdrawals by link + await db.execute(` + CREATE INDEX IF NOT EXISTS idx_withdrawals_link + ON withdrawals(link_id, created_at DESC) + `) + + // Index for looking up by payment hash + await db.execute(` + CREATE INDEX IF NOT EXISTS idx_withdrawals_payment_hash + ON withdrawals(payment_hash) + `) + } + }, + { + version: 3, + name: 'create_hash_checks_table', + up: async (db: ExtensionDatabase) => { + // Temporary table to prevent double-spending during payment processing + await db.execute(` + CREATE TABLE IF NOT EXISTS hash_checks ( + hash TEXT PRIMARY KEY, + k1 TEXT NOT NULL, + created_at INTEGER NOT NULL + ) + `) + } + } +] + +/** + * Run all pending migrations + */ +export async function runMigrations(db: ExtensionDatabase): Promise { + // Get current version + const versionResult = await db.query<{ value: string }>( + `SELECT value FROM _extension_meta WHERE key = 'migration_version'` + ).catch(() => []) + + const currentVersion = versionResult.length > 0 ? parseInt(versionResult[0].value, 10) : 0 + + // Run pending migrations + for (const migration of migrations) { + if (migration.version > currentVersion) { + console.log(`[Withdraw] Running migration ${migration.version}: ${migration.name}`) + await migration.up(db) + + // Update version + await db.execute( + `INSERT INTO _extension_meta (key, value) VALUES ('migration_version', ?) + ON CONFLICT(key) DO UPDATE SET value = excluded.value`, + [String(migration.version)] + ) + } + } +} diff --git a/src/extensions/withdraw/types.ts b/src/extensions/withdraw/types.ts new file mode 100644 index 00000000..d9d05da0 --- /dev/null +++ b/src/extensions/withdraw/types.ts @@ -0,0 +1,261 @@ +/** + * LNURL-withdraw Extension Types + * Implements LUD-03 (LNURL-withdraw) for Lightning.Pub + */ + +// Re-export base extension types +export { + Extension, + ExtensionInfo, + ExtensionContext, + ExtensionDatabase, + ApplicationInfo, + RpcMethodHandler +} from '../types.js' + +// ============================================================================ +// Core Data Types +// ============================================================================ + +/** + * A withdraw link that can be used to pull funds + */ +export interface WithdrawLink { + id: string + application_id: string + + // Display + title: string + description?: string + + // Amounts (in sats) + min_withdrawable: number + max_withdrawable: number + + // Usage limits + uses: number // Total allowed uses + used: number // Times used so far + wait_time: number // Seconds between uses + + // Security + unique_hash: string // For LNURL URL + k1: string // Challenge for callback + is_unique: boolean // Generate unique code per use + uses_csv: string // Comma-separated list of available use IDs + + // Rate limiting + open_time: number // Unix timestamp when next use is allowed + + // Webhook notifications + webhook_url?: string + webhook_headers?: string // JSON string + webhook_body?: string // JSON string + + // Timestamps + created_at: number + updated_at: number +} + +/** + * Withdrawal record - tracks each successful withdrawal + */ +export interface Withdrawal { + id: string + link_id: string + application_id: string + + // Payment details + payment_hash: string + amount_sats: number + fee_sats: number + + // Recipient (if known) + recipient_node?: string + + // Webhook result + webhook_success?: boolean + webhook_response?: string + + // Timestamp + created_at: number +} + +/** + * Hash check - prevents double-spending during payment + */ +export interface HashCheck { + hash: string + k1: string + created_at: number +} + +// ============================================================================ +// LNURL Protocol Types (LUD-03) +// ============================================================================ + +/** + * LNURL-withdraw response (first call) + * Returned when user scans the QR code + */ +export interface LnurlWithdrawResponse { + tag: 'withdrawRequest' + callback: string // URL to call with invoice + k1: string // Challenge + minWithdrawable: number // Millisats + maxWithdrawable: number // Millisats + defaultDescription: string +} + +/** + * LNURL error response + */ +export interface LnurlErrorResponse { + status: 'ERROR' + reason: string +} + +/** + * LNURL success response + */ +export interface LnurlSuccessResponse { + status: 'OK' +} + +// ============================================================================ +// RPC Request/Response Types +// ============================================================================ + +/** + * Create a new withdraw link + */ +export interface CreateWithdrawLinkRequest { + title: string + description?: string + min_withdrawable: number // sats + max_withdrawable: number // sats + uses: number // 1-250 + wait_time: number // seconds between uses + is_unique?: boolean // generate unique code per use + webhook_url?: string + webhook_headers?: string // JSON + webhook_body?: string // JSON +} + +/** + * Update an existing withdraw link + */ +export interface UpdateWithdrawLinkRequest { + id: string + title?: string + description?: string + min_withdrawable?: number + max_withdrawable?: number + uses?: number + wait_time?: number + is_unique?: boolean + webhook_url?: string + webhook_headers?: string + webhook_body?: string +} + +/** + * Get withdraw link by ID + */ +export interface GetWithdrawLinkRequest { + id: string +} + +/** + * List withdraw links + */ +export interface ListWithdrawLinksRequest { + include_spent?: boolean // Include fully used links + limit?: number + offset?: number +} + +/** + * Delete withdraw link + */ +export interface DeleteWithdrawLinkRequest { + id: string +} + +/** + * Create quick vouchers (batch of single-use links) + */ +export interface CreateVouchersRequest { + title: string + amount: number // sats per voucher + count: number // number of vouchers (1-100) + description?: string +} + +/** + * Get withdraw link with LNURL + */ +export interface WithdrawLinkWithLnurl extends WithdrawLink { + lnurl: string // bech32 encoded LNURL + lnurl_url: string // raw callback URL +} + +/** + * List withdrawals for a link + */ +export interface ListWithdrawalsRequest { + link_id?: string + limit?: number + offset?: number +} + +/** + * Withdraw link response with stats + */ +export interface WithdrawLinkResponse { + link: WithdrawLinkWithLnurl + total_withdrawn_sats: number + withdrawals_count: number +} + +/** + * Vouchers response + */ +export interface VouchersResponse { + vouchers: WithdrawLinkWithLnurl[] + total_amount_sats: number +} + +// ============================================================================ +// HTTP Handler Types +// ============================================================================ + +/** + * LNURL callback parameters + */ +export interface LnurlCallbackParams { + k1: string // Challenge from initial response + pr: string // Payment request (BOLT11 invoice) + id_unique_hash?: string // For unique links +} + +/** + * HTTP route handler + */ +export interface HttpRoute { + method: 'GET' | 'POST' + path: string + handler: (req: HttpRequest) => Promise +} + +export interface HttpRequest { + params: Record + query: Record + body?: any + headers: Record +} + +export interface HttpResponse { + status: number + body: any + headers?: Record +} diff --git a/src/extensions/withdraw/utils/lnurl.ts b/src/extensions/withdraw/utils/lnurl.ts new file mode 100644 index 00000000..96926c52 --- /dev/null +++ b/src/extensions/withdraw/utils/lnurl.ts @@ -0,0 +1,131 @@ +/** + * LNURL Encoding Utilities + * + * LNURL is a bech32-encoded URL with hrp "lnurl" + * See: https://github.com/lnurl/luds + */ + +import { bech32 } from 'bech32' +import crypto from 'crypto' + +/** + * Encode a URL as LNURL (bech32) + */ +export function encodeLnurl(url: string): string { + const words = bech32.toWords(Buffer.from(url, 'utf8')) + return bech32.encode('lnurl', words, 2000) // 2000 char limit for URLs +} + +/** + * Decode an LNURL to a URL + */ +export function decodeLnurl(lnurl: string): string { + const { prefix, words } = bech32.decode(lnurl, 2000) + if (prefix !== 'lnurl') { + throw new Error('Invalid LNURL prefix') + } + return Buffer.from(bech32.fromWords(words)).toString('utf8') +} + +/** + * Generate a URL-safe random ID + */ +export function generateId(length: number = 22): string { + const bytes = crypto.randomBytes(Math.ceil(length * 3 / 4)) + return bytes.toString('base64url').slice(0, length) +} + +/** + * Generate a k1 challenge (32 bytes hex) + */ +export function generateK1(): string { + return crypto.randomBytes(32).toString('hex') +} + +/** + * Generate a unique hash for a link + */ +export function generateUniqueHash(): string { + return generateId(32) +} + +/** + * Generate a unique hash for a specific use of a link + * This creates a deterministic hash based on link ID, unique_hash, and use number + */ +export function generateUseHash(linkId: string, uniqueHash: string, useNumber: string): string { + const data = `${linkId}${uniqueHash}${useNumber}` + return crypto.createHash('sha256').update(data).digest('hex').slice(0, 32) +} + +/** + * Verify a use hash matches one of the available uses + */ +export function verifyUseHash( + linkId: string, + uniqueHash: string, + usesCsv: string, + providedHash: string +): string | null { + const uses = usesCsv.split(',').filter(u => u.trim() !== '') + + for (const useNumber of uses) { + const expectedHash = generateUseHash(linkId, uniqueHash, useNumber.trim()) + if (expectedHash === providedHash) { + return useNumber.trim() + } + } + + return null +} + +/** + * Build the LNURL callback URL for a withdraw link + */ +export function buildLnurlUrl(baseUrl: string, uniqueHash: string): string { + // Remove trailing slash from baseUrl + const base = baseUrl.replace(/\/$/, '') + return `${base}/api/v1/lnurl/${uniqueHash}` +} + +/** + * Build the LNURL callback URL for a unique withdraw link + */ +export function buildUniqueLnurlUrl( + baseUrl: string, + uniqueHash: string, + useHash: string +): string { + const base = baseUrl.replace(/\/$/, '') + return `${base}/api/v1/lnurl/${uniqueHash}/${useHash}` +} + +/** + * Build the callback URL for the second step (where user sends invoice) + */ +export function buildCallbackUrl(baseUrl: string, uniqueHash: string): string { + const base = baseUrl.replace(/\/$/, '') + return `${base}/api/v1/lnurl/cb/${uniqueHash}` +} + +/** + * Sats to millisats + */ +export function satsToMsats(sats: number): number { + return sats * 1000 +} + +/** + * Millisats to sats + */ +export function msatsToSats(msats: number): number { + return Math.floor(msats / 1000) +} + +/** + * Validate a BOLT11 invoice (basic check) + */ +export function isValidBolt11(invoice: string): boolean { + const lower = invoice.toLowerCase() + return lower.startsWith('lnbc') || lower.startsWith('lntb') || lower.startsWith('lnbcrt') +} From e998762ca713aee19eff82323c2a0cf23c826299 Mon Sep 17 00:00:00 2001 From: Patrick Mulligan Date: Sat, 14 Feb 2026 13:12:08 -0500 Subject: [PATCH 55/66] feat: integrate extension system with withdraw extension support - Add extension loader initialization to startup - Create mainHandlerAdapter to bridge mainHandler with extension context - Mount extension HTTP routes on separate port (main port + 1) - Configure EXTENSION_SERVICE_URL for LNURL link generation The withdraw extension provides LUD-03 LNURL-withdraw support for creating withdraw links that allow users to pull funds. Co-Authored-By: Claude Opus 4.5 --- src/extensions/mainHandlerAdapter.ts | 128 +++++++++++++++++++++++++++ src/index.ts | 94 +++++++++++++++++++- 2 files changed, 221 insertions(+), 1 deletion(-) create mode 100644 src/extensions/mainHandlerAdapter.ts diff --git a/src/extensions/mainHandlerAdapter.ts b/src/extensions/mainHandlerAdapter.ts new file mode 100644 index 00000000..eecc96b3 --- /dev/null +++ b/src/extensions/mainHandlerAdapter.ts @@ -0,0 +1,128 @@ +/** + * MainHandler Adapter for Extension System + * + * Wraps the Lightning.Pub mainHandler to provide the MainHandlerInterface + * required by the extension system. + */ + +import { MainHandlerInterface } from './context.js' +import { LnurlPayInfo } from './types.js' +import type Main from '../services/main/index.js' + +/** + * Create an adapter that wraps mainHandler for extension use + */ +export function createMainHandlerAdapter(mainHandler: Main): MainHandlerInterface { + return { + applicationManager: { + async getById(id: string) { + // The applicationManager stores apps internally + // We need to access it through the storage layer + try { + const app = await mainHandler.storage.applicationStorage.GetApplication(id) + if (!app) return null + + return { + id: app.app_id, + name: app.name, + nostr_public: app.nostr_public_key || '', + balance: app.owner?.balance_sats || 0 + } + } catch (e) { + // GetApplication throws if not found + return null + } + } + }, + + paymentManager: { + async createInvoice(params: { + applicationId: string + amountSats: number + memo?: string + expiry?: number + metadata?: Record + }) { + // Get the app to find the user ID + const app = await mainHandler.storage.applicationStorage.GetApplication(params.applicationId) + if (!app) { + throw new Error(`Application not found: ${params.applicationId}`) + } + + // Create invoice using the app owner's user ID + const result = await mainHandler.paymentManager.NewInvoice( + app.owner.user_id, + { + amountSats: params.amountSats, + memo: params.memo || '' + }, + { + expiry: params.expiry || 3600 + } + ) + + return { + id: result.invoice.split(':')[0] || result.invoice, // Extract ID if present + paymentRequest: result.invoice, + paymentHash: '', // Not directly available from NewInvoice response + expiry: Date.now() + (params.expiry || 3600) * 1000 + } + }, + + async payInvoice(params: { + applicationId: string + paymentRequest: string + maxFeeSats?: number + }) { + // Get the app to find the user ID and app reference + const app = await mainHandler.storage.applicationStorage.GetApplication(params.applicationId) + if (!app) { + throw new Error(`Application not found: ${params.applicationId}`) + } + + // Pay invoice from the app's balance + const result = await mainHandler.paymentManager.PayInvoice( + app.owner.user_id, + { + invoice: params.paymentRequest, + amount: 0 // Use invoice amount + }, + app, // linkedApplication + {} + ) + + return { + paymentHash: result.preimage || '', // preimage serves as proof of payment + feeSats: result.network_fee || 0 + } + }, + + async getLnurlPayInfoByPubkey(pubkeyHex: string, options?: { + metadata?: string + description?: string + }): Promise { + // This would need implementation based on how Lightning.Pub handles LNURL-pay + // For now, throw not implemented + throw new Error('getLnurlPayInfoByPubkey not yet implemented') + } + }, + + async sendNostrEvent(event: any): Promise { + // The mainHandler doesn't directly expose nostrSend + // This would need to be implemented through the nostrMiddleware + // For now, return null (not implemented) + console.warn('[MainHandlerAdapter] sendNostrEvent not fully implemented') + return null + }, + + async sendEncryptedDM( + applicationId: string, + recipientPubkey: string, + content: string + ): Promise { + // This would need implementation using NIP-44 encryption + // For now, throw not implemented + throw new Error('sendEncryptedDM not yet implemented') + } + } +} diff --git a/src/index.ts b/src/index.ts index fbe6802c..87181da2 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,4 +1,7 @@ import 'dotenv/config' +import express from 'express' +import path from 'path' +import { fileURLToPath } from 'url' import NewServer from '../proto/autogenerated/ts/express_server.js' import GetServerMethods from './services/serverMethods/index.js' import serverOptions from './auth.js'; @@ -8,9 +11,15 @@ import { initMainHandler, initSettings } from './services/main/init.js'; import { nip19 } from 'nostr-tools' import { LoadStorageSettingsFromEnv } from './services/storage/index.js'; import { AppInfo } from './services/nostr/nostrPool.js'; +import { createExtensionLoader, ExtensionLoader } from './extensions/loader.js' +import { createMainHandlerAdapter } from './extensions/mainHandlerAdapter.js' +import type { HttpRoute } from './extensions/withdraw/types.js' //@ts-ignore const { nprofileEncode } = nip19 +const __filename = fileURLToPath(import.meta.url) +const __dirname = path.dirname(__filename) + const start = async () => { const log = getLogger({}) @@ -58,8 +67,91 @@ const start = async () => { wizard.AddConnectInfo(appNprofile, relays) } adminManager.setAppNprofile(appNprofile) + + // Initialize extension system + let extensionLoader: ExtensionLoader | null = null + const mainPort = settingsManager.getSettings().serviceSettings.servicePort + const extensionPort = mainPort + 1 + + // Extension routes run on a separate port (main port + 1) + // SERVICE_URL for extensions should point to this port for LNURL to work + // In production, use a reverse proxy to route /api/v1/lnurl/* to extension port + const extensionServiceUrl = process.env.EXTENSION_SERVICE_URL || `http://localhost:${extensionPort}` + + try { + log("initializing extension system") + const extensionsDir = path.join(__dirname, 'extensions') + const databaseDir = path.join(__dirname, '..', 'data', 'extensions') + + const mainHandlerAdapter = createMainHandlerAdapter(mainHandler) + extensionLoader = createExtensionLoader( + { extensionsDir, databaseDir }, + mainHandlerAdapter + ) + + await extensionLoader.loadAll() + log(`loaded ${extensionLoader.getAllExtensions().length} extension(s)`) + + // Set base URL for LNURL generation on withdraw extension + const withdrawExt = extensionLoader.getExtension('withdraw') + if (withdrawExt && withdrawExt.instance && 'setBaseUrl' in withdrawExt.instance) { + (withdrawExt.instance as any).setBaseUrl(extensionServiceUrl) + log(`withdraw extension base URL set to ${extensionServiceUrl}`) + } + } catch (e) { + log(`extension system initialization failed: ${e}`) + } + + // Create Express app for extension HTTP routes + const extensionApp = express() + extensionApp.use(express.json()) + + // Mount extension HTTP routes + if (extensionLoader) { + for (const ext of extensionLoader.getAllExtensions()) { + if (ext.status === 'ready' && 'getHttpRoutes' in ext.instance) { + const routes = (ext.instance as any).getHttpRoutes() as HttpRoute[] + for (const route of routes) { + log(`mounting extension route: ${route.method} ${route.path}`) + const handler = async (req: express.Request, res: express.Response) => { + try { + const httpReq = { + params: req.params, + query: req.query as Record, + body: req.body, + headers: req.headers as Record + } + const result = await route.handler(httpReq) + res.status(result.status) + if (result.headers) { + for (const [key, value] of Object.entries(result.headers)) { + res.setHeader(key, value) + } + } + res.json(result.body) + } catch (e: any) { + log(`extension route error: ${e.message}`) + res.status(500).json({ status: 'ERROR', reason: e.message }) + } + } + if (route.method === 'GET') { + extensionApp.get(route.path, handler) + } else if (route.method === 'POST') { + extensionApp.post(route.path, handler) + } + } + } + } + } + + // Start extension routes server + extensionApp.listen(extensionPort, () => { + log(`extension HTTP routes listening on port ${extensionPort}`) + }) + + // Start main proto server const Server = NewServer(serverMethods, serverOptions(mainHandler)) - Server.Listen(settingsManager.getSettings().serviceSettings.servicePort) + Server.Listen(mainPort) } start() From f06d50f2272a0ea0fbb8d2067fca6770dfb92b65 Mon Sep 17 00:00:00 2001 From: Patrick Mulligan Date: Sat, 14 Feb 2026 15:28:54 -0500 Subject: [PATCH 56/66] feat(server): add CORS support for extension HTTP routes Enable CORS on the extension HTTP server to allow cross-origin requests from ATM apps and other web-based clients. Co-Authored-By: Claude Opus 4.5 --- src/index.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/index.ts b/src/index.ts index 87181da2..2788c5d0 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,5 +1,6 @@ import 'dotenv/config' import express from 'express' +import cors from 'cors' import path from 'path' import { fileURLToPath } from 'url' import NewServer from '../proto/autogenerated/ts/express_server.js' @@ -104,6 +105,7 @@ const start = async () => { // Create Express app for extension HTTP routes const extensionApp = express() + extensionApp.use(cors()) // Enable CORS for all origins (ATM apps, wallets, etc.) extensionApp.use(express.json()) // Mount extension HTTP routes From 3ee8b6b0106fcad7a1f14c132060642823a7e9b5 Mon Sep 17 00:00:00 2001 From: Patrick Mulligan Date: Sat, 14 Feb 2026 15:29:04 -0500 Subject: [PATCH 57/66] feat(withdraw): add HTTP API for creating withdraw links Add POST /api/v1/withdraw/create endpoint to allow external apps (ATM, web clients) to create LNURL-withdraw links via HTTP instead of RPC. Changes: - Add handleCreateWithdrawLink HTTP handler - Fix route ordering: callback routes before wildcard :unique_hash - Extract app_id from Authorization header (Bearer app_) - Use is_unique=false for simple single-use ATM links Co-Authored-By: Claude Opus 4.5 --- src/extensions/withdraw/index.ts | 91 +++++++++++++++++++++++++++++--- 1 file changed, 85 insertions(+), 6 deletions(-) diff --git a/src/extensions/withdraw/index.ts b/src/extensions/withdraw/index.ts index 0b8259d6..dacf045e 100644 --- a/src/extensions/withdraw/index.ts +++ b/src/extensions/withdraw/index.ts @@ -82,11 +82,17 @@ export default class WithdrawExtension implements Extension { */ getHttpRoutes(): HttpRoute[] { return [ - // Initial LNURL request (simple link) + // Create withdraw link (HTTP API for ATM/external integrations) + { + method: 'POST', + path: '/api/v1/withdraw/create', + handler: this.handleCreateWithdrawLink.bind(this) + }, + // LNURL callback (user submits invoice) - MUST be before :unique_hash routes { method: 'GET', - path: '/api/v1/lnurl/:unique_hash', - handler: this.handleLnurlRequest.bind(this) + path: '/api/v1/lnurl/cb/:unique_hash', + handler: this.handleLnurlCallback.bind(this) }, // Initial LNURL request (unique link with use hash) { @@ -94,11 +100,11 @@ export default class WithdrawExtension implements Extension { path: '/api/v1/lnurl/:unique_hash/:id_unique_hash', handler: this.handleLnurlUniqueRequest.bind(this) }, - // LNURL callback (user submits invoice) + // Initial LNURL request (simple link) - MUST be last (catches all) { method: 'GET', - path: '/api/v1/lnurl/cb/:unique_hash', - handler: this.handleLnurlCallback.bind(this) + path: '/api/v1/lnurl/:unique_hash', + handler: this.handleLnurlRequest.bind(this) } ] } @@ -231,6 +237,79 @@ export default class WithdrawExtension implements Extension { // HTTP Route Handlers // ========================================================================= + /** + * Handle create withdraw link request (HTTP API) + * POST /api/v1/withdraw/create + * + * Body: { + * title: string + * min_withdrawable: number (sats) + * max_withdrawable: number (sats) + * uses?: number (defaults to 1) + * wait_time?: number (seconds between uses, defaults to 0) + * } + * + * Auth: Bearer token in Authorization header (app_) + * + * Returns: { + * link: { lnurl, unique_hash, id, ... } + * } + */ + private async handleCreateWithdrawLink(req: HttpRequest): Promise { + try { + const { title, min_withdrawable, max_withdrawable, uses, wait_time } = req.body + + // Extract app_id from Authorization header (Bearer app_) + const authHeader = req.headers?.authorization || req.headers?.Authorization || '' + let app_id = 'default' + if (authHeader.startsWith('Bearer app_')) { + app_id = authHeader.replace('Bearer app_', '') + } + + if (!title || !min_withdrawable) { + return { + status: 400, + body: { status: 'ERROR', reason: 'Missing required fields: title, min_withdrawable' }, + headers: { 'Content-Type': 'application/json' } + } + } + + const link = await this.manager.create(app_id, { + title, + min_withdrawable, + max_withdrawable: max_withdrawable || min_withdrawable, + uses: uses || 1, + wait_time: wait_time || 0, + is_unique: false // Simple single-use links for ATM + }) + + // Return in format expected by ATM client + return { + status: 200, + body: { + status: 'OK', + link: { + lnurl: link.lnurl, + unique_hash: link.unique_hash, + id: link.id, + title: link.title, + min_withdrawable: link.min_withdrawable, + max_withdrawable: link.max_withdrawable, + uses: link.uses, + used: link.used + } + }, + headers: { 'Content-Type': 'application/json' } + } + } catch (error: any) { + return { + status: 500, + body: { status: 'ERROR', reason: error.message }, + headers: { 'Content-Type': 'application/json' } + } + } + } + /** * Handle initial LNURL request (simple link) * GET /api/v1/lnurl/:unique_hash From 1273da90206529a14041ce70ddad94f1e4d33bf3 Mon Sep 17 00:00:00 2001 From: Patrick Mulligan Date: Mon, 16 Feb 2026 16:55:53 -0500 Subject: [PATCH 58/66] feat: route Nostr RPC to extension methods Initialize extension system before nostrMiddleware so registered RPC methods are available. Extension methods (e.g. withdraw.createLink) are intercepted and routed to the extension loader before falling through to the standard nostrTransport. Co-Authored-By: Claude Opus 4.6 --- src/index.ts | 71 ++++++++++++++++++++++-------------------- src/nostrMiddleware.ts | 33 +++++++++++++++++++- 2 files changed, 69 insertions(+), 35 deletions(-) diff --git a/src/index.ts b/src/index.ts index 2788c5d0..5fbb21dc 100644 --- a/src/index.ts +++ b/src/index.ts @@ -35,41 +35,8 @@ const start = async () => { const { mainHandler, localProviderClient, wizard, adminManager } = keepOn const serverMethods = GetServerMethods(mainHandler) - log("initializing nostr middleware") - const relays = settingsManager.getSettings().nostrRelaySettings.relays - const maxEventContentLength = settingsManager.getSettings().nostrRelaySettings.maxEventContentLength - const apps: AppInfo[] = keepOn.apps.map(app => { - return { - appId: app.appId, - privateKey: app.privateKey, - publicKey: app.publicKey, - name: app.name, - provider: app.publicKey === localProviderClient.publicKey ? { - clientId: `client_${localProviderClient.appId}`, - pubkey: settingsManager.getSettings().liquiditySettings.liquidityProviderPub, - relayUrl: settingsManager.getSettings().liquiditySettings.providerRelayUrl - } : undefined - } - }) - const { Send, Stop, Ping, Reset } = nostrMiddleware(serverMethods, mainHandler, - { - relays, maxEventContentLength, apps - }, - (e, p) => mainHandler.liquidityProvider.onEvent(e, p) - ) - exitHandler(() => { Stop(); mainHandler.Stop() }) - log("starting server") - mainHandler.attachNostrSend(Send) - mainHandler.attachNostrProcessPing(Ping) - mainHandler.attachNostrReset(Reset) - mainHandler.StartBeacons() - const appNprofile = nprofileEncode({ pubkey: localProviderClient.publicKey, relays }) - if (wizard) { - wizard.AddConnectInfo(appNprofile, relays) - } - adminManager.setAppNprofile(appNprofile) - // Initialize extension system + // Initialize extension system BEFORE nostrMiddleware so RPC methods are available let extensionLoader: ExtensionLoader | null = null const mainPort = settingsManager.getSettings().serviceSettings.servicePort const extensionPort = mainPort + 1 @@ -103,6 +70,42 @@ const start = async () => { log(`extension system initialization failed: ${e}`) } + // Initialize nostr middleware with extension loader for RPC routing + log("initializing nostr middleware") + const relays = settingsManager.getSettings().nostrRelaySettings.relays + const maxEventContentLength = settingsManager.getSettings().nostrRelaySettings.maxEventContentLength + const apps: AppInfo[] = keepOn.apps.map(app => { + return { + appId: app.appId, + privateKey: app.privateKey, + publicKey: app.publicKey, + name: app.name, + provider: app.publicKey === localProviderClient.publicKey ? { + clientId: `client_${localProviderClient.appId}`, + pubkey: settingsManager.getSettings().liquiditySettings.liquidityProviderPub, + relayUrl: settingsManager.getSettings().liquiditySettings.providerRelayUrl + } : undefined + } + }) + const { Send, Stop, Ping, Reset } = nostrMiddleware(serverMethods, mainHandler, + { + relays, maxEventContentLength, apps + }, + (e, p) => mainHandler.liquidityProvider.onEvent(e, p), + { extensionLoader: extensionLoader || undefined } + ) + exitHandler(() => { Stop(); mainHandler.Stop() }) + log("starting server") + mainHandler.attachNostrSend(Send) + mainHandler.attachNostrProcessPing(Ping) + mainHandler.attachNostrReset(Reset) + mainHandler.StartBeacons() + const appNprofile = nprofileEncode({ pubkey: localProviderClient.publicKey, relays }) + if (wizard) { + wizard.AddConnectInfo(appNprofile, relays) + } + adminManager.setAppNprofile(appNprofile) + // Create Express app for extension HTTP routes const extensionApp = express() extensionApp.use(cors()) // Enable CORS for all origins (ATM apps, wallets, etc.) diff --git a/src/nostrMiddleware.ts b/src/nostrMiddleware.ts index 4dd3b281..a7131375 100644 --- a/src/nostrMiddleware.ts +++ b/src/nostrMiddleware.ts @@ -5,9 +5,15 @@ import * as Types from '../proto/autogenerated/ts/types.js' import NewNostrTransport, { NostrRequest } from '../proto/autogenerated/ts/nostr_transport.js'; import { ERROR, getLogger } from "./services/helpers/logger.js"; import { NdebitData, NofferData, NmanageRequest } from "@shocknet/clink-sdk"; +import type { ExtensionLoader } from "./extensions/loader.js" type ExportedCalls = { Stop: () => void, Send: NostrSend, Ping: () => Promise, Reset: (settings: NostrSettings) => void } type ClientEventCallback = (e: { requestId: string }, fromPub: string) => void -export default (serverMethods: Types.ServerMethods, mainHandler: Main, nostrSettings: NostrSettings, onClientEvent: ClientEventCallback): ExportedCalls => { + +export type NostrMiddlewareOptions = { + extensionLoader?: ExtensionLoader +} + +export default (serverMethods: Types.ServerMethods, mainHandler: Main, nostrSettings: NostrSettings, onClientEvent: ClientEventCallback, options?: NostrMiddlewareOptions): ExportedCalls => { const log = getLogger({}) const nostrTransport = NewNostrTransport(serverMethods, { NostrUserAuthGuard: async (appId, pub) => { @@ -95,6 +101,31 @@ export default (serverMethods: Types.ServerMethods, mainHandler: Main, nostrSett log(ERROR, "authIdentifier does not match", j.authIdentifier || "--", event.pub) return } + + // Check if this is an extension RPC method + const extensionLoader = options?.extensionLoader + if (extensionLoader && j.rpcName && extensionLoader.hasMethod(j.rpcName)) { + // Route to extension + log(`[Nostr] Routing to extension method: ${j.rpcName}`) + extensionLoader.callMethod(j.rpcName, j.body || {}, event.appId, event.pub) + .then(result => { + const response = { status: 'OK', requestId: j.requestId, ...result } + nostr.Send( + { type: 'app', appId: event.appId }, + { type: 'content', pub: event.pub, content: JSON.stringify(response) } + ) + }) + .catch(err => { + log(ERROR, `Extension method ${j.rpcName} failed:`, err.message) + const response = { status: 'ERROR', requestId: j.requestId, reason: err.message } + nostr.Send( + { type: 'app', appId: event.appId }, + { type: 'content', pub: event.pub, content: JSON.stringify(response) } + ) + }) + return + } + nostrTransport({ ...j, appId: event.appId }, res => { nostr.Send({ type: 'app', appId: event.appId }, { type: 'content', pub: event.pub, content: JSON.stringify({ ...res, requestId: j.requestId }) }) }, event.startAtNano, event.startAtMs) From cb9fb78eb889c4b2dc565c3921ba1894ae05e011 Mon Sep 17 00:00:00 2001 From: Patrick Mulligan Date: Mon, 16 Feb 2026 16:56:21 -0500 Subject: [PATCH 59/66] feat(withdraw): track creator pubkey on withdraw links Store the Nostr pubkey of the user who creates a withdraw link so the LNURL callback debits the correct user's balance instead of the app owner's. Pass userPubkey through from RPC handler to WithdrawManager. - Add creator_pubkey column (migration v4) - Store creatorPubkey on link creation - Pass creator_pubkey to payInvoice on LNURL callback Co-Authored-By: Claude Opus 4.6 --- src/extensions/withdraw/index.ts | 4 ++-- .../withdraw/managers/withdrawManager.ts | 14 ++++++++++---- src/extensions/withdraw/migrations.ts | 11 +++++++++++ src/extensions/withdraw/types.ts | 3 +++ 4 files changed, 26 insertions(+), 6 deletions(-) diff --git a/src/extensions/withdraw/index.ts b/src/extensions/withdraw/index.ts index dacf045e..1a38930b 100644 --- a/src/extensions/withdraw/index.ts +++ b/src/extensions/withdraw/index.ts @@ -114,8 +114,8 @@ export default class WithdrawExtension implements Extension { */ private registerRpcMethods(ctx: ExtensionContext): void { // Create withdraw link - ctx.registerMethod('withdraw.createLink', async (req, appId) => { - const link = await this.manager.create(appId, req as CreateWithdrawLinkRequest) + ctx.registerMethod('withdraw.createLink', async (req, appId, userPubkey) => { + const link = await this.manager.create(appId, req as CreateWithdrawLinkRequest, userPubkey) const stats = await this.manager.getWithdrawalStats(link.id) return { link, diff --git a/src/extensions/withdraw/managers/withdrawManager.ts b/src/extensions/withdraw/managers/withdrawManager.ts index 91677f82..5f76008e 100644 --- a/src/extensions/withdraw/managers/withdrawManager.ts +++ b/src/extensions/withdraw/managers/withdrawManager.ts @@ -48,6 +48,7 @@ interface WithdrawLinkRow { is_unique: number uses_csv: string open_time: number + creator_pubkey: string | null webhook_url: string | null webhook_headers: string | null webhook_body: string | null @@ -87,6 +88,7 @@ function rowToLink(row: WithdrawLinkRow): WithdrawLink { is_unique: row.is_unique === 1, uses_csv: row.uses_csv, open_time: row.open_time, + creator_pubkey: row.creator_pubkey || undefined, webhook_url: row.webhook_url || undefined, webhook_headers: row.webhook_headers || undefined, webhook_body: row.webhook_body || undefined, @@ -150,7 +152,7 @@ export class WithdrawManager { /** * Create a new withdraw link */ - async create(applicationId: string, req: CreateWithdrawLinkRequest): Promise { + async create(applicationId: string, req: CreateWithdrawLinkRequest, creatorPubkey?: string): Promise { // Validation if (req.uses < 1 || req.uses > 250) { throw new Error('Uses must be between 1 and 250') @@ -200,6 +202,7 @@ export class WithdrawManager { is_unique: req.is_unique || false, uses_csv: usesCsv, open_time: now, + creator_pubkey: creatorPubkey, webhook_url: req.webhook_url, webhook_headers: req.webhook_headers, webhook_body: req.webhook_body, @@ -212,13 +215,15 @@ export class WithdrawManager { id, application_id, title, description, min_withdrawable, max_withdrawable, uses, used, wait_time, unique_hash, k1, is_unique, uses_csv, open_time, + creator_pubkey, webhook_url, webhook_headers, webhook_body, created_at, updated_at - ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, + ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, [ link.id, link.application_id, link.title, link.description || null, link.min_withdrawable, link.max_withdrawable, link.uses, link.used, link.wait_time, link.unique_hash, link.k1, link.is_unique ? 1 : 0, link.uses_csv, link.open_time, + link.creator_pubkey || null, link.webhook_url || null, link.webhook_headers || null, link.webhook_body || null, link.created_at, link.updated_at ] @@ -502,11 +507,12 @@ export class WithdrawManager { } try { - // Pay the invoice + // Pay the invoice from the creator's balance (if created via Nostr RPC) const payment = await this.ctx.payInvoice( link.application_id, params.pr, - link.max_withdrawable + link.max_withdrawable, + link.creator_pubkey ) // Record the withdrawal diff --git a/src/extensions/withdraw/migrations.ts b/src/extensions/withdraw/migrations.ts index 86886885..1625638a 100644 --- a/src/extensions/withdraw/migrations.ts +++ b/src/extensions/withdraw/migrations.ts @@ -122,6 +122,17 @@ export const migrations: Migration[] = [ ) `) } + }, + { + version: 4, + name: 'add_creator_pubkey_column', + up: async (db: ExtensionDatabase) => { + // Store the Nostr pubkey of the user who created the withdraw link + // so that when the LNURL callback fires, we debit the correct user's balance + await db.execute(` + ALTER TABLE withdraw_links ADD COLUMN creator_pubkey TEXT + `) + } } ] diff --git a/src/extensions/withdraw/types.ts b/src/extensions/withdraw/types.ts index d9d05da0..88d25f33 100644 --- a/src/extensions/withdraw/types.ts +++ b/src/extensions/withdraw/types.ts @@ -46,6 +46,9 @@ export interface WithdrawLink { // Rate limiting open_time: number // Unix timestamp when next use is allowed + // Creator identity (for Nostr RPC-created links) + creator_pubkey?: string // Nostr pubkey of the user who created this link + // Webhook notifications webhook_url?: string webhook_headers?: string // JSON string From 5aaa3bcc23d3b5cd3e1a16012ea667f36782d373 Mon Sep 17 00:00:00 2001 From: Patrick Mulligan Date: Mon, 16 Feb 2026 16:56:34 -0500 Subject: [PATCH 60/66] feat(extensions): pay from caller's balance via PayAppUserInvoice When userPubkey is provided, resolve the ApplicationUser and call applicationManager.PayAppUserInvoice instead of paymentManager.PayInvoice directly. This ensures notifyAppUserPayment fires, sending LiveUserOperation events via Nostr for real-time balance updates. Co-Authored-By: Claude Opus 4.6 --- src/extensions/context.ts | 19 +++++++++++++-- src/extensions/mainHandlerAdapter.ts | 35 ++++++++++++++++++++++++---- src/extensions/types.ts | 3 ++- 3 files changed, 50 insertions(+), 7 deletions(-) diff --git a/src/extensions/context.ts b/src/extensions/context.ts index b1c6e8d6..f18891f5 100644 --- a/src/extensions/context.ts +++ b/src/extensions/context.ts @@ -20,6 +20,17 @@ export interface MainHandlerInterface { // Application management applicationManager: { getById(id: string): Promise + PayAppUserInvoice(appId: string, req: { + amount: number + invoice: string + user_identifier: string + debit_npub?: string + }): Promise<{ + preimage: string + amount_paid: number + network_fee: number + service_fee: number + }> } // Payment operations @@ -41,6 +52,7 @@ export interface MainHandlerInterface { applicationId: string paymentRequest: string maxFeeSats?: number + userPubkey?: string }): Promise<{ paymentHash: string feeSats: number @@ -156,16 +168,19 @@ export class ExtensionContextImpl implements ExtensionContext { /** * Pay a Lightning invoice + * If userPubkey is provided, pays from that user's balance instead of app.owner */ async payInvoice( applicationId: string, paymentRequest: string, - maxFeeSats?: number + maxFeeSats?: number, + userPubkey?: string ): Promise<{ paymentHash: string; feeSats: number }> { return this.mainHandler.paymentManager.payInvoice({ applicationId, paymentRequest, - maxFeeSats + maxFeeSats, + userPubkey }) } diff --git a/src/extensions/mainHandlerAdapter.ts b/src/extensions/mainHandlerAdapter.ts index eecc96b3..fec73c3f 100644 --- a/src/extensions/mainHandlerAdapter.ts +++ b/src/extensions/mainHandlerAdapter.ts @@ -32,6 +32,10 @@ export function createMainHandlerAdapter(mainHandler: Main): MainHandlerInterfac // GetApplication throws if not found return null } + }, + + async PayAppUserInvoice(appId, req) { + return mainHandler.applicationManager.PayAppUserInvoice(appId, req) } }, @@ -73,6 +77,7 @@ export function createMainHandlerAdapter(mainHandler: Main): MainHandlerInterfac applicationId: string paymentRequest: string maxFeeSats?: number + userPubkey?: string }) { // Get the app to find the user ID and app reference const app = await mainHandler.storage.applicationStorage.GetApplication(params.applicationId) @@ -80,19 +85,41 @@ export function createMainHandlerAdapter(mainHandler: Main): MainHandlerInterfac throw new Error(`Application not found: ${params.applicationId}`) } - // Pay invoice from the app's balance + if (params.userPubkey) { + // Resolve the Nostr user's ApplicationUser to get their identifier + const appUser = await mainHandler.storage.applicationStorage.GetOrCreateNostrAppUser(app, params.userPubkey) + console.log(`[MainHandlerAdapter] Paying via PayAppUserInvoice from Nostr user ${params.userPubkey.slice(0, 8)}... (identifier: ${appUser.identifier})`) + + // Use applicationManager.PayAppUserInvoice so notifyAppUserPayment fires + // This sends LiveUserOperation events via Nostr for real-time balance updates + const result = await mainHandler.applicationManager.PayAppUserInvoice( + params.applicationId, + { + invoice: params.paymentRequest, + amount: 0, // Use invoice amount + user_identifier: appUser.identifier + } + ) + + return { + paymentHash: result.preimage || '', + feeSats: result.network_fee || 0 + } + } + + // Fallback: pay from app owner's balance (no Nostr user context) const result = await mainHandler.paymentManager.PayInvoice( app.owner.user_id, { invoice: params.paymentRequest, - amount: 0 // Use invoice amount + amount: 0 }, - app, // linkedApplication + app, {} ) return { - paymentHash: result.preimage || '', // preimage serves as proof of payment + paymentHash: result.preimage || '', feeSats: result.network_fee || 0 } }, diff --git a/src/extensions/types.ts b/src/extensions/types.ts index 2027fb09..66a4c46a 100644 --- a/src/extensions/types.ts +++ b/src/extensions/types.ts @@ -140,8 +140,9 @@ export interface ExtensionContext { /** * Pay a Lightning invoice (requires sufficient balance) + * If userPubkey is provided, pays from that user's balance instead of app.owner */ - payInvoice(applicationId: string, paymentRequest: string, maxFeeSats?: number): Promise<{ + payInvoice(applicationId: string, paymentRequest: string, maxFeeSats?: number, userPubkey?: string): Promise<{ paymentHash: string feeSats: number }> From 68c71599f8ac61a36a0b0775ee1ac2429d69eaab Mon Sep 17 00:00:00 2001 From: Patrick Mulligan Date: Sat, 28 Feb 2026 10:55:44 -0500 Subject: [PATCH 61/66] fix(lnd): allow self-payments for LNURL-withdraw When the user's wallet (e.g. Zeus) is connected to the same LND node that LP uses, LNURL-withdraw fails because LND rejects the payment with "no self-payments allowed". This is safe because LP always decrements the user's balance before paying and refunds on failure. Co-Authored-By: Claude Opus 4.6 --- src/services/lnd/payInvoiceReq.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/services/lnd/payInvoiceReq.ts b/src/services/lnd/payInvoiceReq.ts index 3b90dd3d..3ae28c30 100644 --- a/src/services/lnd/payInvoiceReq.ts +++ b/src/services/lnd/payInvoiceReq.ts @@ -9,7 +9,7 @@ export const PayInvoiceReq = (invoice: string, amount: number, feeLimit: number) maxParts: 3, timeoutSeconds: 50, - allowSelfPayment: false, + allowSelfPayment: true, amp: false, amtMsat: 0n, cltvLimit: 0, From e18fe9f83a8ef2c02557244336eedd802327d012 Mon Sep 17 00:00:00 2001 From: Patrick Mulligan Date: Fri, 13 Feb 2026 14:27:04 -0500 Subject: [PATCH 62/66] feat(extensions): add NIP-05 identity extension Implements Nostr NIP-05 for human-readable identity verification: - Username claiming and management (username@domain) - /.well-known/nostr.json endpoint per spec - Optional relay hints in JSON response - Admin controls for identity management RPC methods: - nip05.claim - Claim a username - nip05.release - Release your username - nip05.updateRelays - Update relay hints - nip05.getMyIdentity - Get your identity - nip05.lookup - Look up by username - nip05.lookupByPubkey - Look up by pubkey - nip05.listIdentities - List all (admin) - nip05.deactivate/reactivate - Admin controls Co-Authored-By: Claude Opus 4.5 --- src/extensions/nip05/index.ts | 227 +++++++++ src/extensions/nip05/managers/nip05Manager.ts | 452 ++++++++++++++++++ src/extensions/nip05/migrations.ts | 93 ++++ src/extensions/nip05/types.ts | 130 +++++ 4 files changed, 902 insertions(+) create mode 100644 src/extensions/nip05/index.ts create mode 100644 src/extensions/nip05/managers/nip05Manager.ts create mode 100644 src/extensions/nip05/migrations.ts create mode 100644 src/extensions/nip05/types.ts diff --git a/src/extensions/nip05/index.ts b/src/extensions/nip05/index.ts new file mode 100644 index 00000000..a37fe8e0 --- /dev/null +++ b/src/extensions/nip05/index.ts @@ -0,0 +1,227 @@ +/** + * NIP-05 Extension for Lightning.Pub + * + * Implements Nostr NIP-05: Mapping Nostr keys to DNS-based internet identifiers + * Allows users to claim human-readable addresses like alice@domain.com + * + * Features: + * - Username claiming and management + * - .well-known/nostr.json endpoint + * - Optional relay hints + * - Admin controls for identity management + */ + +import { + Extension, + ExtensionInfo, + ExtensionContext, + ExtensionDatabase, + HttpRoute, + HttpRequest, + HttpResponse +} from '../types.js' +import { runMigrations } from './migrations.js' +import { Nip05Manager } from './managers/nip05Manager.js' +import { + ClaimUsernameRequest, + UpdateRelaysRequest, + Nip05Config +} from './types.js' + +/** + * NIP-05 Extension + */ +export default class Nip05Extension implements Extension { + readonly info: ExtensionInfo = { + id: 'nip05', + name: 'NIP-05 Identity', + version: '1.0.0', + description: 'Human-readable Nostr identities (username@domain)', + author: 'Lightning.Pub', + minPubVersion: '1.0.0' + } + + private manager!: Nip05Manager + private ctx!: ExtensionContext + private config: Nip05Config = {} + + /** + * Initialize the extension + */ + async initialize(ctx: ExtensionContext, db: ExtensionDatabase): Promise { + this.ctx = ctx + + // Run migrations + await runMigrations(db) + + // Initialize manager + this.manager = new Nip05Manager(ctx, db, this.config) + + // Register RPC methods + this.registerRpcMethods(ctx) + + ctx.log('info', 'Extension initialized') + } + + /** + * Shutdown the extension + */ + async shutdown(): Promise { + // Cleanup if needed + } + + /** + * Configure the extension + */ + configure(config: Nip05Config): void { + this.config = config + } + + /** + * Get HTTP routes for this extension + * These need to be mounted by the main HTTP server + */ + getHttpRoutes(): HttpRoute[] { + return [ + // NIP-05 well-known endpoint + { + method: 'GET', + path: '/.well-known/nostr.json', + handler: this.handleNostrJson.bind(this) + }, + // Alternative path for proxied setups + { + method: 'GET', + path: '/api/v1/nip05/nostr.json', + handler: this.handleNostrJson.bind(this) + } + ] + } + + /** + * Register RPC methods with the extension context + */ + private registerRpcMethods(ctx: ExtensionContext): void { + // Claim a username + ctx.registerMethod('nip05.claim', async (req, appId, userId, pubkey) => { + if (!userId || !pubkey) { + throw new Error('Authentication required') + } + return this.manager.claimUsername(userId, pubkey, appId, req as ClaimUsernameRequest) + }) + + // Release your username + ctx.registerMethod('nip05.release', async (req, appId, userId) => { + if (!userId) { + throw new Error('Authentication required') + } + await this.manager.releaseUsername(userId, appId) + return { success: true } + }) + + // Update your relays + ctx.registerMethod('nip05.updateRelays', async (req, appId, userId) => { + if (!userId) { + throw new Error('Authentication required') + } + const identity = await this.manager.updateRelays(userId, appId, req as UpdateRelaysRequest) + return { identity } + }) + + // Get your identity + ctx.registerMethod('nip05.getMyIdentity', async (req, appId, userId) => { + if (!userId) { + throw new Error('Authentication required') + } + return this.manager.getMyIdentity(userId, appId) + }) + + // Look up a username (public) + ctx.registerMethod('nip05.lookup', async (req, appId) => { + return this.manager.lookupUsername(appId, req.username) + }) + + // Look up by pubkey (public) + ctx.registerMethod('nip05.lookupByPubkey', async (req, appId) => { + return this.manager.lookupByPubkey(appId, req.pubkey) + }) + + // List all identities (admin) + ctx.registerMethod('nip05.listIdentities', async (req, appId) => { + return this.manager.listIdentities(appId, { + limit: req.limit, + offset: req.offset, + activeOnly: req.active_only + }) + }) + + // Deactivate an identity (admin) + ctx.registerMethod('nip05.deactivate', async (req, appId) => { + await this.manager.deactivateIdentity(appId, req.identity_id) + return { success: true } + }) + + // Reactivate an identity (admin) + ctx.registerMethod('nip05.reactivate', async (req, appId) => { + await this.manager.reactivateIdentity(appId, req.identity_id) + return { success: true } + }) + } + + // ========================================================================= + // HTTP Route Handlers + // ========================================================================= + + /** + * Handle /.well-known/nostr.json request + * GET /.well-known/nostr.json?name= + * + * Per NIP-05 spec, returns: + * { + * "names": { "": "" }, + * "relays": { "": ["wss://..."] } + * } + */ + private async handleNostrJson(req: HttpRequest): Promise { + try { + // Get application ID from request context + // In a multi-tenant setup, this would come from the host or path + const appId = req.headers['x-application-id'] || 'default' + + // Set domain from request host for NIP-05 address formatting + if (req.headers['host']) { + this.manager.setDomain(req.headers['host'].split(':')[0]) + } + + // Get the name parameter + const name = req.query.name + + // Get the JSON response + const response = await this.manager.handleNostrJson(appId, name) + + return { + status: 200, + body: response, + headers: { + 'Content-Type': 'application/json', + 'Access-Control-Allow-Origin': '*', + 'Cache-Control': 'max-age=300' // Cache for 5 minutes + } + } + } catch (error) { + this.ctx.log('error', `Error handling nostr.json: ${error}`) + return { + status: 500, + body: { error: 'Internal server error' }, + headers: { + 'Content-Type': 'application/json', + 'Access-Control-Allow-Origin': '*' + } + } + } + } +} + +// Export types for external use +export * from './types.js' +export { Nip05Manager } from './managers/nip05Manager.js' diff --git a/src/extensions/nip05/managers/nip05Manager.ts b/src/extensions/nip05/managers/nip05Manager.ts new file mode 100644 index 00000000..3efe85b8 --- /dev/null +++ b/src/extensions/nip05/managers/nip05Manager.ts @@ -0,0 +1,452 @@ +/** + * NIP-05 Identity Manager + * + * Handles username claiming, lookup, and .well-known/nostr.json responses + */ + +import { ExtensionContext, ExtensionDatabase } from '../../types.js' +import { + Nip05Identity, + Nip05IdentityRow, + Nip05JsonResponse, + Nip05Config, + UsernameValidation, + ClaimUsernameRequest, + ClaimUsernameResponse, + UpdateRelaysRequest, + LookupUsernameResponse, + GetMyIdentityResponse +} from '../types.js' +import crypto from 'crypto' + +/** + * Default configuration + */ +const DEFAULT_CONFIG: Required = { + max_username_length: 30, + min_username_length: 1, + reserved_usernames: ['admin', 'root', 'system', 'support', 'help', 'info', 'contact', 'abuse', 'postmaster', 'webmaster', 'hostmaster', 'noreply', 'no-reply', 'null', 'undefined', 'api', 'www', 'mail', 'ftp', 'ssh', 'test', 'demo'], + include_relays: true, + default_relays: [] +} + +/** + * Convert database row to Nip05Identity + */ +function rowToIdentity(row: Nip05IdentityRow): Nip05Identity { + return { + id: row.id, + application_id: row.application_id, + user_id: row.user_id, + username: row.username, + pubkey_hex: row.pubkey_hex, + relays: JSON.parse(row.relays_json), + is_active: row.is_active === 1, + created_at: row.created_at, + updated_at: row.updated_at + } +} + +/** + * Generate a unique ID + */ +function generateId(): string { + return crypto.randomBytes(16).toString('hex') +} + +/** + * Validate username format + * - Lowercase alphanumeric and underscore only + * - Must start with a letter + * - Length within bounds + */ +function validateUsername(username: string, config: Required): UsernameValidation { + if (!username) { + return { valid: false, error: 'Username is required' } + } + + const normalized = username.toLowerCase().trim() + + if (normalized.length < config.min_username_length) { + return { valid: false, error: `Username must be at least ${config.min_username_length} character(s)` } + } + + if (normalized.length > config.max_username_length) { + return { valid: false, error: `Username must be at most ${config.max_username_length} characters` } + } + + // Only lowercase letters, numbers, and underscores + if (!/^[a-z][a-z0-9_]*$/.test(normalized)) { + return { valid: false, error: 'Username must start with a letter and contain only lowercase letters, numbers, and underscores' } + } + + // Check reserved usernames + if (config.reserved_usernames.includes(normalized)) { + return { valid: false, error: 'This username is reserved' } + } + + return { valid: true } +} + +/** + * Validate relay URLs + */ +function validateRelays(relays: string[]): UsernameValidation { + if (!Array.isArray(relays)) { + return { valid: false, error: 'Relays must be an array' } + } + + for (const relay of relays) { + if (typeof relay !== 'string') { + return { valid: false, error: 'Each relay must be a string' } + } + if (!relay.startsWith('wss://') && !relay.startsWith('ws://')) { + return { valid: false, error: `Invalid relay URL: ${relay}` } + } + } + + return { valid: true } +} + +export class Nip05Manager { + private ctx: ExtensionContext + private db: ExtensionDatabase + private config: Required + private domain: string + + constructor(ctx: ExtensionContext, db: ExtensionDatabase, config?: Nip05Config) { + this.ctx = ctx + this.db = db + this.config = { ...DEFAULT_CONFIG, ...config } + // Extract domain from the service URL + this.domain = this.extractDomain() + } + + /** + * Extract domain from service URL for NIP-05 addresses + */ + private extractDomain(): string { + // This would come from Lightning.Pub's configuration + // For now, we'll derive it when needed from the request host + return 'localhost' + } + + /** + * Set the domain (called from HTTP request context) + */ + setDomain(domain: string): void { + this.domain = domain + } + + /** + * Claim a username for the current user + */ + async claimUsername( + userId: string, + pubkeyHex: string, + applicationId: string, + request: ClaimUsernameRequest + ): Promise { + const normalizedUsername = request.username.toLowerCase().trim() + + // Validate username format + const validation = validateUsername(normalizedUsername, this.config) + if (!validation.valid) { + throw new Error(validation.error) + } + + // Validate relays if provided + const relays = request.relays || this.config.default_relays + if (relays.length > 0) { + const relayValidation = validateRelays(relays) + if (!relayValidation.valid) { + throw new Error(relayValidation.error) + } + } + + // Check if user already has an identity in this application + const existingByUser = await this.db.query( + `SELECT * FROM identities WHERE application_id = ? AND user_id = ?`, + [applicationId, userId] + ) + if (existingByUser.length > 0) { + throw new Error('You already have a username. Release it first to claim a new one.') + } + + // Check if username is already taken + const existingByUsername = await this.db.query( + `SELECT * FROM identities WHERE application_id = ? AND username = ?`, + [applicationId, normalizedUsername] + ) + if (existingByUsername.length > 0) { + throw new Error('This username is already taken') + } + + // Create the identity + const now = Math.floor(Date.now() / 1000) + const id = generateId() + + await this.db.execute( + `INSERT INTO identities (id, application_id, user_id, username, pubkey_hex, relays_json, is_active, created_at, updated_at) + VALUES (?, ?, ?, ?, ?, ?, 1, ?, ?)`, + [id, applicationId, userId, normalizedUsername, pubkeyHex, JSON.stringify(relays), now, now] + ) + + const identity: Nip05Identity = { + id, + application_id: applicationId, + user_id: userId, + username: normalizedUsername, + pubkey_hex: pubkeyHex, + relays, + is_active: true, + created_at: now, + updated_at: now + } + + return { + identity, + nip05_address: `${normalizedUsername}@${this.domain}` + } + } + + /** + * Release (delete) the current user's username + */ + async releaseUsername(userId: string, applicationId: string): Promise { + const result = await this.db.execute( + `DELETE FROM identities WHERE application_id = ? AND user_id = ?`, + [applicationId, userId] + ) + + if (result.changes === 0) { + throw new Error('You do not have a username to release') + } + } + + /** + * Update relays for the current user's identity + */ + async updateRelays( + userId: string, + applicationId: string, + request: UpdateRelaysRequest + ): Promise { + // Validate relays + const validation = validateRelays(request.relays) + if (!validation.valid) { + throw new Error(validation.error) + } + + const now = Math.floor(Date.now() / 1000) + + const result = await this.db.execute( + `UPDATE identities SET relays_json = ?, updated_at = ? WHERE application_id = ? AND user_id = ?`, + [JSON.stringify(request.relays), now, applicationId, userId] + ) + + if (result.changes === 0) { + throw new Error('You do not have a username') + } + + // Fetch and return the updated identity + const rows = await this.db.query( + `SELECT * FROM identities WHERE application_id = ? AND user_id = ?`, + [applicationId, userId] + ) + + return rowToIdentity(rows[0]) + } + + /** + * Get the current user's identity + */ + async getMyIdentity(userId: string, applicationId: string): Promise { + const rows = await this.db.query( + `SELECT * FROM identities WHERE application_id = ? AND user_id = ?`, + [applicationId, userId] + ) + + if (rows.length === 0) { + return { has_identity: false } + } + + const identity = rowToIdentity(rows[0]) + return { + has_identity: true, + identity, + nip05_address: `${identity.username}@${this.domain}` + } + } + + /** + * Look up a username (public, no auth required) + */ + async lookupUsername(applicationId: string, username: string): Promise { + const normalizedUsername = username.toLowerCase().trim() + + const rows = await this.db.query( + `SELECT * FROM identities WHERE application_id = ? AND username = ? AND is_active = 1`, + [applicationId, normalizedUsername] + ) + + if (rows.length === 0) { + return { found: false } + } + + const identity = rowToIdentity(rows[0]) + return { + found: true, + identity, + nip05_address: `${identity.username}@${this.domain}` + } + } + + /** + * Look up by pubkey + */ + async lookupByPubkey(applicationId: string, pubkeyHex: string): Promise { + const rows = await this.db.query( + `SELECT * FROM identities WHERE application_id = ? AND pubkey_hex = ? AND is_active = 1`, + [applicationId, pubkeyHex] + ) + + if (rows.length === 0) { + return { found: false } + } + + const identity = rowToIdentity(rows[0]) + return { + found: true, + identity, + nip05_address: `${identity.username}@${this.domain}` + } + } + + /** + * Handle /.well-known/nostr.json request + * This is the core NIP-05 endpoint + */ + async handleNostrJson(applicationId: string, name?: string): Promise { + const response: Nip05JsonResponse = { + names: {} + } + + if (this.config.include_relays) { + response.relays = {} + } + + if (name) { + // Look up specific username + const normalizedName = name.toLowerCase().trim() + const rows = await this.db.query( + `SELECT * FROM identities WHERE application_id = ? AND username = ? AND is_active = 1`, + [applicationId, normalizedName] + ) + + if (rows.length > 0) { + const identity = rowToIdentity(rows[0]) + response.names[identity.username] = identity.pubkey_hex + + if (this.config.include_relays && identity.relays.length > 0) { + response.relays![identity.pubkey_hex] = identity.relays + } + } + } else { + // Return all active identities (with reasonable limit) + const rows = await this.db.query( + `SELECT * FROM identities WHERE application_id = ? AND is_active = 1 LIMIT 1000`, + [applicationId] + ) + + for (const row of rows) { + const identity = rowToIdentity(row) + response.names[identity.username] = identity.pubkey_hex + + if (this.config.include_relays && identity.relays.length > 0) { + response.relays![identity.pubkey_hex] = identity.relays + } + } + } + + return response + } + + /** + * List all identities for an application (admin) + */ + async listIdentities( + applicationId: string, + options?: { limit?: number; offset?: number; activeOnly?: boolean } + ): Promise<{ identities: Nip05Identity[]; total: number }> { + const limit = options?.limit || 50 + const offset = options?.offset || 0 + const activeClause = options?.activeOnly !== false ? 'AND is_active = 1' : '' + + // Get total count + const countResult = await this.db.query<{ count: number }>( + `SELECT COUNT(*) as count FROM identities WHERE application_id = ? ${activeClause}`, + [applicationId] + ) + const total = countResult[0]?.count || 0 + + // Get page of results + const rows = await this.db.query( + `SELECT * FROM identities WHERE application_id = ? ${activeClause} + ORDER BY created_at DESC LIMIT ? OFFSET ?`, + [applicationId, limit, offset] + ) + + return { + identities: rows.map(rowToIdentity), + total + } + } + + /** + * Deactivate an identity (admin) + */ + async deactivateIdentity(applicationId: string, identityId: string): Promise { + const now = Math.floor(Date.now() / 1000) + + const result = await this.db.execute( + `UPDATE identities SET is_active = 0, updated_at = ? WHERE application_id = ? AND id = ?`, + [now, applicationId, identityId] + ) + + if (result.changes === 0) { + throw new Error('Identity not found') + } + } + + /** + * Reactivate an identity (admin) + */ + async reactivateIdentity(applicationId: string, identityId: string): Promise { + const now = Math.floor(Date.now() / 1000) + + // Check if username is taken by an active identity + const identity = await this.db.query( + `SELECT * FROM identities WHERE id = ? AND application_id = ?`, + [identityId, applicationId] + ) + + if (identity.length === 0) { + throw new Error('Identity not found') + } + + const conflicting = await this.db.query( + `SELECT * FROM identities WHERE application_id = ? AND username = ? AND is_active = 1 AND id != ?`, + [applicationId, identity[0].username, identityId] + ) + + if (conflicting.length > 0) { + throw new Error('Username is already taken by another active identity') + } + + await this.db.execute( + `UPDATE identities SET is_active = 1, updated_at = ? WHERE application_id = ? AND id = ?`, + [now, applicationId, identityId] + ) + } +} diff --git a/src/extensions/nip05/migrations.ts b/src/extensions/nip05/migrations.ts new file mode 100644 index 00000000..5cf22909 --- /dev/null +++ b/src/extensions/nip05/migrations.ts @@ -0,0 +1,93 @@ +/** + * NIP-05 Extension Database Migrations + */ + +import { ExtensionDatabase } from '../types.js' + +export interface Migration { + version: number + name: string + up: (db: ExtensionDatabase) => Promise + down?: (db: ExtensionDatabase) => Promise +} + +export const migrations: Migration[] = [ + { + version: 1, + name: 'create_identities_table', + up: async (db: ExtensionDatabase) => { + await db.execute(` + CREATE TABLE IF NOT EXISTS identities ( + id TEXT PRIMARY KEY, + application_id TEXT NOT NULL, + user_id TEXT NOT NULL, + + -- Identity mapping + username TEXT NOT NULL, + pubkey_hex TEXT NOT NULL, + + -- Optional relays (JSON array) + relays_json TEXT NOT NULL DEFAULT '[]', + + -- Status + is_active INTEGER NOT NULL DEFAULT 1, + + -- Timestamps + created_at INTEGER NOT NULL, + updated_at INTEGER NOT NULL + ) + `) + + // Unique username per application (case-insensitive via lowercase storage) + await db.execute(` + CREATE UNIQUE INDEX IF NOT EXISTS idx_identities_username_app + ON identities(application_id, username) + `) + + // One identity per user per application + await db.execute(` + CREATE UNIQUE INDEX IF NOT EXISTS idx_identities_user_app + ON identities(application_id, user_id) + `) + + // Look up by pubkey + await db.execute(` + CREATE INDEX IF NOT EXISTS idx_identities_pubkey + ON identities(pubkey_hex) + `) + + // Look up active identities for .well-known endpoint + await db.execute(` + CREATE INDEX IF NOT EXISTS idx_identities_active + ON identities(application_id, is_active, username) + `) + } + } +] + +/** + * Run all pending migrations + */ +export async function runMigrations(db: ExtensionDatabase): Promise { + // Get current version + const versionResult = await db.query<{ value: string }>( + `SELECT value FROM _extension_meta WHERE key = 'migration_version'` + ).catch(() => []) + + const currentVersion = versionResult.length > 0 ? parseInt(versionResult[0].value, 10) : 0 + + // Run pending migrations + for (const migration of migrations) { + if (migration.version > currentVersion) { + console.log(`[NIP-05] Running migration ${migration.version}: ${migration.name}`) + await migration.up(db) + + // Update version + await db.execute( + `INSERT INTO _extension_meta (key, value) VALUES ('migration_version', ?) + ON CONFLICT(key) DO UPDATE SET value = excluded.value`, + [String(migration.version)] + ) + } + } +} diff --git a/src/extensions/nip05/types.ts b/src/extensions/nip05/types.ts new file mode 100644 index 00000000..93967f4c --- /dev/null +++ b/src/extensions/nip05/types.ts @@ -0,0 +1,130 @@ +/** + * NIP-05 Extension Types + * + * Implements Nostr NIP-05: Mapping Nostr keys to DNS-based internet identifiers + * Allows users to have human-readable addresses like alice@domain.com + */ + +/** + * A NIP-05 identity mapping a username to a Nostr public key + */ +export interface Nip05Identity { + id: string + application_id: string + user_id: string + + /** The human-readable username (lowercase, alphanumeric + underscore) */ + username: string + + /** The Nostr public key in hex format */ + pubkey_hex: string + + /** Optional list of relay URLs for this user */ + relays: string[] + + /** Whether this identity is active */ + is_active: boolean + + created_at: number + updated_at: number +} + +/** + * NIP-05 JSON response format per the spec + * GET /.well-known/nostr.json?name= + */ +export interface Nip05JsonResponse { + names: Record + relays?: Record +} + +/** + * Request to claim a username + */ +export interface ClaimUsernameRequest { + username: string + relays?: string[] +} + +/** + * Response after claiming a username + */ +export interface ClaimUsernameResponse { + identity: Nip05Identity + nip05_address: string +} + +/** + * Request to update relays for a username + */ +export interface UpdateRelaysRequest { + relays: string[] +} + +/** + * Request to look up a username + */ +export interface LookupUsernameRequest { + username: string +} + +/** + * Response for username lookup + */ +export interface LookupUsernameResponse { + found: boolean + identity?: Nip05Identity + nip05_address?: string +} + +/** + * Response for getting current user's identity + */ +export interface GetMyIdentityResponse { + has_identity: boolean + identity?: Nip05Identity + nip05_address?: string +} + +/** + * Database row for NIP-05 identity + */ +export interface Nip05IdentityRow { + id: string + application_id: string + user_id: string + username: string + pubkey_hex: string + relays_json: string + is_active: number + created_at: number + updated_at: number +} + +/** + * Extension configuration + */ +export interface Nip05Config { + /** Maximum username length (default: 30) */ + max_username_length?: number + + /** Minimum username length (default: 1) */ + min_username_length?: number + + /** Reserved usernames that cannot be claimed */ + reserved_usernames?: string[] + + /** Whether to include relays in the JSON response (default: true) */ + include_relays?: boolean + + /** Default relays to suggest for new users */ + default_relays?: string[] +} + +/** + * Validation result for username + */ +export interface UsernameValidation { + valid: boolean + error?: string +} From 883bb71116c35fbbaf43788e9f9cff3e890480ef Mon Sep 17 00:00:00 2001 From: Patrick Mulligan Date: Fri, 13 Feb 2026 15:04:59 -0500 Subject: [PATCH 63/66] feat(nip05): add Lightning Address support for zaps Adds /.well-known/lnurlp/:username endpoint that: 1. Looks up username in NIP-05 database 2. Gets LNURL-pay info from Lightning.Pub for that user 3. Returns standard LUD-16 response for wallet compatibility This makes NIP-05 addresses (alice@domain) work seamlessly as Lightning Addresses for receiving payments and NIP-57 zaps. Co-Authored-By: Claude Opus 4.5 --- src/extensions/nip05/index.ts | 73 +++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) diff --git a/src/extensions/nip05/index.ts b/src/extensions/nip05/index.ts index a37fe8e0..a8c1a7fd 100644 --- a/src/extensions/nip05/index.ts +++ b/src/extensions/nip05/index.ts @@ -94,6 +94,13 @@ export default class Nip05Extension implements Extension { method: 'GET', path: '/api/v1/nip05/nostr.json', handler: this.handleNostrJson.bind(this) + }, + // Lightning Address endpoint (LUD-16) + // Makes NIP-05 usernames work as Lightning Addresses for zaps + { + method: 'GET', + path: '/.well-known/lnurlp/:username', + handler: this.handleLnurlPay.bind(this) } ] } @@ -220,6 +227,72 @@ export default class Nip05Extension implements Extension { } } } + + /** + * Handle /.well-known/lnurlp/:username request (Lightning Address / LUD-16) + * + * This enables NIP-05 usernames to work as Lightning Addresses for receiving + * payments and zaps. When someone sends to alice@domain.com: + * 1. Wallet resolves /.well-known/lnurlp/alice + * 2. We look up alice -> pubkey in our NIP-05 database + * 3. We return LNURL-pay info from Lightning.Pub for that user + */ + private async handleLnurlPay(req: HttpRequest): Promise { + try { + const { username } = req.params + const appId = req.headers['x-application-id'] || 'default' + + if (!username) { + return { + status: 400, + body: { status: 'ERROR', reason: 'Username required' }, + headers: { + 'Content-Type': 'application/json', + 'Access-Control-Allow-Origin': '*' + } + } + } + + // Look up the username in our NIP-05 database + const lookup = await this.manager.lookupUsername(appId, username) + + if (!lookup.found || !lookup.identity) { + return { + status: 404, + body: { status: 'ERROR', reason: 'User not found' }, + headers: { + 'Content-Type': 'application/json', + 'Access-Control-Allow-Origin': '*' + } + } + } + + // Get LNURL-pay info from Lightning.Pub for this user's pubkey + const lnurlPayInfo = await this.ctx.getLnurlPayInfo(lookup.identity.pubkey_hex, { + description: `Pay to ${username}` + }) + + return { + status: 200, + body: lnurlPayInfo, + headers: { + 'Content-Type': 'application/json', + 'Access-Control-Allow-Origin': '*', + 'Cache-Control': 'max-age=60' // Cache for 1 minute + } + } + } catch (error) { + this.ctx.log('error', `Error handling lnurlp: ${error}`) + return { + status: 500, + body: { status: 'ERROR', reason: 'Internal server error' }, + headers: { + 'Content-Type': 'application/json', + 'Access-Control-Allow-Origin': '*' + } + } + } + } } // Export types for external use From 7dd767a78aa1230fb5db829b10064a64f07a5f4f Mon Sep 17 00:00:00 2001 From: Patrick Mulligan Date: Wed, 1 Apr 2026 13:25:06 -0400 Subject: [PATCH 64/66] fix(nip05): allow hyphens and periods in usernames per NIP-05 spec NIP-05 spec states local-part MUST only use characters a-z0-9-_. The previous regex /^[a-z][a-z0-9_]*$/ rejected hyphens and periods. Updated to /^[a-z][a-z0-9._-]*[a-z0-9]$/ and added support for the root identifier "_" (_@domain) as described in the spec. Co-Authored-By: Claude Opus 4.6 (1M context) --- src/extensions/nip05/managers/nip05Manager.ts | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/extensions/nip05/managers/nip05Manager.ts b/src/extensions/nip05/managers/nip05Manager.ts index 3efe85b8..d83fef1c 100644 --- a/src/extensions/nip05/managers/nip05Manager.ts +++ b/src/extensions/nip05/managers/nip05Manager.ts @@ -55,10 +55,12 @@ function generateId(): string { } /** - * Validate username format - * - Lowercase alphanumeric and underscore only + * Validate username format per NIP-05 spec + * - Characters allowed: a-z, 0-9, hyphen (-), underscore (_), period (.) * - Must start with a letter + * - Must not end with a hyphen, underscore, or period * - Length within bounds + * - Special case: "_" alone is the root identifier (_@domain) */ function validateUsername(username: string, config: Required): UsernameValidation { if (!username) { @@ -67,6 +69,11 @@ function validateUsername(username: string, config: Required): User const normalized = username.toLowerCase().trim() + // Special case: root identifier "_" per NIP-05 + if (normalized === '_') { + return { valid: true } + } + if (normalized.length < config.min_username_length) { return { valid: false, error: `Username must be at least ${config.min_username_length} character(s)` } } @@ -75,9 +82,10 @@ function validateUsername(username: string, config: Required): User return { valid: false, error: `Username must be at most ${config.max_username_length} characters` } } - // Only lowercase letters, numbers, and underscores - if (!/^[a-z][a-z0-9_]*$/.test(normalized)) { - return { valid: false, error: 'Username must start with a letter and contain only lowercase letters, numbers, and underscores' } + // NIP-05 spec: local-part MUST only use characters a-z0-9-_. + // Must start with a letter, must not end with separator + if (!/^[a-z][a-z0-9._-]*[a-z0-9]$/.test(normalized) && !/^[a-z]$/.test(normalized)) { + return { valid: false, error: 'Username must start with a letter, end with a letter or number, and contain only a-z, 0-9, hyphens, underscores, and periods' } } // Check reserved usernames From 915ca667e53440b05416134ff22c24daa01d5839 Mon Sep 17 00:00:00 2001 From: Patrick Mulligan Date: Wed, 1 Apr 2026 13:25:19 -0400 Subject: [PATCH 65/66] fix(nip05): add redirect prevention docs and zap field validation Gap #5: Document NIP-05 spec requirement that /.well-known/nostr.json MUST NOT return HTTP redirects. The extension already complies (always returns direct responses), but reverse proxy deployments need awareness. Gap #7: Log a warning when getLnurlPayInfo() response is missing allowsNostr or nostrPubkey fields required by NIP-57 for zap support. This surfaces misconfiguration early instead of silently breaking zaps. Co-Authored-By: Claude Opus 4.6 (1M context) --- src/extensions/nip05/index.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/extensions/nip05/index.ts b/src/extensions/nip05/index.ts index a8c1a7fd..c74c0bf5 100644 --- a/src/extensions/nip05/index.ts +++ b/src/extensions/nip05/index.ts @@ -189,6 +189,12 @@ export default class Nip05Extension implements Extension { * "relays": { "": ["wss://..."] } * } */ + /** + * NIP-05 spec: "The /.well-known/nostr.json endpoint MUST NOT return any + * HTTP redirects." This extension always returns direct 200/4xx/5xx responses. + * Deployment note: ensure reverse proxies do not add 3xx redirects on this path + * (e.g. HTTP→HTTPS or trailing-slash redirects). + */ private async handleNostrJson(req: HttpRequest): Promise { try { // Get application ID from request context @@ -272,6 +278,11 @@ export default class Nip05Extension implements Extension { description: `Pay to ${username}` }) + // NIP-57: ensure zap support fields are present for wallet compatibility + if (!lnurlPayInfo.allowsNostr || !lnurlPayInfo.nostrPubkey) { + this.ctx.log('warn', `LNURL-pay response for ${username} missing zap fields (allowsNostr=${lnurlPayInfo.allowsNostr}, nostrPubkey=${!!lnurlPayInfo.nostrPubkey}). Zaps will not work.`) + } + return { status: 200, body: lnurlPayInfo, From f59073e58932cadb30ba705c230cd5123ae0cbe6 Mon Sep 17 00:00:00 2001 From: Patrick Mulligan Date: Wed, 1 Apr 2026 13:31:33 -0400 Subject: [PATCH 66/66] fix(nip05): add configurable limits for relays per user and identity listing Adds max_relays_per_user (default: 10) to prevent users from attaching excessive relay URLs that inflate .well-known/nostr.json responses. Enforced in both claimUsername and updateRelays. Reduces the no-name listing limit from hardcoded 1000 to configurable max_identities_listing (default: 100) for the /.well-known/nostr.json endpoint when no ?name= parameter is provided. Co-Authored-By: Claude Opus 4.6 (1M context) --- src/extensions/nip05/managers/nip05Manager.ts | 21 ++++++++++++------- src/extensions/nip05/types.ts | 6 ++++++ 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/src/extensions/nip05/managers/nip05Manager.ts b/src/extensions/nip05/managers/nip05Manager.ts index d83fef1c..4eba8225 100644 --- a/src/extensions/nip05/managers/nip05Manager.ts +++ b/src/extensions/nip05/managers/nip05Manager.ts @@ -27,7 +27,9 @@ const DEFAULT_CONFIG: Required = { min_username_length: 1, reserved_usernames: ['admin', 'root', 'system', 'support', 'help', 'info', 'contact', 'abuse', 'postmaster', 'webmaster', 'hostmaster', 'noreply', 'no-reply', 'null', 'undefined', 'api', 'www', 'mail', 'ftp', 'ssh', 'test', 'demo'], include_relays: true, - default_relays: [] + default_relays: [], + max_relays_per_user: 10, + max_identities_listing: 100 } /** @@ -99,11 +101,15 @@ function validateUsername(username: string, config: Required): User /** * Validate relay URLs */ -function validateRelays(relays: string[]): UsernameValidation { +function validateRelays(relays: string[], maxRelays?: number): UsernameValidation { if (!Array.isArray(relays)) { return { valid: false, error: 'Relays must be an array' } } + if (maxRelays && relays.length > maxRelays) { + return { valid: false, error: `Too many relays (max ${maxRelays})` } + } + for (const relay of relays) { if (typeof relay !== 'string') { return { valid: false, error: 'Each relay must be a string' } @@ -166,7 +172,7 @@ export class Nip05Manager { // Validate relays if provided const relays = request.relays || this.config.default_relays if (relays.length > 0) { - const relayValidation = validateRelays(relays) + const relayValidation = validateRelays(relays, this.config.max_relays_per_user) if (!relayValidation.valid) { throw new Error(relayValidation.error) } @@ -241,7 +247,7 @@ export class Nip05Manager { request: UpdateRelaysRequest ): Promise { // Validate relays - const validation = validateRelays(request.relays) + const validation = validateRelays(request.relays, this.config.max_relays_per_user) if (!validation.valid) { throw new Error(validation.error) } @@ -361,10 +367,11 @@ export class Nip05Manager { } } } else { - // Return all active identities (with reasonable limit) + // Return all active identities (with configurable limit) + const limit = this.config.max_identities_listing const rows = await this.db.query( - `SELECT * FROM identities WHERE application_id = ? AND is_active = 1 LIMIT 1000`, - [applicationId] + `SELECT * FROM identities WHERE application_id = ? AND is_active = 1 LIMIT ?`, + [applicationId, limit] ) for (const row of rows) { diff --git a/src/extensions/nip05/types.ts b/src/extensions/nip05/types.ts index 93967f4c..6836f714 100644 --- a/src/extensions/nip05/types.ts +++ b/src/extensions/nip05/types.ts @@ -119,6 +119,12 @@ export interface Nip05Config { /** Default relays to suggest for new users */ default_relays?: string[] + + /** Maximum number of relays per user (default: 10) */ + max_relays_per_user?: number + + /** Maximum number of identities returned when no name query param is provided (default: 100) */ + max_identities_listing?: number } /**