The `Broadcast`/`ResendWalletTransactions` interface is strange:

- it's the node saying to the wallet "Try to submit your unconfirmed transactions to the mempool again"
- it's called in one place by the node, in `SendMessages()` here: https://github.com/bitcoin/bitcoin/blob/c033c4b5cef89a654e4d9d5c5f9bd823871b068b/src/net_processing.cpp#L3515. `SendMessages()` is called on the message handling thread on a loop.
- the actual scheduling of when the wallet sends messages is handled in the `ResendWalletTransactions()` function itself, using the `nNextResend` and `nLastResend` wallet globals (which could as easily be static variables in `ResendWalletTransactions()`).

Therefore the only use of `Broadcast()` is to periodically prod the wallet. The wallet itself decides whether it's time to resend transactions. This could be done by scheduling regular calls to `ResendWalletTransactions()`, in the same way that we schedule regular wallet flushes here: https://github.com/bitcoin/bitcoin/blob/c033c4b5cef89a654e4d9d5c5f9bd823871b068b/src/wallet/init.cpp#L215.

A couple of minor implementation details:

- the call to `Broadcast()` in `SendMessages()` is protected by an if statement `if (!fReindex && !fImporting && !IsInitialBlockDownload()) {`. Those tests could be moved into `ResendWalletTransactions()` (through the `Chain` interface).
- The `Broadcast` notification passes in the `nTimeBestReceived` time of the best block. That could be fetched by `ResendWalletTransactions()` through the `Chain` interface.
gArgs.AddArg("-walletdir=<dir>", "Specify directory to hold wallets (default: <datadir>/wallets if it exists, otherwise <datadir>)", false, OptionsCategory::WALLET);
    gArgs.AddArg("-walletnotify=<cmd>", "Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)", false, OptionsCategory::WALLET);
    gArgs.AddArg("-walletrbf", strprintf("Send transactions with full-RBF opt-in enabled (RPC only, default: %u)", DEFAULT_WALLET_RBF), false, OptionsCategory::WALLET);
    gArgs.AddArg("-zapwallettxes=<mode>", "Delete all wallet transactions and only recover those parts of the blockchain through -rescan on startup"
                               " (1 = keep tx meta data e.g. payment request information, 2 = drop tx meta data)", false, OptionsCategory::WALLET);
    gArgs.AddArg("-dblogsize=<n>", strprintf("Flush wallet database activity from memory to disk log every <n> megabytes (default: %u)", DEFAULT_WALLET_DBLOGSIZE), true, OptionsCategory::WALLET_DEBUG_TEST);
    gArgs.AddArg("-flushwallet", strprintf("Run a thread to flush wallet periodically (default: %u)", DEFAULT_FLUSHWALLET), true, OptionsCategory::WALLET_DEBUG_TEST);
    gArgs.AddArg("-privdb", strprintf("Sets the DB_PRIVATE flag in the wallet db environment (default: %u)", DEFAULT_WALLET_PRIVDB), true, OptionsCategory::WALLET_DEBUG_TEST);
    gArgs.AddArg("-walletrejectlongchains", strprintf("Wallet will not create transactions that violate mempool chain limits (default: %u)", DEFAULT_WALLET_REJECT_LONG_CHAINS), true, OptionsCategory::WALLET_DEBUG_TEST);
}
bool WalletInit::ParameterInteraction() const
{
    if (gArgs.GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET)) {
        for (const std::string& wallet : gArgs.GetArgs("-wallet")) {
            LogPrintf("%s: parameter interaction: -disablewallet -> ignoring -wallet=%s\n", __func__, wallet);
        }
        return true;
    }
    const bool is_multiwallet = gArgs.GetArgs("-wallet").size() > 1;
    if (gArgs.GetBoolArg("-blocksonly", DEFAULT_BLOCKSONLY) && gArgs.SoftSetBoolArg("-walletbroadcast", false)) {
        LogPrintf("%s: parameter interaction: -blocksonly=1 -> setting -walletbroadcast=0\n", __func__);
    }
    if (gArgs.GetBoolArg("-salvagewallet", false)) {
        if (is_multiwallet) {
            return InitError(strprintf("%s is only allowed with a single wallet file", "-salvagewallet"));
        }
        
        if (gArgs.SoftSetBoolArg("-rescan", true)) {
            LogPrintf("%s: parameter interaction: -salvagewallet=1 -> setting -rescan=1\n", __func__);
        }