fix: parse fee rate with the invariant culture

On Italian/German systems "1.5" was read as 15 sat/vB. The Send form,
the Donate form and the CLI now share CoinAmount.TryParseFeeRate
(invariant culture, '.' or ',' as decimal separator, range (0, 1000]).
Donate and the CLI report an invalid rate instead of silently using 1.
This commit is contained in:
davide committed 2026-11-03 12:15:27 +01:00
1 parent d431996ddc
commit cb551efce4
7 files changed
+99 -7

No files matched your search

@@ -44,9 +44,11 @@ public partial class MainWindowViewModel
DonatePreview = Loc.Tr("msg.amount.invalid");
return;
}
if (!decimal.TryParse(SendFeeRate, System.Globalization.NumberStyles.Any,
System.Globalization.CultureInfo.InvariantCulture, out var feeRate) || feeRate <= 0)
feeRate = 1m;
if (!CoinAmount.TryParseFeeRate(SendFeeRate, out var feeRate))
{
DonatePreview = Loc.Tr("msg.feerate.invalid");
return;
}
_pendingDonate = new TransactionFactory(_account).Build(
_doc.Cache.Utxos, _lastTransactions, destination, amount, feeRate,
@@ -74,7 +74,7 @@ public partial class MainWindowViewModel
SendPreview = Loc.Tr("msg.amount.invalid");
return;
}
if (!decimal.TryParse(SendFeeRate, out var feeRate) || feeRate <= 0)
if (!CoinAmount.TryParseFeeRate(SendFeeRate, out var feeRate))
{
SendPreview = Loc.Tr("msg.feerate.invalid");
return;
+3 -1
View File
@@ -217,7 +217,9 @@ static async Task<int> Send(string[] o)
long amount = 0;
if (!sendAll && !CoinAmount.TryParseCoins(Opt(o, "--amount") ?? "", out amount))
throw new WalletSpendException("--amount missing or invalid (or use --all).");
var feeRate = decimal.TryParse(Opt(o, "--feerate"), out var fr) ? fr : 1m;
var feeRate = 1m;
if (Opt(o, "--feerate") is { } feeText && !CoinAmount.TryParseFeeRate(feeText, out feeRate))
throw new WalletSpendException($"--feerate invalid (expected sat/vB in (0, {CoinAmount.MaxFeeRate}]).");
// Source transactions of the UTXOs: needed for amounts and signing.
await using var client = await Connect(o, account.Profile);
+21
View File
@@ -80,4 +80,25 @@ public static class CoinAmount
}
return true;
}
/// <summary>Upper bound accepted for a fee rate, in sat/vB (guards against typos).</summary>
public const decimal MaxFeeRate = 1000m;
/// <summary>
/// Parses a fee rate in sat/vB, independent of the system culture. Accepts a decimal point or
/// comma; rejects thousands separators, exponents, signs, zero and values above
/// <see cref="MaxFeeRate"/>.
/// </summary>
public static bool TryParseFeeRate(string? text, out decimal satPerVbyte)
{
satPerVbyte = 0;
if (text is null)
return false;
text = text.Trim().Replace(',', '.');
if (!decimal.TryParse(text, NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out var rate)
|| rate <= 0 || rate > MaxFeeRate)
return false;
satPerVbyte = rate;
return true;
}
}