mirror of
https://github.com/comit-network/xmr-btc-swap.git
synced 2025-12-15 08:38:58 -05:00
fix(cli, gui): Use 0-1 for address pool (#440)
This commit is contained in:
parent
11b891f530
commit
1587f63232
3 changed files with 32 additions and 20 deletions
|
|
@ -1623,7 +1623,7 @@ impl FfiWallet {
|
||||||
/// # Errors
|
/// # Errors
|
||||||
///
|
///
|
||||||
/// Returns an error if:
|
/// Returns an error if:
|
||||||
/// - Percentages don't sum to 100.0
|
/// - Percentages don't sum to 1.0
|
||||||
/// - Balance is zero
|
/// - Balance is zero
|
||||||
/// - There are more outputs than piconeros in balance
|
/// - There are more outputs than piconeros in balance
|
||||||
fn distribute(balance: monero::Amount, percentages: &[f64]) -> Result<Vec<monero::Amount>> {
|
fn distribute(balance: monero::Amount, percentages: &[f64]) -> Result<Vec<monero::Amount>> {
|
||||||
|
|
@ -1633,8 +1633,8 @@ impl FfiWallet {
|
||||||
|
|
||||||
const TOLERANCE: f64 = 1e-6;
|
const TOLERANCE: f64 = 1e-6;
|
||||||
let sum: f64 = percentages.iter().sum();
|
let sum: f64 = percentages.iter().sum();
|
||||||
if (sum - 100.0).abs() > TOLERANCE {
|
if (sum - 1.0).abs() > TOLERANCE {
|
||||||
bail!("Percentages must sum to 100 (actual sum: {})", sum);
|
bail!("Percentages must sum to 1 (actual sum: {})", sum);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle the case where distributable amount is zero
|
// Handle the case where distributable amount is zero
|
||||||
|
|
@ -1652,7 +1652,7 @@ impl FfiWallet {
|
||||||
|
|
||||||
// Distribute amounts according to ratios, except for the last one
|
// Distribute amounts according to ratios, except for the last one
|
||||||
for &percentage in &percentages[..percentages.len() - 1] {
|
for &percentage in &percentages[..percentages.len() - 1] {
|
||||||
let amount_pico = ((balance.as_pico() as f64) * percentage / 100.0).floor() as u64;
|
let amount_pico = ((balance.as_pico() as f64) * percentage).floor() as u64;
|
||||||
let amount = Amount::from_pico(amount_pico);
|
let amount = Amount::from_pico(amount_pico);
|
||||||
amounts.push(amount);
|
amounts.push(amount);
|
||||||
total += amount;
|
total += amount;
|
||||||
|
|
@ -1917,13 +1917,13 @@ mod tests {
|
||||||
return TestResult::discard();
|
return TestResult::discard();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure percentages are valid (non-negative and sum to approximately 100.0)
|
// Ensure percentages are valid (non-negative and sum to approximately 1.0)
|
||||||
if percentages.iter().any(|&p| p < 0.0 || p > 100.0) {
|
if percentages.iter().any(|&p| p < 0.0 || p > 1.0) {
|
||||||
return TestResult::discard();
|
return TestResult::discard();
|
||||||
}
|
}
|
||||||
|
|
||||||
let percentage_sum: f64 = percentages.iter().sum();
|
let percentage_sum: f64 = percentages.iter().sum();
|
||||||
if (percentage_sum - 100.0).abs() > 1e-6 {
|
if (percentage_sum - 1.0).abs() > 1e-6 {
|
||||||
return TestResult::discard();
|
return TestResult::discard();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1947,12 +1947,12 @@ mod tests {
|
||||||
return TestResult::discard();
|
return TestResult::discard();
|
||||||
}
|
}
|
||||||
|
|
||||||
if percentages.iter().any(|&p| p < 0.0 || p > 100.0) {
|
if percentages.iter().any(|&p| p < 0.0 || p > 1.0) {
|
||||||
return TestResult::discard();
|
return TestResult::discard();
|
||||||
}
|
}
|
||||||
|
|
||||||
let percentage_sum: f64 = percentages.iter().sum();
|
let percentage_sum: f64 = percentages.iter().sum();
|
||||||
if (percentage_sum - 100.0).abs() > 1e-6 {
|
if (percentage_sum - 1.0).abs() > 1e-6 {
|
||||||
return TestResult::discard();
|
return TestResult::discard();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1973,12 +1973,12 @@ mod tests {
|
||||||
return TestResult::discard();
|
return TestResult::discard();
|
||||||
}
|
}
|
||||||
|
|
||||||
if percentages.iter().any(|&p| p < 0.0 || p > 100.0) {
|
if percentages.iter().any(|&p| p < 0.0 || p > 1.0) {
|
||||||
return TestResult::discard();
|
return TestResult::discard();
|
||||||
}
|
}
|
||||||
|
|
||||||
let percentage_sum: f64 = percentages.iter().sum();
|
let percentage_sum: f64 = percentages.iter().sum();
|
||||||
if (percentage_sum - 100.0).abs() > 1e-6 {
|
if (percentage_sum - 1.0).abs() > 1e-6 {
|
||||||
return TestResult::discard();
|
return TestResult::discard();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1991,7 +1991,7 @@ mod tests {
|
||||||
let mut percentages_respected = true;
|
let mut percentages_respected = true;
|
||||||
for i in 0..percentages.len() - 1 {
|
for i in 0..percentages.len() - 1 {
|
||||||
let expected_amount =
|
let expected_amount =
|
||||||
((balance.as_pico() as f64) * percentages[i] / 100.0).floor() as u64;
|
((balance.as_pico() as f64) * percentages[i]).floor() as u64;
|
||||||
if amounts[i].as_pico() != expected_amount {
|
if amounts[i].as_pico() != expected_amount {
|
||||||
percentages_respected = false;
|
percentages_respected = false;
|
||||||
break;
|
break;
|
||||||
|
|
@ -2013,7 +2013,7 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_distribute_zero_balance() {
|
fn test_distribute_zero_balance() {
|
||||||
let balance = monero::Amount::from_pico(0);
|
let balance = monero::Amount::from_pico(0);
|
||||||
let percentages = vec![50.0, 50.0];
|
let percentages = vec![0.5, 0.5];
|
||||||
|
|
||||||
let amounts = FfiWallet::distribute(balance, &percentages);
|
let amounts = FfiWallet::distribute(balance, &percentages);
|
||||||
assert!(amounts.is_err());
|
assert!(amounts.is_err());
|
||||||
|
|
@ -2022,7 +2022,7 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_distribute_insufficient_balance_for_outputs() {
|
fn test_distribute_insufficient_balance_for_outputs() {
|
||||||
let balance = monero::Amount::from_pico(2);
|
let balance = monero::Amount::from_pico(2);
|
||||||
let percentages = vec![30.0, 30.0, 40.0]; // 3 outputs but only 2 piconeros
|
let percentages = vec![0.3, 0.3, 0.4]; // 3 outputs but only 2 piconeros
|
||||||
|
|
||||||
let amounts = FfiWallet::distribute(balance, &percentages);
|
let amounts = FfiWallet::distribute(balance, &percentages);
|
||||||
assert!(amounts.is_err());
|
assert!(amounts.is_err());
|
||||||
|
|
@ -2031,7 +2031,7 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_distribute_simple_case() {
|
fn test_distribute_simple_case() {
|
||||||
let balance = monero::Amount::from_pico(1000);
|
let balance = monero::Amount::from_pico(1000);
|
||||||
let percentages = vec![50.0, 30.0, 20.0];
|
let percentages = vec![0.5, 0.3, 0.2];
|
||||||
|
|
||||||
let amounts = FfiWallet::distribute(balance, &percentages).unwrap();
|
let amounts = FfiWallet::distribute(balance, &percentages).unwrap();
|
||||||
|
|
||||||
|
|
@ -2051,7 +2051,7 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_distribute_small_donation() {
|
fn test_distribute_small_donation() {
|
||||||
let balance = monero::Amount::from_pico(1000);
|
let balance = monero::Amount::from_pico(1000);
|
||||||
let percentages = vec![99.9, 0.1];
|
let percentages = vec![0.999, 0.001];
|
||||||
|
|
||||||
let amounts = FfiWallet::distribute(balance, &percentages).unwrap();
|
let amounts = FfiWallet::distribute(balance, &percentages).unwrap();
|
||||||
|
|
||||||
|
|
@ -2068,9 +2068,9 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_distribute_percentages_not_sum_to_100() {
|
fn test_distribute_percentages_not_sum_to_1() {
|
||||||
let balance = monero::Amount::from_pico(1000);
|
let balance = monero::Amount::from_pico(1000);
|
||||||
let percentages = vec![50.0, 30.0]; // Only sums to 80%
|
let percentages = vec![0.5, 0.3]; // Only sums to 0.8
|
||||||
|
|
||||||
let amounts = FfiWallet::distribute(balance, &percentages);
|
let amounts = FfiWallet::distribute(balance, &percentages);
|
||||||
assert!(amounts.is_err());
|
assert!(amounts.is_err());
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
-- Fix percentage values that are stored as 0-100 instead of 0-1
|
||||||
|
-- This migration converts percentage values for swap_ids where the sum > 1.0
|
||||||
|
-- by scaling all percentages for that swap_id by dividing by 100
|
||||||
|
UPDATE monero_addresses
|
||||||
|
SET percentage = percentage / 100.0
|
||||||
|
WHERE swap_id IN (
|
||||||
|
SELECT swap_id
|
||||||
|
FROM monero_addresses
|
||||||
|
GROUP BY swap_id
|
||||||
|
HAVING SUM(percentage) > 1.0
|
||||||
|
);
|
||||||
|
|
@ -307,7 +307,7 @@ impl MoneroAddressPool {
|
||||||
self.0.iter().map(|address| address.address()).collect()
|
self.0.iter().map(|address| address.address()).collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a vector of all percentages as f64 values.
|
/// Returns a vector of all percentages as f64 values (0-1 range).
|
||||||
pub fn percentages(&self) -> Vec<f64> {
|
pub fn percentages(&self) -> Vec<f64> {
|
||||||
self.0
|
self.0
|
||||||
.iter()
|
.iter()
|
||||||
|
|
@ -903,10 +903,11 @@ mod tests {
|
||||||
|
|
||||||
let address = "53gEuGZUhP9JMEBZoGaFNzhwEgiG7hwQdMCqFxiyiTeFPmkbt1mAoNybEUvYBKHcnrSgxnVWgZsTvRBaHBNXPa8tHiCU51a".parse().unwrap();
|
let address = "53gEuGZUhP9JMEBZoGaFNzhwEgiG7hwQdMCqFxiyiTeFPmkbt1mAoNybEUvYBKHcnrSgxnVWgZsTvRBaHBNXPa8tHiCU51a".parse().unwrap();
|
||||||
|
|
||||||
// Valid percentages should work
|
// Valid percentages should work (0-1 range)
|
||||||
assert!(LabeledMoneroAddress::new(address, Decimal::ZERO, "test".to_string()).is_ok());
|
assert!(LabeledMoneroAddress::new(address, Decimal::ZERO, "test".to_string()).is_ok());
|
||||||
assert!(LabeledMoneroAddress::new(address, Decimal::ONE, "test".to_string()).is_ok());
|
assert!(LabeledMoneroAddress::new(address, Decimal::ONE, "test".to_string()).is_ok());
|
||||||
assert!(LabeledMoneroAddress::new(address, Decimal::new(5, 1), "test".to_string()).is_ok()); // 0.5
|
assert!(LabeledMoneroAddress::new(address, Decimal::new(5, 1), "test".to_string()).is_ok()); // 0.5
|
||||||
|
assert!(LabeledMoneroAddress::new(address, Decimal::new(9925, 4), "test".to_string()).is_ok()); // 0.9925
|
||||||
|
|
||||||
// Invalid percentages should fail
|
// Invalid percentages should fail
|
||||||
assert!(
|
assert!(
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue