scemadex_sdk/
primitives.rs1use serde::{Deserialize, Serialize};
2
3use crate::error::{Result, ScemaDexError};
4
5#[derive(Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
11pub struct Address(String);
12
13impl Address {
14 pub fn new(s: impl Into<String>) -> Result<Self> {
16 let s = s.into();
17 match bs58::decode(&s).into_vec() {
18 Ok(bytes) if bytes.len() == 32 => Ok(Self(s)),
19 _ => Err(ScemaDexError::InvalidAddress(s)),
20 }
21 }
22
23 pub fn as_str(&self) -> &str {
24 &self.0
25 }
26}
27
28impl std::fmt::Display for Address {
29 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
30 f.write_str(&self.0)
31 }
32}
33
34impl std::fmt::Debug for Address {
35 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
36 write!(f, "Address({})", self.0)
37 }
38}
39
40#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
42pub struct Amount {
43 pub raw: u64,
44 pub decimals: u8,
45}
46
47impl Amount {
48 pub fn new(raw: u64, decimals: u8) -> Self {
49 Self { raw, decimals }
50 }
51
52 pub fn ui(&self) -> f64 {
54 self.raw as f64 / 10f64.powi(self.decimals as i32)
55 }
56}
57
58#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
61pub struct Usdc(pub u64);
62
63impl Usdc {
64 pub fn from_usdc(v: f64) -> Self {
65 Self((v * 1_000_000.0) as u64)
66 }
67
68 pub fn as_usdc(&self) -> f64 {
69 self.0 as f64 / 1_000_000.0
70 }
71}
72
73#[cfg(test)]
74mod tests {
75 use super::*;
76
77 #[test]
78 fn rejects_non_base58_address() {
79 assert!(Address::new("not-an-address!!").is_err());
80 }
81
82 #[test]
83 fn accepts_valid_mint() {
84 assert!(Address::new("So11111111111111111111111111111111111111112").is_ok());
85 }
86
87 #[test]
88 fn amount_ui_scales_by_decimals() {
89 assert_eq!(Amount::new(1_500_000_000, 9).ui(), 1.5);
90 }
91
92 #[test]
93 fn usdc_round_trips() {
94 assert_eq!(Usdc::from_usdc(2.5).as_usdc(), 2.5);
95 }
96}