func testTransactionSubscriptions(miner *rpctest.Harness, w *lnwallet.LightningWallet, t *testing.T) { t.Log("Running transaction subscriptions test") // First, check to see if this wallet meets the TransactionNotifier // interface, if not then we'll skip this test for this particular // implementation of the WalletController. txClient, err := w.SubscribeTransactions() if err != nil { t.Fatalf("unable to generate tx subscription: %v") } defer txClient.Cancel() const ( outputAmt = btcutil.SatoshiPerBitcoin numTxns = 3 ) unconfirmedNtfns := make(chan struct{}) go func() { for i := 0; i < numTxns; i++ { txDetail := <-txClient.UnconfirmedTransactions() if txDetail.NumConfirmations != 0 { t.Fatalf("incorrect number of confs, expected %v got %v", 0, txDetail.NumConfirmations) } if txDetail.Value != outputAmt { t.Fatalf("incorrect output amt, expected %v got %v", outputAmt, txDetail.Value) } if txDetail.BlockHash != nil { t.Fatalf("block hash should be nil, is instead %v", txDetail.BlockHash) } } close(unconfirmedNtfns) }() // Next, fetch a fresh address from the wallet, create 3 new outputs // with the pkScript. for i := 0; i < numTxns; i++ { addr, err := w.NewAddress(lnwallet.WitnessPubKey, false) if err != nil { t.Fatalf("unable to create new address: %v", err) } script, err := txscript.PayToAddrScript(addr) if err != nil { t.Fatalf("unable to create output script: %v", err) } output := &wire.TxOut{outputAmt, script} if _, err := miner.CoinbaseSpend([]*wire.TxOut{output}); err != nil { t.Fatalf("unable to send coinbase: %v", err) } } // We should receive a notification for all three transactions // generated above. select { case <-time.After(time.Second * 5): t.Fatalf("transactions not received after 3 seconds") case <-unconfirmedNtfns: // Fall through on successs } confirmedNtfns := make(chan struct{}) go func() { for i := 0; i < numTxns; i++ { txDetail := <-txClient.ConfirmedTransactions() if txDetail.NumConfirmations != 1 { t.Fatalf("incorrect number of confs, expected %v got %v", 0, txDetail.NumConfirmations) } if txDetail.Value != outputAmt { t.Fatalf("incorrect output amt, expected %v got %v", outputAmt, txDetail.Value) } } close(confirmedNtfns) }() // Next mine a single block, all the transactions generated above // should be included. if _, err := miner.Node.Generate(1); err != nil { t.Fatalf("unable to generate block: %v", err) } // We should receive a notification for all three transactions // since they should be mined in the next block. select { case <-time.After(time.Second * 5): t.Fatalf("transactions not received after 3 seconds") case <-confirmedNtfns: // Fall through on successs } }