Repository: bitcoin/bitcoin
File: src/common/messages.cpp (C++)

Code before:
        {FeeReason::PAYTXFEE, "PayTxFee set"},
        {FeeReason::FALLBACK, "Fallback fee"},
        {FeeReason::REQUIRED, "Minimum Required Fee"},
    };
    auto reason_string = fee_reason_strings.find(reason);

    if (reason_string == fee_reason_strings.end()) return "Unknown";

    return reason_string->second;
}

const std::vector<std::pair<std::string, FeeEstimateMode>>& FeeModeMap()
{
    static const std::vector<std::pair<std::string, FeeEstimateMode>> FEE_MODES = {
        {"unset", FeeEstimateMode::UNSET},
        {"economical", FeeEstimateMode::ECONOMICAL},
        {"conservative", FeeEstimateMode::CONSERVATIVE},
    };
    return FEE_MODES;
}

std::string FeeModes(const std::string& delimiter)
{
    return Join(FeeModeMap(), delimiter, [&](const std::pair<std::string, FeeEstimateMode>& i) { return i.first; });
}

std::string InvalidEstimateModeErrorMessage()
{
    return "Invalid estimate_mode parameter, must be one of: \"" + FeeModes("\", \"") + "\"";
}

bool FeeModeFromString(const std::string& mode_string, FeeEstimateMode& fee_estimate_mode)
{
    auto searchkey = ToUpper(mode_string);
    for (const auto& pair : FeeModeMap()) {
        if (ToUpper(pair.first) == searchkey) {
            fee_estimate_mode = pair.second;
            return true;
        }
    }
    return false;
}

bilingual_str PSBTErrorString(PSBTError err)
{
    switch (err) {
        case PSBTError::MISSING_INPUTS:
            return Untranslated("Inputs missing or spent");
        case PSBTError::SIGHASH_MISMATCH:
            return Untranslated("Specified sighash value does not match value stored in PSBT");
        case PSBTError::EXTERNAL_SIGNER_NOT_FOUND:

Review comment (security):
it might be useful to let the user know what the default is here

`unset: no mode set; default mode (economical) will be used.`

---

When using `bitcoin-cli sendtoaddress` I see the following snippit

```
8. estimate_mode            (string, optional, default="unset") The fee estimate mode, must be one of (case insensitive):
                            Available modes: "unset", "economical", "conservative"
                            unset: no mode set; default mode will be used.
                            Economical estimates use a shorter time horizon, making them more
                            responsive to short-term drops in the prevailing fee market. This mode
                            potentially returns a lower fee rate estimate.
                            Conservative estimates use a longer time horizon, making them
                            less responsive to short-term drops in the prevailing fee market. This mode
                            potentially returns a higher fee rate estimate.
```

Code after:
        {FeeReason::PAYTXFEE, "PayTxFee set"},
        {FeeReason::FALLBACK, "Fallback fee"},
        {FeeReason::REQUIRED, "Minimum Required Fee"},
    };
    auto reason_string = fee_reason_strings.find(reason);

    if (reason_string == fee_reason_strings.end()) return "Unknown";

    return reason_string->second;
}

const std::vector<std::pair<std::string, FeeEstimateMode>>& FeeModeMap()
{
    static const std::vector<std::pair<std::string, FeeEstimateMode>> FEE_MODES = {
        {"unset", FeeEstimateMode::UNSET},
        {"economical", FeeEstimateMode::ECONOMICAL},
        {"conservative", FeeEstimateMode::CONSERVATIVE},
    };
    return FEE_MODES;
}

std::string FeeModeInfo(const std::pair<std::string, FeeEstimateMode>& mode, std::string& default_info)
{
    switch (mode.second) {
        case FeeEstimateMode::UNSET:
            return strprintf("%s means no mode set (%s). \n", mode.first, default_info);
        case FeeEstimateMode::ECONOMICAL:
            return strprintf("%s estimates use a shorter time horizon, making them more\n"
                   "responsive to short-term drops in the prevailing fee market. This mode\n"
                   "potentially returns a lower fee rate estimate.\n", mode.first);
        case FeeEstimateMode::CONSERVATIVE:
            return strprintf("%s estimates use a longer time horizon, making them\n"
                   "less responsive to short-term drops in the prevailing fee market. This mode\n"
                   "potentially returns a higher fee rate estimate.\n", mode.first);
        default:
            // Other modes apart from the ones handled are fee rate units; they should not be clarified.
            assert(false);
    }
}

std::string FeeModesDetail(std::string default_info)
{
    std::string info;
    for (const auto& fee_mode : FeeModeMap()) {
        info += FeeModeInfo(fee_mode, default_info);
    }
    return strprintf("%s \n%s", FeeModes(", "), info);
}

std::string FeeModes(const std::string& delimiter)
{