From a4e38c30b4fbc504a9df7c7ddb3ba5310b462492 Mon Sep 17 00:00:00 2001 From: benthecarman <15256660+benthecarman@users.noreply.github.com> Date: Mon, 17 Oct 2022 14:41:53 -0500 Subject: [PATCH] Add helper functions for lnd chain notifications (#4846) --- .../lnd/rpc/LndRpcClientPairTest.scala | 16 +++++-- .../org/bitcoins/lnd/rpc/LndRpcClient.scala | 46 +++++++++++++++++++ 2 files changed, 59 insertions(+), 3 deletions(-) diff --git a/lnd-rpc-test/src/test/scala/org/bitcoins/lnd/rpc/LndRpcClientPairTest.scala b/lnd-rpc-test/src/test/scala/org/bitcoins/lnd/rpc/LndRpcClientPairTest.scala index 3727d0703d..23a97eee1e 100644 --- a/lnd-rpc-test/src/test/scala/org/bitcoins/lnd/rpc/LndRpcClientPairTest.scala +++ b/lnd-rpc-test/src/test/scala/org/bitcoins/lnd/rpc/LndRpcClientPairTest.scala @@ -17,13 +17,13 @@ import org.bitcoins.core.psbt.PSBT import org.bitcoins.core.wallet.fee.{SatoshisPerKW, SatoshisPerVirtualByte} import org.bitcoins.crypto._ import org.bitcoins.testkit.fixtures.DualLndFixture -import scodec.bits.HexStringSyntax +import scodec.bits.{ByteVector, HexStringSyntax} -import scala.concurrent.Future +import scala.concurrent.{Await, Future} import scala.concurrent.duration.DurationInt import scala.util.{Failure, Success} -class LndRpcClientPairTest extends DualLndFixture { +class LndRpcClientPairTest extends DualLndFixture with LndUtils { it must "get info from both lnds" in { param => val (_, lndA, lndB) = param @@ -196,8 +196,16 @@ class LndRpcClientPairTest extends DualLndFixture { tx <- lndA.sendOutputs(Vector(output), feeRate, spendUnconfirmed = false) _ <- lndA.publishTransaction(tx) + height <- bitcoind.getBlockCount + confirmedF = lndB.subscribeTxConfirmation(txId = tx.txId, + script = addr.scriptPubKey, + requiredConfs = 6, + heightHint = height) _ <- bitcoind.getNewAddress.flatMap(bitcoind.generateToAddress(6, _)) + // await so if this fails the test doesn't hang forever + conf = Await.result(confirmedF, 10.seconds) + detailsOpt <- lndB.getTransaction(tx.txIdBE) _ = assert(detailsOpt.isDefined) details = detailsOpt.get @@ -213,6 +221,8 @@ class LndRpcClientPairTest extends DualLndFixture { assert(details.txId == tx.txIdBE) assert(details.outputDetails.flatMap(_.addressOpt).contains(addr)) assert(details.amount == sendAmt) + + assert(ByteVector(conf.rawTx.toByteArray) == tx.bytes) } } diff --git a/lnd-rpc/src/main/scala/org/bitcoins/lnd/rpc/LndRpcClient.scala b/lnd-rpc/src/main/scala/org/bitcoins/lnd/rpc/LndRpcClient.scala index c4d1070401..8bda22d8ee 100644 --- a/lnd-rpc/src/main/scala/org/bitcoins/lnd/rpc/LndRpcClient.scala +++ b/lnd-rpc/src/main/scala/org/bitcoins/lnd/rpc/LndRpcClient.scala @@ -950,6 +950,52 @@ class LndRpcClient(val instance: LndInstance, binaryOpt: Option[File] = None)( .map(_.transactions.toVector.map(LndTransactionToTxDetails)) } + def subscribeTxConfirmation( + script: ScriptPubKey, + requiredConfs: Int, + heightHint: Int): Future[ConfDetails] = { + require(heightHint > 0, + s"heightHint must be greater than 0, got $heightHint") + + val request = + ConfRequest(txid = DoubleSha256Digest.empty.bytes, + script = script.asmBytes, + numConfs = UInt32(requiredConfs), + heightHint = UInt32(heightHint)) + + registerConfirmationsNotification(request) + .filter(_.event.isConf) + .runWith(Sink.head) + .map(_.getConf) + } + + def subscribeTxConfirmation( + txId: DoubleSha256Digest, + script: ScriptPubKey, + requiredConfs: Int, + heightHint: Int): Future[ConfDetails] = { + require(heightHint > 0, + s"heightHint must be greater than 0, got $heightHint") + + val request = + ConfRequest(txid = txId.bytes, + script = script.asmBytes, + numConfs = UInt32(requiredConfs), + heightHint = UInt32(heightHint)) + + registerConfirmationsNotification(request) + .filter(_.event.isConf) + .runWith(Sink.head) + .map(_.getConf) + } + + def registerConfirmationsNotification( + request: ConfRequest): Source[ConfEvent, NotUsed] = { + logger.trace("lnd calling RegisterConfirmationsNtfn") + + chainClient.registerConfirmationsNtfn(request) + } + def monitorInvoice( rHash: PaymentHashTag, interval: FiniteDuration = 1.second,