lwk/
mnemonic.rs

1use std::{fmt::Display, str::FromStr, sync::Arc};
2
3use lwk_signer::bip39;
4
5use crate::LwkError;
6
7/// Wrapper over [`bip39::Mnemonic`]
8#[derive(uniffi::Object, PartialEq, Eq, Debug)]
9#[uniffi::export(Display)]
10pub struct Mnemonic {
11    inner: bip39::Mnemonic,
12}
13
14impl From<bip39::Mnemonic> for Mnemonic {
15    fn from(inner: bip39::Mnemonic) -> Self {
16        Self { inner }
17    }
18}
19
20impl Display for Mnemonic {
21    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
22        write!(f, "{}", self.inner)
23    }
24}
25
26#[uniffi::export]
27impl Mnemonic {
28    /// Construct a Mnemonic type
29    #[uniffi::constructor]
30    pub fn new(s: &str) -> Result<Arc<Self>, LwkError> {
31        let inner = bip39::Mnemonic::from_str(s)?;
32        Ok(Arc::new(Self { inner }))
33    }
34
35    /// Creates a Mnemonic from entropy, at least 16 bytes are needed.
36    #[uniffi::constructor]
37    pub fn from_entropy(b: &[u8]) -> Result<Arc<Self>, LwkError> {
38        let inner = bip39::Mnemonic::from_entropy(b)?;
39        Ok(Arc::new(Self { inner }))
40    }
41
42    /// Creates a random Mnemonic of given words (12,15,18,21,24)
43    #[uniffi::constructor]
44    pub fn from_random(word_count: u8) -> Result<Arc<Self>, LwkError> {
45        let inner = bip39::Mnemonic::generate(word_count as usize)?;
46        Ok(Arc::new(Self { inner }))
47    }
48}
49
50#[cfg(test)]
51mod tests {
52    use crate::Mnemonic;
53    use lwk_signer::bip39;
54    use std::str::FromStr;
55
56    #[test]
57    fn mnemonic() {
58        let mnemonic_str = lwk_test_util::TEST_MNEMONIC;
59        let mnemonic_bip39 = bip39::Mnemonic::from_str(mnemonic_str).unwrap();
60        let from_bip39: Mnemonic = mnemonic_bip39.into();
61        let mnemonic = Mnemonic::new(mnemonic_str).unwrap();
62        assert_eq!(mnemonic_str, mnemonic.to_string());
63        assert_eq!(from_bip39, *mnemonic);
64
65        let rand_mnemonic = Mnemonic::from_random(12).unwrap();
66        assert_ne!(mnemonic, rand_mnemonic);
67
68        let entropy = rand_mnemonic.inner.to_entropy();
69        let entropy_mnemonic = Mnemonic::from_entropy(&entropy).unwrap();
70        assert_eq!(entropy_mnemonic, rand_mnemonic);
71    }
72}