1use alloc::format;
4use alloc::string::String;
5use core::fmt;
6use core::str::FromStr;
7
8use kobe_primitives::ParseDerivationStyleError;
9
10#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
15#[non_exhaustive]
16pub enum KeyAlgo {
17 #[default]
21 Secp256k1,
22 Ed25519,
27}
28
29const ALL_ALGOS: &[KeyAlgo] = &[KeyAlgo::Secp256k1, KeyAlgo::Ed25519];
31
32const ACCEPTED_TOKENS: &[&str] = &["secp256k1", "secp", "ecdsa", "ed25519", "ed", "eddsa"];
34
35impl kobe_primitives::DerivationStyle for KeyAlgo {
36 fn path(self, index: u32) -> String {
37 match self {
38 Self::Secp256k1 => format!("m/44'/506'/0'/0/{index}"),
39 Self::Ed25519 => format!("m/44'/506'/0'/0'/{index}'"),
40 }
41 }
42
43 fn name(self) -> &'static str {
44 match self {
45 Self::Secp256k1 => "secp256k1",
46 Self::Ed25519 => "ed25519",
47 }
48 }
49
50 fn all() -> &'static [Self] {
51 ALL_ALGOS
52 }
53}
54
55impl fmt::Display for KeyAlgo {
56 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
57 f.write_str(<Self as kobe_primitives::DerivationStyle>::name(*self))
58 }
59}
60
61impl FromStr for KeyAlgo {
62 type Err = ParseDerivationStyleError;
63
64 fn from_str(s: &str) -> Result<Self, Self::Err> {
65 match s.to_lowercase().as_str() {
66 "secp256k1" | "secp" | "ecdsa" => Ok(Self::Secp256k1),
67 "ed25519" | "ed" | "eddsa" => Ok(Self::Ed25519),
68 _ => Err(ParseDerivationStyleError::new("casper", s, ACCEPTED_TOKENS)),
69 }
70 }
71}
72
73#[cfg(test)]
74#[allow(clippy::unwrap_used, reason = "unit tests")]
75mod tests {
76 use kobe_primitives::DerivationStyle as _;
77
78 use super::*;
79
80 #[test]
81 fn paths() {
82 assert_eq!(KeyAlgo::Secp256k1.path(0), "m/44'/506'/0'/0/0");
83 assert_eq!(KeyAlgo::Secp256k1.path(7), "m/44'/506'/0'/0/7");
84 assert_eq!(KeyAlgo::Ed25519.path(0), "m/44'/506'/0'/0'/0'");
85 assert_eq!(KeyAlgo::Ed25519.path(3), "m/44'/506'/0'/0'/3'");
86 }
87
88 #[test]
89 fn from_str_aliases() {
90 assert_eq!("secp256k1".parse::<KeyAlgo>().unwrap(), KeyAlgo::Secp256k1);
91 assert_eq!("SECP".parse::<KeyAlgo>().unwrap(), KeyAlgo::Secp256k1);
92 assert_eq!("ed25519".parse::<KeyAlgo>().unwrap(), KeyAlgo::Ed25519);
93 assert_eq!("ed".parse::<KeyAlgo>().unwrap(), KeyAlgo::Ed25519);
94 assert!("rsa".parse::<KeyAlgo>().is_err());
95 }
96
97 #[test]
98 fn default_is_secp() {
99 assert_eq!(KeyAlgo::default(), KeyAlgo::Secp256k1);
100 }
101}