code: func (m *wsNotificationManager) notifyForTxOuts(ops map[wire.OutPoint]map[chan struct{}]*wsClient,
  	addrs map[string]map[chan struct{}]*wsClient, tx *btcutil.Tx, block *btcutil.Block) {
  
  	// Nothing to do if nobody is listening for address notifications.
  	if len(addrs) == 0 {
  		return
  	}
  
  	txHex := ""
  	wscNotified := make(map[chan struct{}]struct{})
  	for i, txOut := range tx.MsgTx().TxOut {
  		_, txAddrs, _, err := txscript.ExtractPkScriptAddrs(
  			txOut.PkScript, m.server.cfg.ChainParams)
  		if err != nil {
  			continue
  		}
  
  		for _, txAddr := range txAddrs {
  			cmap, ok := addrs[txAddr.EncodeAddress()]
  			if !ok {
  				continue
  			}
  
  			if txHex == "" {
  				txHex = txHexString(tx.MsgTx())
  			}
  			ntfn := btcjson.NewRecvTxNtfn(txHex, blockDetails(block,
  				tx.Index()))
  
  			marshalledJSON, err := btcjson.MarshalCmd(nil, ntfn)
  			if err != nil {
  				rpcsLog.Errorf("Failed to marshal processedtx notification: %v", err)
  				continue
  			}
  
  			op := []*wire.OutPoint{wire.NewOutPoint(tx.Hash(), uint32(i))}
  			for wscQuit, wsc := range cmap {
  				m.addSpentRequests(ops, wsc, op)
  
  				if _, ok := wscNotified[wscQuit]; !ok {
  					wscNotified[wscQuit] = struct{}{}
  					wsc.QueueNotification(marshalledJSON)
  				}
  			}
  		}
  	}
  }
docs: // notifyForTxOuts examines each transaction output, notifying interested
  // websocket clients of the transaction if an output spends to a watched
  // address.  A spent notification request is automatically registered for
  // the client for each matching output.