utils.rs 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. //! Utils
  2. use base64::{engine::general_purpose, Engine as _};
  3. use bitcoin::hashes::sha256::Hash as Sha256;
  4. use bitcoin::hashes::Hash;
  5. use rand::prelude::*;
  6. use regex::Regex;
  7. use crate::amount::Amount;
  8. /// Split amount into cashu denominations (powers of 2)
  9. pub fn split_amount(amount: Amount) -> Vec<Amount> {
  10. let mut chunks = Vec::new();
  11. let value = amount.to_sat();
  12. for i in 0..64 {
  13. let mask = 1 << i;
  14. if (value & mask) != 0 {
  15. chunks.push(Amount::from_sat(2u64.pow(i as u32)));
  16. }
  17. }
  18. chunks
  19. }
  20. pub fn extract_url_from_error(error: &str) -> Option<String> {
  21. let regex = Regex::new(r"https?://[^\s]+").unwrap();
  22. if let Some(capture) = regex.captures(error) {
  23. return Some(capture[0].to_owned());
  24. }
  25. None
  26. }
  27. /// Generate Secret Message
  28. pub fn generate_secret() -> String {
  29. let mut rng = rand::thread_rng();
  30. let mut secret = [0u8; 32];
  31. rng.fill_bytes(&mut secret);
  32. general_purpose::STANDARD.encode(secret)
  33. }
  34. pub fn random_hash() -> Vec<u8> {
  35. let mut rng = rand::thread_rng();
  36. let mut random_bytes = [0u8; Sha256::LEN];
  37. rng.fill_bytes(&mut random_bytes);
  38. let hash = Sha256::hash(&random_bytes);
  39. hash.to_byte_array().to_vec()
  40. }
  41. #[cfg(test)]
  42. mod tests {
  43. use super::*;
  44. #[test]
  45. fn test_split_amount() {
  46. assert_eq!(split_amount(Amount::from_sat(1)), vec![Amount::from_sat(1)]);
  47. assert_eq!(split_amount(Amount::from_sat(2)), vec![Amount::from_sat(2)]);
  48. assert_eq!(
  49. split_amount(Amount::from_sat(3)),
  50. vec![Amount::from_sat(1), Amount::from_sat(2)]
  51. );
  52. let amounts: Vec<Amount> = vec![1, 2, 8].iter().map(|a| Amount::from_sat(*a)).collect();
  53. assert_eq!(split_amount(Amount::from_sat(11)), amounts);
  54. let amounts: Vec<Amount> = vec![1, 2, 4, 8, 16, 32, 64, 128]
  55. .iter()
  56. .map(|a| Amount::from_sat(*a))
  57. .collect();
  58. assert_eq!(split_amount(Amount::from_sat(255)), amounts);
  59. }
  60. }