solana_tokens/
token_display.rs

1use {
2    solana_account_decoder::parse_token::real_number_string_trimmed,
3    solana_cli_output::display::build_balance_message,
4    std::{
5        fmt::{Debug, Display, Formatter, Result},
6        ops::Add,
7    },
8};
9
10const SOL_SYMBOL: &str = "◎";
11
12#[derive(PartialEq, Eq)]
13pub enum TokenType {
14    Sol,
15    SplToken,
16}
17
18pub struct Token {
19    amount: u64,
20    decimals: u8,
21    token_type: TokenType,
22}
23
24impl Token {
25    fn write_with_symbol(&self, f: &mut Formatter) -> Result {
26        match &self.token_type {
27            TokenType::Sol => {
28                let amount = build_balance_message(self.amount, false, false);
29                write!(f, "{SOL_SYMBOL}{amount}")
30            }
31            TokenType::SplToken => {
32                let amount = real_number_string_trimmed(self.amount, self.decimals);
33                write!(f, "{amount} tokens")
34            }
35        }
36    }
37
38    pub fn sol(amount: u64) -> Self {
39        Self {
40            amount,
41            decimals: 9,
42            token_type: TokenType::Sol,
43        }
44    }
45
46    pub fn spl_token(amount: u64, decimals: u8) -> Self {
47        Self {
48            amount,
49            decimals,
50            token_type: TokenType::SplToken,
51        }
52    }
53}
54
55impl Display for Token {
56    fn fmt(&self, f: &mut Formatter) -> Result {
57        self.write_with_symbol(f)
58    }
59}
60
61impl Debug for Token {
62    fn fmt(&self, f: &mut Formatter) -> Result {
63        self.write_with_symbol(f)
64    }
65}
66
67impl Add for Token {
68    type Output = Token;
69
70    fn add(self, other: Self) -> Self {
71        if self.token_type == other.token_type {
72            Self {
73                amount: self.amount + other.amount,
74                decimals: self.decimals,
75                token_type: self.token_type,
76            }
77        } else {
78            self
79        }
80    }
81}