1fn has_character_count(s: &str, char_count: u64) -> bool {
3 s.chars().count() as u64 == char_count
4}
5
6pub fn is_p2pkh(address: &String) -> bool {
12 let p2pkh_leading_symbols = vec![
13 "1", "m", "n", ];
17
18 let has_p2pkh_leading_symbol = p2pkh_leading_symbols
19 .iter()
20 .any(|leading_symbol| address.starts_with(leading_symbol));
21 let has_correct_char_count =
22 has_character_count(address, 33) || has_character_count(address, 34);
23 has_correct_char_count && has_p2pkh_leading_symbol
24}
25pub fn is_p2sh(address: &String) -> bool {
33 let p2sh_leading_symbols = vec![
34 "2", "3", ];
37
38 let has_p2sh_leading_symbol = p2sh_leading_symbols
39 .iter()
40 .any(|leading_symbol| address.starts_with(leading_symbol));
41 let has_correct_char_count =
42 has_character_count(address, 34)
44 || has_character_count(address, 35);
46 has_correct_char_count && has_p2sh_leading_symbol
47}
48fn could_be_p2sh_p2wpkh(address: &String) -> bool {
56 is_p2sh(address)
57}
58fn could_be_p2sh_p2wsh(address: &String) -> bool {
67 is_p2sh(address)
68}
69pub fn is_p2wpkh(address: &String) -> bool {
77 let p2wpkh_leading_symbols = vec![
78 "bc1q", "tb1q", ];
81
82 let has_p2wpkh_leading_symbol = p2wpkh_leading_symbols
83 .iter()
84 .any(|leading_symbol| address.starts_with(leading_symbol));
85 has_character_count(address, 42) && has_p2wpkh_leading_symbol
86}
87pub fn is_p2wsh(address: &String) -> bool {
95 let p2wsh_leading_symbols = vec![
96 "bc1q", "tb1q", ];
99
100 let has_p2wsh_leading_symbol = p2wsh_leading_symbols
101 .iter()
102 .any(|leading_symbol| address.starts_with(leading_symbol));
103 has_character_count(address, 62) && has_p2wsh_leading_symbol
104}
105pub fn is_p2tr(address: &String) -> bool {
113 let p2tr_leading_symbols = vec![
114 "bc1p", "tb1p", ];
117
118 let has_p2tr_leading_symbol = p2tr_leading_symbols
119 .iter()
120 .any(|leading_symbol| address.starts_with(leading_symbol));
121 has_character_count(address, 62) && has_p2tr_leading_symbol
122}
123pub fn is_legacy(address: &String) -> bool {
126 is_p2pkh(address)
127}
128
129pub fn is_nested_segwit(address: &String) -> bool {
130 is_p2sh(address)
131}
132pub fn is_wrapped_segwit(address: &String) -> bool {
134 is_nested_segwit(address)
135}
136
137pub fn is_segwit_native(address: &String) -> bool {
138 is_p2wpkh(address) || is_p2wsh(address)
139}
140
141pub fn is_segwit_v0(address: &String) -> bool {
142 is_segwit_native(address) || is_p2sh(address)
143}
144pub fn is_segwit_v1(address: &String) -> bool {
145 is_taproot(address)
146}
147
148pub fn is_taproot(address: &String) -> bool {
149 is_p2tr(address)
150}
151
152#[cfg(test)]
154mod tests {
155 use super::*;
156
157 #[test]
158 fn is_legacy_works() {
159 let legacy_address = "1J9uwBYepTm5737RtzkSEePTevGgDGLP5S".to_string();
160 let nested_segwit_address = "37u4L57bLqZ8NL9bs1GNX2x52KxviDfvPp".to_string();
161 let native_segwit_address = "bc1qfvmj8jse4r7203mrchfyt24sjcpna3s2y35ylp".to_string();
162 let taproot_address =
163 "bc1p8denc9m4sqe9hluasrvxkkdqgkydrk5ctxre5nkk4qwdvefn0sdsc6eqxe".to_string();
164
165 assert_eq!(is_legacy(&legacy_address), true);
166 assert_eq!(is_legacy(&nested_segwit_address), false);
167 assert_eq!(is_legacy(&native_segwit_address), false);
168 assert_eq!(is_legacy(&taproot_address), false);
169
170 assert_eq!(is_nested_segwit(&nested_segwit_address), true);
171 assert_eq!(is_nested_segwit(&legacy_address), false);
172 assert_eq!(is_nested_segwit(&native_segwit_address), false);
173 assert_eq!(is_nested_segwit(&taproot_address), false);
174
175 assert_eq!(is_segwit_native(&native_segwit_address), true);
176 assert_eq!(is_segwit_native(&legacy_address), false);
177 assert_eq!(is_segwit_native(&nested_segwit_address), false);
178 assert_eq!(is_segwit_native(&taproot_address), false);
179
180 assert_eq!(is_segwit_v0(&nested_segwit_address), true);
181 assert_eq!(is_segwit_v0(&native_segwit_address), true);
182 assert_eq!(is_segwit_v0(&taproot_address), false);
183
184 assert_eq!(is_segwit_v1(&nested_segwit_address), false);
185 assert_eq!(is_segwit_v1(&native_segwit_address), false);
186 assert_eq!(is_segwit_v1(&taproot_address), true);
187
188 assert_eq!(is_taproot(&taproot_address), true);
189 assert_eq!(is_taproot(&legacy_address), false);
190 assert_eq!(is_taproot(&nested_segwit_address), false);
191 assert_eq!(is_taproot(&native_segwit_address), false);
192 }
193}