hiero_sdk/key/
key_list.rs1use hiero_sdk_proto::services;
2
3use crate::protobuf::{
4 FromProtobuf,
5 ToProtobuf,
6};
7use crate::Key;
8
9#[derive(Clone, Eq, PartialEq, Hash, Debug, Default)]
13pub struct KeyList {
14 pub keys: Vec<Key>,
17
18 pub threshold: Option<u32>,
20}
21
22impl std::ops::Deref for KeyList {
23 type Target = Vec<Key>;
24
25 fn deref(&self) -> &Self::Target {
26 &self.keys
27 }
28}
29
30impl std::ops::DerefMut for KeyList {
31 fn deref_mut(&mut self) -> &mut Self::Target {
32 &mut self.keys
33 }
34}
35
36impl KeyList {
37 #[must_use]
39 pub fn new() -> Self {
40 Self::default()
41 }
42
43 #[must_use]
45 pub fn is_empty(&self) -> bool {
46 self.keys.is_empty()
47 }
48
49 pub fn remove(&mut self, index: usize) -> Key {
54 self.keys.remove(index)
55 }
56
57 pub(crate) fn to_protobuf_key(&self) -> services::key::Key {
59 let key_list = services::KeyList { keys: self.keys.to_protobuf() };
60
61 if let Some(threshold) = self.threshold {
62 return services::key::Key::ThresholdKey(services::ThresholdKey {
63 threshold,
64 keys: Some(key_list),
65 });
66 };
67
68 services::key::Key::KeyList(key_list)
69 }
70}
71
72impl ToProtobuf for KeyList {
73 type Protobuf = services::KeyList;
74
75 fn to_protobuf(&self) -> Self::Protobuf {
76 services::KeyList { keys: self.keys.to_protobuf() }
77 }
78}
79
80impl FromIterator<Key> for KeyList {
81 fn from_iter<T: IntoIterator<Item = Key>>(iter: T) -> Self {
82 Self { keys: Vec::from_iter(iter), threshold: None }
83 }
84}
85
86impl From<Vec<Key>> for KeyList {
87 fn from(value: Vec<Key>) -> Self {
88 Self { keys: value, threshold: None }
89 }
90}
91
92impl<T: Into<Key>, const N: usize> From<[T; N]> for KeyList {
93 fn from(value: [T; N]) -> Self {
94 value.into_iter().map(Into::into).collect()
95 }
96}
97
98impl FromProtobuf<services::KeyList> for KeyList {
99 fn from_protobuf(pb: services::KeyList) -> crate::Result<Self>
100 where
101 Self: Sized,
102 {
103 Vec::from_protobuf(pb.keys).map(Self::from)
104 }
105}
106
107impl FromProtobuf<services::ThresholdKey> for KeyList {
108 fn from_protobuf(pb: services::ThresholdKey) -> crate::Result<Self>
109 where
110 Self: Sized,
111 {
112 let keys = Vec::from_protobuf(pb.keys.unwrap_or_default().keys)?;
113 Ok(Self { keys, threshold: Some(pb.threshold) })
114 }
115}
116
117#[cfg(test)]
118mod tests {
119 use assert_matches::assert_matches;
120 use hiero_sdk_proto::services;
121
122 use crate::protobuf::{
123 FromProtobuf,
124 ToProtobuf,
125 };
126 use crate::{
127 KeyList,
128 PrivateKey,
129 PublicKey,
130 };
131
132 fn keys() -> [PublicKey; 3] {
133 let key1 = PrivateKey::from_str_ed25519(
134 "302e020100300506032b657004220420db484b828e64b2d8f12ce3c0a0e93a0b8cce7af1bb8f39c97732394482538e10").unwrap()
135 .public_key();
136
137 let key2 = PrivateKey::from_str_ed25519(
138 "302e020100300506032b657004220420db484b828e64b2d8f12ce3c0a0e93a0b8cce7af1bb8f39c97732394482538e11").unwrap()
139 .public_key();
140
141 let key3 = PrivateKey::from_str_ed25519(
142 "302e020100300506032b657004220420db484b828e64b2d8f12ce3c0a0e93a0b8cce7af1bb8f39c97732394482538e12").unwrap()
143 .public_key();
144
145 [key1, key2, key3]
146 }
147
148 #[test]
149 fn from_protobuf() {
150 let key_list_pb =
151 services::KeyList { keys: keys().iter().map(|it| it.to_protobuf()).collect() };
152
153 let key_list = KeyList::from_protobuf(key_list_pb).unwrap();
154
155 assert!(keys().iter().all(|it| key_list.contains(&crate::Key::Single(*it))));
156 }
157
158 #[test]
159 fn to_protobuf_key() {
160 let key_list = KeyList::from(keys());
161
162 let proto_key = key_list.to_protobuf_key();
163
164 let proto_key_list = assert_matches!(proto_key, services::key::Key::KeyList(it) => it);
165
166 for (actual, expected) in proto_key_list.keys.iter().zip(keys()) {
167 assert_eq!(actual, &expected.to_protobuf());
168 }
169 }
170
171 #[test]
172 fn to_protobuf() {
173 let key_list = KeyList::from(keys());
174
175 let proto_key_list = key_list.to_protobuf();
176
177 for (actual, expected) in proto_key_list.keys.iter().zip(keys()) {
178 assert_eq!(actual, &expected.to_protobuf());
179 }
180 }
181
182 #[test]
183 fn len() {
184 let key_list = KeyList::from(keys());
185 let empty_key_list = KeyList::new();
186
187 assert_eq!(key_list.len(), 3);
188 assert!(!key_list.is_empty());
189 assert_eq!(empty_key_list.len(), 0);
190 assert!(empty_key_list.is_empty());
191 }
192
193 #[test]
194 fn contains() {
195 let key_list = KeyList::from(keys());
198 let empty_key_list = KeyList::new();
199
200 assert!(keys().iter().all(|it| key_list.contains(&crate::Key::Single(*it))));
201 assert!(!keys().iter().any(|it| empty_key_list.contains(&crate::Key::Single(*it))));
202 }
203
204 #[test]
205 fn push() {
206 let [a, b, c] = keys();
207
208 let mut key_list = KeyList::from([a, b]);
209
210 key_list.push(c.into());
211
212 assert_eq!(key_list.len(), 3);
213
214 assert!(key_list.contains(&c.into()));
215 }
216
217 #[test]
218 fn remove() {
219 let keys = keys();
220 let mut key_list = KeyList::from(keys);
221
222 let _ = key_list.remove(0);
223
224 assert_eq!(key_list.len(), 2);
225
226 assert!(!key_list.contains(&keys[0].into()));
227 assert!(key_list.contains(&keys[1].into()));
228 assert!(key_list.contains(&keys[2].into()));
229 }
230
231 #[test]
232 fn clear() {
233 let mut key_list = KeyList::from(keys());
234
235 key_list.clear();
236
237 assert!(key_list.is_empty());
238 }
239}