@@ -40,17 +40,13 @@ import fr.acinq.lightning.bin.logs.stringTimestamp
4040import fr.acinq.lightning.blockchain.mempool.MempoolSpaceClient
4141import fr.acinq.lightning.blockchain.mempool.MempoolSpaceWatcher
4242import fr.acinq.lightning.crypto.LocalKeyManager
43- import fr.acinq.lightning.db.ChannelsDb
44- import fr.acinq.lightning.db.Databases
45- import fr.acinq.lightning.db.PaymentsDb
43+ import fr.acinq.lightning.db.*
4644import fr.acinq.lightning.io.Peer
4745import fr.acinq.lightning.io.TcpSocket
4846import fr.acinq.lightning.logging.LoggerFactory
4947import fr.acinq.lightning.payment.LiquidityPolicy
50- import fr.acinq.lightning.utils.Connection
51- import fr.acinq.lightning.utils.msat
52- import fr.acinq.lightning.utils.sat
53- import fr.acinq.lightning.utils.toByteVector
48+ import fr.acinq.lightning.utils.*
49+ import fr.acinq.lightning.wire.LiquidityAds
5450import fr.acinq.phoenix.db.*
5551import io.ktor.http.*
5652import io.ktor.server.application.*
@@ -90,14 +86,14 @@ class Phoenixd : CliktCommand() {
9086 }
9187 private val agreeToTermsOfService by option(" --agree-to-terms-of-service" , hidden = true , help = " Agree to terms of service" ).flag()
9288 private val chain by option(" --chain" , help = " Bitcoin chain to use" ).choice(
93- " mainnet" to Chain .Mainnet , " testnet" to Chain .Testnet
89+ " mainnet" to Chain .Mainnet , " testnet" to Chain .Testnet3
9490 ).default(Chain .Mainnet , defaultForHelp = " mainnet" )
9591 private val mempoolSpaceUrl by option(" --mempool-space-url" , help = " Custom mempool.space instance" )
9692 .convert { Url (it) }
9793 .defaultLazy {
9894 when (chain) {
9995 Chain .Mainnet -> MempoolSpaceClient .OfficialMempoolMainnet
100- Chain .Testnet -> MempoolSpaceClient .OfficialMempoolTestnet
96+ Chain .Testnet3 -> MempoolSpaceClient .OfficialMempoolTestnet
10197 else -> error(" unsupported chain" )
10298 }
10399 }
@@ -155,7 +151,7 @@ class Phoenixd : CliktCommand() {
155151 " off" to 0 .sat,
156152 " 50k" to 50_000 .sat,
157153 " 100k" to 100_000 .sat,
158- ).default(100_000 .sat, " 100k" )
154+ ).convert { it.toMilliSatoshi() }. default(100_000 .sat.toMilliSatoshi() , " 100k" )
159155 private val maxRelativeFeePct by option(" --max-relative-fee-percent" , help = " Max relative fee for on-chain operations in percent." , hidden = true )
160156 .int()
161157 .restrictTo(1 .. 50 )
@@ -244,10 +240,11 @@ class Phoenixd : CliktCommand() {
244240 )
245241 val lsp = LSP .from(chain)
246242 val liquidityPolicy = LiquidityPolicy .Auto (
247- maxMiningFee = liquidityOptions.maxMiningFee,
243+ inboundLiquidityTarget = liquidityOptions.autoLiquidity,
244+ maxAbsoluteFee = liquidityOptions.maxMiningFee,
248245 maxRelativeFeeBasisPoints = liquidityOptions.maxRelativeFeeBasisPoints,
249- skipMiningFeeCheck = false ,
250- maxAllowedCredit = liquidityOptions.maxFeeCredit
246+ skipAbsoluteFeeCheck = false ,
247+ maxAllowedFeeCredit = liquidityOptions.maxFeeCredit
251248 )
252249 val keyManager = LocalKeyManager (seed.seed, chain, lsp.swapInXpub)
253250 val nodeParams = NodeParams (chain, loggerFactory, keyManager)
@@ -276,9 +273,6 @@ class Phoenixd : CliktCommand() {
276273 channel_close_outgoing_paymentsAdapter = Channel_close_outgoing_payments .Adapter (
277274 closing_info_typeAdapter = EnumColumnAdapter ()
278275 ),
279- inbound_liquidity_outgoing_paymentsAdapter = Inbound_liquidity_outgoing_payments .Adapter (
280- lease_typeAdapter = EnumColumnAdapter ()
281- )
282276 )
283277 val channelsDb = SqliteChannelsDb (driver, database)
284278 val paymentsDb = SqlitePaymentsDb (database)
@@ -324,39 +318,59 @@ class Phoenixd : CliktCommand() {
324318 }
325319 launch {
326320 nodeParams.nodeEvents
327- .filterIsInstance<PaymentEvents .PaymentReceived >()
328- .filter { it.amount > 0 .msat }
321+ .filterIsInstance<PaymentEvents >()
329322 .collect {
330- consoleLog(" received lightning payment: ${it.amount.truncateToSatoshi()} (${it.receivedWith.joinToString { part -> part::class .simpleName.toString().lowercase() }} )" )
323+ when (it) {
324+ is PaymentEvents .PaymentReceived -> {
325+ val fee = it.receivedWith.filterIsInstance<IncomingPayment .ReceivedWith .LightningPayment >().map { it.fundingFee?.amount ? : 0 .msat }.sum().truncateToSatoshi()
326+ val type = it.receivedWith.joinToString { part -> part::class .simpleName.toString().lowercase() }
327+ consoleLog(" received lightning payment: ${it.amount.truncateToSatoshi()} ($type${if (fee > 0 .sat) " fee=$fee " else " " } )" )
328+ }
329+ is PaymentEvents .PaymentSent ->
330+ when (val payment = it.payment) {
331+ is InboundLiquidityOutgoingPayment -> {
332+ val totalFee = payment.fees.truncateToSatoshi()
333+ val feePaidFromBalance = payment.feePaidFromChannelBalance.total
334+ val feePaidFromFeeCredit = payment.feeCreditUsed.truncateToSatoshi()
335+ val feeRemaining = totalFee - feePaidFromBalance - feePaidFromFeeCredit
336+ val purchaseType = payment.purchase.paymentDetails.paymentType::class .simpleName.toString().lowercase()
337+ consoleLog(" purchased inbound liquidity: ${payment.purchase.amount} (totalFee=$totalFee feePaidFromBalance=$feePaidFromBalance feePaidFromFeeCredit=$feePaidFromFeeCredit feeRemaining=$feeRemaining purchaseType=$purchaseType )" )
338+ }
339+ else -> {}
340+ }
341+ }
331342 }
332343 }
333344 launch {
334345 nodeParams.nodeEvents
335- .filterIsInstance<LiquidityEvents .Decision . Rejected >()
346+ .filterIsInstance<LiquidityEvents .Rejected >()
336347 .collect {
337348 when (val reason = it.reason) {
338- is LiquidityEvents .Decision .Rejected .Reason .OverMaxCredit -> {
339- consoleLog(yellow(" lightning payment rejected (amount=${it.amount.truncateToSatoshi()} ): over max fee credit (max=${reason.maxAllowedCredit} )" ))
340- }
341- is LiquidityEvents .Decision .Rejected .Reason .TooExpensive .OverMaxMiningFee -> {
342- consoleLog(yellow(" lightning payment rejected (amount=${it.amount.truncateToSatoshi()} ): over max mining fee (max=${reason.maxMiningFee} )" ))
343- }
344- is LiquidityEvents .Decision .Rejected .Reason .TooExpensive .OverRelativeFee -> {
345- consoleLog(yellow(" lightning payment rejected (amount=${it.amount.truncateToSatoshi()} ): fee=${it.fee.truncateToSatoshi()} more than ${reason.maxRelativeFeeBasisPoints.toDouble() / 100 } % of amount" ))
346- }
347- LiquidityEvents .Decision .Rejected .Reason .ChannelInitializing -> {
348- consoleLog(yellow(" channels are initializing" ))
349- }
350- LiquidityEvents .Decision .Rejected .Reason .PolicySetToDisabled -> {
349+ // TODO: put this back after rework of LiquidityPolicy to handle fee credit
350+ // is LiquidityEvents.Rejected.Reason.OverMaxCredit -> {
351+ // consoleLog(yellow("lightning payment rejected (amount=${it.amount.truncateToSatoshi()}): over max fee credit (max=${reason.maxAllowedCredit})"))
352+ // }
353+ is LiquidityEvents .Rejected .Reason .TooExpensive .OverAbsoluteFee ->
354+ consoleLog(yellow(" lightning payment rejected (amount=${it.amount.truncateToSatoshi()} ): over absolute fee (fee=${it.fee.truncateToSatoshi()} max=${reason.maxAbsoluteFee} )" ))
355+ is LiquidityEvents .Rejected .Reason .TooExpensive .OverRelativeFee ->
356+ consoleLog(yellow(" lightning payment rejected (amount=${it.amount.truncateToSatoshi()} ): over relative fee (fee=${it.fee.truncateToSatoshi()} max=${reason.maxRelativeFeeBasisPoints.toDouble() / 100 } %)" ))
357+ LiquidityEvents .Rejected .Reason .PolicySetToDisabled ->
351358 consoleLog(yellow(" automated liquidity is disabled" ))
352- }
359+ LiquidityEvents .Rejected .Reason .ChannelFundingInProgress ->
360+ consoleLog(yellow(" channel operation is in progress" ))
361+ is LiquidityEvents .Rejected .Reason .MissingOffChainAmountTooLow ->
362+ consoleLog(yellow(" missing offchain amount is too low (missingOffChainAmount=${reason.missingOffChainAmount} currentFeeCredit=${reason.currentFeeCredit} " ))
363+ LiquidityEvents .Rejected .Reason .NoMatchingFundingRate ->
364+ consoleLog(yellow(" no matching funding rates" ))
365+ is LiquidityEvents .Rejected .Reason .TooManyParts ->
366+ consoleLog(yellow(" too many payment parts" ))
353367 }
354368 }
355369 }
356370 launch {
357- nodeParams.feeCredit
358- .drop(1 ) // we drop the initial value which is 0 sat
359- .collect { feeCredit -> consoleLog(" fee credit: $feeCredit " ) }
371+ peer.feeCreditFlow
372+ .drop(1 ) // we drop the initial value which is 0 msat
373+ .collect { feeCredit -> consoleLog(" fee credit: ${ feeCredit.truncateToSatoshi()} " ) }
360374 }
361375 }
362376
@@ -370,8 +384,6 @@ class Phoenixd : CliktCommand() {
370384
371385 runBlocking {
372386 peer.connectionState.first { it == Connection .ESTABLISHED }
373- peer.registerFcmToken(" super-${randomBytes32().toHex()} " )
374- peer.setAutoLiquidityParams(liquidityOptions.autoLiquidity)
375387 }
376388
377389 val server = embeddedServer(CIO , port = httpBindPort, host = httpBindIp,
0 commit comments