utils.rs 1.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445
  1. use base64::{engine::general_purpose, Engine as _};
  2. use bitcoin::Amount;
  3. use rand::prelude::*;
  4. /// Split amount into cashu denominations (powers of 2)
  5. pub fn split_amount(amount: Amount) -> Vec<Amount> {
  6. let mut chunks = Vec::new();
  7. let value = amount.to_sat();
  8. for i in 0..64 {
  9. let mask = 1 << i;
  10. if (value & mask) != 0 {
  11. chunks.push(Amount::from_sat(2u64.pow(i as u32)));
  12. }
  13. }
  14. chunks
  15. }
  16. pub fn generate_secret() -> String {
  17. let mut rng = rand::thread_rng();
  18. let mut secret = [0u8; 32];
  19. rng.fill_bytes(&mut secret);
  20. general_purpose::STANDARD.encode(secret)
  21. }
  22. #[cfg(test)]
  23. mod tests {
  24. use super::*;
  25. #[test]
  26. fn test_split_amount() {
  27. assert_eq!(split_amount(Amount::from_sat(1)), vec![Amount::from_sat(1)]);
  28. assert_eq!(split_amount(Amount::from_sat(2)), vec![Amount::from_sat(2)]);
  29. assert_eq!(
  30. split_amount(Amount::from_sat(3)),
  31. vec![Amount::from_sat(1), Amount::from_sat(2)]
  32. );
  33. let amounts: Vec<Amount> = vec![1, 2, 8].iter().map(|a| Amount::from_sat(*a)).collect();
  34. assert_eq!(split_amount(Amount::from_sat(11)), amounts);
  35. let amounts: Vec<Amount> = vec![1, 2, 4, 8, 16, 32, 64, 128]
  36. .iter()
  37. .map(|a| Amount::from_sat(*a))
  38. .collect();
  39. assert_eq!(split_amount(Amount::from_sat(255)), amounts);
  40. }
  41. }