| Crates.io | sanctum-fee-ratio |
| lib.rs | sanctum-fee-ratio |
| version | 1.0.0 |
| created_at | 2025-03-30 07:47:57.085727+00 |
| updated_at | 2025-03-30 07:47:57.085727+00 |
| description | Abstractions over fees applied as ratios to u64 quantities. |
| homepage | |
| repository | https://github.com/igneous-labs/sanctum-token-ratio |
| max_upload_size | |
| id | 1612154 |
| size | 37,476 |
Abstractions over fees applied as ratios to u64 quantities.
Token amounts on Solana are most commonly u64s. A very common operation is applying a fee to a token amount. These fees are usually calculated by multiplying the token amount with a ratio <=1.0. The remaining amount after substracting this product is the amount after fees. This library seeks to provide generalized code that can be reused across multiple such contexts.
use sanctum_fee_ratio::{Fee, ratio::{Ceil, Ratio}};
type FeeCeil = Fee<Ceil<Ratio<u16, u16>>>;
struct BpsFeeCeil(FeeCeil);
impl BpsFeeCeil {
pub fn new(bps: u16) -> Option<Self> {
FeeCeil::new(Ratio { n: bps, d: 10_000 }).map(Self)
}
}
let four_bps_fee = BpsFeeCeil::new(4).unwrap();
let bef_fee = 1_000_000_001;
let aft_fee = four_bps_fee.0.apply(bef_fee).unwrap();
assert_eq!(aft_fee.rem(), 999_600_000);
assert_eq!(aft_fee.fee(), 400_001);
// bef_fee() performs rem() + fee() to get original amount before fee
assert_eq!(aft_fee.bef_fee(), bef_fee);
Uses [sanctum_u64_ratio]'s reverse() functionality to obtain a range of amount before fees from quantities after fees.
remCalling .apply() to any number in the returned range is guaranteed to return an [AftFee] with the same rem(), but it might not have the same fee()
use sanctum_fee_ratio::{Fee, ratio::{Ceil, Ratio}};
type FeeCeil = Fee<Ceil<Ratio<u64, u64>>>;
let fee = FeeCeil::new(Ratio { n: 1, d: 10 }).unwrap();
let bef_fee = 1_000_000_001;
let aft_fee = fee.apply(bef_fee).unwrap();
assert_eq!(aft_fee.rem(), 900_000_000);
assert_eq!(aft_fee.fee(), 100_000_001);
let range = fee.reverse_from_rem(aft_fee.rem()).unwrap();
// min results in a different fee, but max doesnt
let min = fee.apply(*range.start()).unwrap();
assert_eq!(min.rem(), aft_fee.rem());
assert_eq!(min.fee(), 100_000_000);
let max = fee.apply(*range.end()).unwrap();
assert_eq!(max.rem(), aft_fee.rem());
assert_eq!(max.fee(), 100_000_001);
feeCalling .apply() to any number in the returned range is guaranteed to return an [AftFee] with the same fee(), but it might not have the same rem()
use sanctum_fee_ratio::{Fee, ratio::{Floor, Ratio}};
type FeeFloor = Fee<Floor<Ratio<u64, u64>>>;
let fee = FeeFloor::new(Ratio { n: 1, d: 10 }).unwrap();
let bef_fee = 1_000_000_001;
let aft_fee = fee.apply(bef_fee).unwrap();
assert_eq!(aft_fee.rem(), 900_000_001);
assert_eq!(aft_fee.fee(), 100_000_000);
let range = fee.reverse_from_fee(aft_fee.fee()).unwrap();
// both min and max result in a different `rem()`
let min = fee.apply(*range.start()).unwrap();
assert_eq!(min.rem(), 900_000_000);
assert_eq!(min.fee(), aft_fee.fee());
let max = fee.apply(*range.end()).unwrap();
assert_eq!(max.rem(), 900_000_009);
assert_eq!(max.fee(), aft_fee.fee());