docs: public TransactionBroadcast broadcastTransaction(final Transaction tx, final int minConnections) {
          // If we don't have a record of where this tx came from already, set it to be ourselves so Peer doesn't end up
          // redownloading it from the network redundantly.
          if (tx.getConfidence().getSource().equals(TransactionConfidence.Source.UNKNOWN)) {
              log.info("Transaction source unknown, setting to SELF: {}", tx.getTxId());
              tx.getConfidence().setSource(TransactionConfidence.Source.SELF);
          }
          final TransactionBroadcast broadcast = new TransactionBroadcast(this, tx);
          broadcast.setMinConnections(minConnections);
          // Send the TX to the wallet once we have a successful broadcast.
          Futures.addCallback(broadcast.future(), new FutureCallback<Transaction>() {
              @Override
              public void onSuccess(Transaction transaction) {
                  runningBroadcasts.remove(broadcast);
                  // OK, now tell the wallet about the transaction. If the wallet created the transaction then
                  // it already knows and will ignore this. If it's a transaction we received from
                  // somebody else via a side channel and are now broadcasting, this will put it into the
                  // wallet now we know it's valid.
                  for (Wallet wallet : wallets) {
                      // Assumption here is there are no dependencies of the created transaction.
                      //
                      // We may end up with two threads trying to do this in parallel - the wallet will
                      // ignore whichever one loses the race.
                      try {
                          wallet.receivePending(transaction, null);
                      } catch (VerificationException e) {
                          throw new RuntimeException(e);   // Cannot fail to verify a tx we created ourselves.
                      }
                  }
              }
  
              @Override
              public void onFailure(Throwable throwable) {
                  // This can happen if we get a reject message from a peer.
                  runningBroadcasts.remove(broadcast);
              }
          }, MoreExecutors.directExecutor());
          // Keep a reference to the TransactionBroadcast object. This is important because otherwise, the entire tree
          // of objects we just created would become garbage if the user doesn't hold on to the returned future, and
          // eventually be collected. This in turn could result in the transaction not being committed to the wallet
          // at all.
          runningBroadcasts.add(broadcast);
          broadcast.broadcast();
          return broadcast;
      }