white_whale_std/pool_network/
token.rs1use cosmwasm_schema::cw_serde;
2use cosmwasm_std::{StdError, StdResult, Uint128};
3use cw20::{Cw20Coin, MinterResponse};
4
5#[cw_serde]
7pub struct InstantiateMsg {
8 pub name: String,
9 pub symbol: String,
10 pub decimals: u8,
11 pub initial_balances: Vec<Cw20Coin>,
12 pub mint: Option<MinterResponse>,
13}
14
15impl InstantiateMsg {
16 pub fn get_cap(&self) -> Option<Uint128> {
17 self.mint.as_ref().and_then(|v| v.cap)
18 }
19
20 pub fn validate(&self) -> StdResult<()> {
21 if !is_valid_name(&self.name) {
23 return Err(StdError::generic_err(
24 "Name is not in the expected format (3-50 UTF-8 bytes)",
25 ));
26 }
27 if !is_valid_symbol(&self.symbol) {
28 return Err(StdError::generic_err(
29 "Ticker symbol is not in expected format [a-zA-Z\\-]{3,12}",
30 ));
31 }
32 if self.decimals > 18 {
33 return Err(StdError::generic_err("Decimals must not exceed 18"));
34 }
35 Ok(())
36 }
37}
38
39fn is_valid_name(name: &str) -> bool {
40 let bytes = name.as_bytes();
41 if bytes.len() < 3 || bytes.len() > 50 {
42 return false;
43 }
44 true
45}
46
47fn is_valid_symbol(symbol: &str) -> bool {
48 let bytes = symbol.as_bytes();
49 if bytes.len() < 3 || bytes.len() > 12 {
50 return false;
51 }
52 for byte in bytes.iter() {
53 if (*byte != 45) && (*byte < 65 || *byte > 90) && (*byte < 97 || *byte > 122) {
54 return false;
55 }
56 }
57 true
58}
59
60#[cfg(test)]
61mod test {
62 use super::*;
63
64 #[test]
65 fn get_cap() {
66 let msg = InstantiateMsg {
67 decimals: 6u8,
68 initial_balances: vec![],
69 mint: Some(MinterResponse {
70 cap: Some(Uint128::from(1u128)),
71 minter: "minter0000".to_string(),
72 }),
73 name: "test_token".to_string(),
74 symbol: "TNT".to_string(),
75 };
76
77 assert_eq!(msg.get_cap(), Some(Uint128::from(1u128)))
78 }
79
80 #[test]
81 fn validate() {
82 let valid_msg = InstantiateMsg {
83 decimals: 6u8,
84 initial_balances: vec![],
85 mint: Some(MinterResponse {
86 cap: Some(Uint128::from(1u128)),
87 minter: "minter0000".to_string(),
88 }),
89 name: "test_token".to_string(),
90 symbol: "TNT".to_string(),
91 };
92
93 assert_eq!(valid_msg.validate(), Ok(()));
94
95 let name_invalid_msg = InstantiateMsg {
96 decimals: 6u8,
97 initial_balances: vec![],
98 mint: Some(MinterResponse {
99 cap: Some(Uint128::from(1u128)),
100 minter: "minter0000".to_string(),
101 }),
102 name: "a".to_string(),
103 symbol: "TNT".to_string(),
104 };
105
106 assert_eq!(
107 name_invalid_msg.validate(),
108 Err(StdError::generic_err(
109 "Name is not in the expected format (3-50 UTF-8 bytes)",
110 ))
111 );
112
113 let symbol_invalid_msg = InstantiateMsg {
114 decimals: 6u8,
115 initial_balances: vec![],
116 mint: Some(MinterResponse {
117 cap: Some(Uint128::from(1u128)),
118 minter: "minter0000".to_string(),
119 }),
120 name: "test_token".to_string(),
121 symbol: "TN".to_string(),
122 };
123
124 assert_eq!(
125 symbol_invalid_msg.validate(),
126 Err(StdError::generic_err(
127 "Ticker symbol is not in expected format [a-zA-Z\\-]{3,12}",
128 ))
129 );
130
131 let decimal_invalid_msg = InstantiateMsg {
132 decimals: 20u8,
133 initial_balances: vec![],
134 mint: Some(MinterResponse {
135 cap: Some(Uint128::from(1u128)),
136 minter: "minter0000".to_string(),
137 }),
138 name: "test_token".to_string(),
139 symbol: "TNT".to_string(),
140 };
141
142 assert_eq!(
143 decimal_invalid_msg.validate(),
144 Err(StdError::generic_err("Decimals must not exceed 18"))
145 );
146 }
147}