diff --git a/lnwallet/btcwallet/btcwallet.go b/lnwallet/btcwallet/btcwallet.go index 268d8dd4..420760e8 100644 --- a/lnwallet/btcwallet/btcwallet.go +++ b/lnwallet/btcwallet/btcwallet.go @@ -556,6 +556,7 @@ func minedTransactionsToDetails( // for an unconfirmed transaction to a transaction detail. func unminedTransactionsToDetail( summary base.TransactionSummary, + chainParams *chaincfg.Params, ) (*lnwallet.TransactionDetail, error) { wireTx := &wire.MsgTx{} @@ -565,11 +566,23 @@ func unminedTransactionsToDetail( return nil, err } + var destAddresses []btcutil.Address + for _, txOut := range wireTx.TxOut { + _, outAddresses, _, err := + txscript.ExtractPkScriptAddrs(txOut.PkScript, chainParams) + if err != nil { + return nil, err + } + + destAddresses = append(destAddresses, outAddresses...) + } + txDetail := &lnwallet.TransactionDetail{ - Hash: *summary.Hash, - TotalFees: int64(summary.Fee), - Timestamp: summary.Timestamp, - RawTx: summary.Transaction, + Hash: *summary.Hash, + TotalFees: int64(summary.Fee), + Timestamp: summary.Timestamp, + DestAddresses: destAddresses, + RawTx: summary.Transaction, } balanceDelta, err := extractBalanceDelta(summary, wireTx) @@ -618,7 +631,7 @@ func (b *BtcWallet) ListTransactionDetails() ([]*lnwallet.TransactionDetail, err txDetails = append(txDetails, details...) } for _, tx := range txns.UnminedTransactions { - detail, err := unminedTransactionsToDetail(tx) + detail, err := unminedTransactionsToDetail(tx, b.netParams) if err != nil { return nil, err } @@ -705,7 +718,9 @@ out: // notifications for any newly unconfirmed transactions. go func() { for _, tx := range txNtfn.UnminedTransactions { - detail, err := unminedTransactionsToDetail(tx) + detail, err := unminedTransactionsToDetail( + tx, t.w.ChainParams(), + ) if err != nil { continue } diff --git a/lnwallet/interface_test.go b/lnwallet/interface_test.go index 0f966263..ca7d9a27 100644 --- a/lnwallet/interface_test.go +++ b/lnwallet/interface_test.go @@ -1181,9 +1181,11 @@ func testListTransactionDetails(miner *rpctest.Harness, // Next create a transaction paying to an output which isn't under the // wallet's control. - b := txscript.NewScriptBuilder() - b.AddOp(txscript.OP_0) - outputScript, err := b.Script() + minerAddr, err := miner.NewAddress() + if err != nil { + t.Fatalf("unable to generate address: %v", err) + } + outputScript, err := txscript.PayToAddrScript(minerAddr) if err != nil { t.Fatalf("unable to make output script: %v", err) } @@ -1227,6 +1229,20 @@ func testListTransactionDetails(miner *rpctest.Harness, t.Fatalf("num confs incorrect, got %v expected %v", txDetail.NumConfirmations, 0) } + + // We test that each txDetail has destination addresses. This ensures + // that even when we have 0 confirmation transactions, the destination + // addresses are returned. + var match bool + for _, addr := range txDetail.DestAddresses { + if addr.String() == minerAddr.String() { + match = true + break + } + } + if !match { + t.Fatalf("minerAddr: %v should have been a dest addr", minerAddr) + } } if !mempoolTxFound { t.Fatalf("unable to find mempool tx in tx details!") diff --git a/rpcserver.go b/rpcserver.go index 560007c5..327ccf56 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -3576,6 +3576,10 @@ func (r *rpcServer) SubscribeTransactions(req *lnrpc.GetTransactionsRequest, for { select { case tx := <-txClient.ConfirmedTransactions(): + destAddresses := make([]string, 0, len(tx.DestAddresses)) + for _, destAddress := range tx.DestAddresses { + destAddresses = append(destAddresses, destAddress.EncodeAddress()) + } detail := &lnrpc.Transaction{ TxHash: tx.Hash.String(), Amount: int64(tx.Value), @@ -3583,6 +3587,7 @@ func (r *rpcServer) SubscribeTransactions(req *lnrpc.GetTransactionsRequest, BlockHash: tx.BlockHash.String(), TimeStamp: tx.Timestamp, TotalFees: tx.TotalFees, + DestAddresses: destAddresses, RawTxHex: hex.EncodeToString(tx.RawTx), } if err := updateStream.Send(detail); err != nil { @@ -3590,12 +3595,17 @@ func (r *rpcServer) SubscribeTransactions(req *lnrpc.GetTransactionsRequest, } case tx := <-txClient.UnconfirmedTransactions(): + var destAddresses []string + for _, destAddress := range tx.DestAddresses { + destAddresses = append(destAddresses, destAddress.EncodeAddress()) + } detail := &lnrpc.Transaction{ - TxHash: tx.Hash.String(), - Amount: int64(tx.Value), - TimeStamp: tx.Timestamp, - TotalFees: tx.TotalFees, - RawTxHex: hex.EncodeToString(tx.RawTx), + TxHash: tx.Hash.String(), + Amount: int64(tx.Value), + TimeStamp: tx.Timestamp, + TotalFees: tx.TotalFees, + DestAddresses: destAddresses, + RawTxHex: hex.EncodeToString(tx.RawTx), } if err := updateStream.Send(detail); err != nil { return err