| 1 |
|
| 2 |
|
| 3 |
|
| 4 |
pub fn stripe_timestamp(ts: i64) -> chrono::DateTime<chrono::Utc> { |
| 5 |
chrono::DateTime::from_timestamp(ts, 0).unwrap_or_else(chrono::Utc::now) |
| 6 |
} |
| 7 |
|
| 8 |
|
| 9 |
|
| 10 |
|
| 11 |
|
| 12 |
|
| 13 |
|
| 14 |
|
| 15 |
|
| 16 |
|
| 17 |
|
| 18 |
|
| 19 |
|
| 20 |
|
| 21 |
|
| 22 |
pub fn estimate_stripe_fee(price_cents: i32) -> (i32, i32) { |
| 23 |
if price_cents <= 0 { |
| 24 |
return (0, 0); |
| 25 |
} |
| 26 |
let fee = (price_cents as f64 * crate::constants::STRIPE_FEE_PERCENTAGE |
| 27 |
+ crate::constants::STRIPE_FEE_FIXED_CENTS) as i32; |
| 28 |
let creator_receives = (price_cents - fee).max(0); |
| 29 |
(fee.min(price_cents), creator_receives) |
| 30 |
} |
| 31 |
|
| 32 |
|
| 33 |
|
| 34 |
|
| 35 |
|
| 36 |
|
| 37 |
pub fn stripe_fee_estimate_applies(currency: crate::currency::SettlementCurrency) -> bool { |
| 38 |
currency == crate::currency::SettlementCurrency::Usd |
| 39 |
} |
| 40 |
|
| 41 |
#[cfg(test)] |
| 42 |
mod tests { |
| 43 |
use super::*; |
| 44 |
|
| 45 |
|
| 46 |
|
| 47 |
#[test] |
| 48 |
fn stripe_fee_standard_price() { |
| 49 |
let (fee, receives) = estimate_stripe_fee(1000); |
| 50 |
assert_eq!(fee, 59); |
| 51 |
assert_eq!(receives, 941); |
| 52 |
} |
| 53 |
|
| 54 |
#[test] |
| 55 |
fn stripe_fee_small_price() { |
| 56 |
let (fee, receives) = estimate_stripe_fee(100); |
| 57 |
assert_eq!(fee, 32); |
| 58 |
assert_eq!(receives, 68); |
| 59 |
} |
| 60 |
|
| 61 |
#[test] |
| 62 |
fn stripe_fee_zero_is_free() { |
| 63 |
let (fee, receives) = estimate_stripe_fee(0); |
| 64 |
assert_eq!(fee, 0); |
| 65 |
assert_eq!(receives, 0); |
| 66 |
} |
| 67 |
|
| 68 |
#[test] |
| 69 |
fn stripe_fee_negative_price() { |
| 70 |
let (fee, receives) = estimate_stripe_fee(-100); |
| 71 |
assert_eq!(fee, 0); |
| 72 |
assert_eq!(receives, 0); |
| 73 |
} |
| 74 |
|
| 75 |
#[test] |
| 76 |
fn stripe_fee_plus_receives_equals_price() { |
| 77 |
for price in [50, 100, 250, 500, 999, 1000, 2500, 5000, 10000, 50000] { |
| 78 |
let (fee, receives) = estimate_stripe_fee(price); |
| 79 |
assert_eq!( |
| 80 |
fee + receives, |
| 81 |
price, |
| 82 |
"fee + receives should equal price for {price} cents" |
| 83 |
); |
| 84 |
} |
| 85 |
} |
| 86 |
|
| 87 |
|
| 88 |
|
| 89 |
#[test] |
| 90 |
fn stripe_timestamp_zero() { |
| 91 |
assert_eq!(stripe_timestamp(0).timestamp(), 0); |
| 92 |
} |
| 93 |
|
| 94 |
#[test] |
| 95 |
fn stripe_timestamp_valid() { |
| 96 |
assert_eq!(stripe_timestamp(1_714_400_000).timestamp(), 1_714_400_000); |
| 97 |
} |
| 98 |
|
| 99 |
|
| 100 |
|
| 101 |
proptest::proptest! { |
| 102 |
#[test] |
| 103 |
fn prop_stripe_fee_invariant(price in 1..=1_000_000i32) { |
| 104 |
let (fee, receives) = estimate_stripe_fee(price); |
| 105 |
proptest::prop_assert_eq!(fee + receives, price, |
| 106 |
"fee ({}) + receives ({}) must equal price ({})", fee, receives, price); |
| 107 |
proptest::prop_assert!(fee > 0, "Fee should be positive for price {}", price); |
| 108 |
proptest::prop_assert!(receives >= 0, "Receives should be non-negative"); |
| 109 |
} |
| 110 |
} |
| 111 |
} |
| 112 |
|