1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
use super::*;

/// Tool for generating, validating and parsing [BIP-0039](https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki) phrases in different supported languages.
#[wasm_bindgen(js_name = Bip39)]
#[derive(Clone, Debug)]
pub struct JsBip39 {
    inner: Bip39,
}

#[wasm_bindgen(js_class = Bip39)]
impl JsBip39 {
    /// Creates an object that can handle BIP39 phrases in a given language. (e.g. 'en')
    #[wasm_bindgen(constructor)]
    pub fn new(lang_code: &str) -> Result<JsBip39, JsValue> {
        let inner = Bip39::language_code(lang_code).map_err_to_js()?;
        Ok(Self { inner })
    }

    /// Creates a new phrase using the [CSPRNG](https://en.wikipedia.org/wiki/Cryptographically_secure_pseudorandom_number_generator)
    /// available on the platform.
    pub fn generate(&self) -> Result<JsBip39Phrase, JsValue> {
        let phrase = self.inner.generate();
        Ok(JsBip39Phrase::from(phrase))
    }

    /// Creates a new phrase using the 256 bits of entropy provided in a buffer. IOP encourages using 24 word phrases everywhere.
    #[wasm_bindgen(js_name = entropy)]
    pub fn entropy(&self, entropy: &[u8]) -> Result<JsBip39Phrase, JsValue> {
        let phrase = self.inner.entropy(entropy).map_err_to_js()?;
        Ok(JsBip39Phrase::from(phrase))
    }

    /// Creates a new phrase using the entropy provided in a buffer. This method is only for compatibility with other wallets. Check
    /// the BIP39 standard for the buffer sizes allowed.
    #[wasm_bindgen(js_name = shortEntropy)]
    pub fn short_entropy(&self, entropy: &[u8]) -> Result<JsBip39Phrase, JsValue> {
        let phrase = self.inner.short_entropy(entropy).map_err_to_js()?;
        Ok(JsBip39Phrase::from(phrase))
    }

    /// Validates a whole BIP39 mnemonic phrase. Because the phrase contains some checksum, the whole phrase can be invalid even when
    /// each word itself is valid. Note also, that the standards only allows NFKD normalization of Unicode codepoints, and a single
    /// space between words, but this library is more tolerant and provides normalization for those.
    #[wasm_bindgen(js_name = validatePhrase)]
    pub fn validate_phrase(&self, phrase: &str) -> Result<(), JsValue> {
        self.inner.validate(phrase).map_err_to_js()
    }

    /// Lists all words in the BIP39 dictionary, which start with the given prefix.
    ///
    /// Can be used in 3 different ways:
    /// - When the prefix is empty, the sorted list of all words are returned
    /// - When the prefix is a partial word, the returned list can be used for auto-completion
    /// - When the returned list is empty, the prefix is not a valid word in the dictionary
    #[wasm_bindgen(js_name = listWords)]
    pub fn list_words(&self, prefix: &str) -> Box<[JsValue]> {
        let words = self
            .inner
            .list_words(prefix)
            .iter()
            .map(|word| JsValue::from_str(word))
            .collect::<Vec<_>>();
        words.into_boxed_slice()
    }

    /// Validates a whole 24-word BIP39 mnemonic phrase and returns an intermediate object that can be
    /// later converted into a [`Seed`] with an optional password.
    pub fn phrase(&self, phrase: &str) -> Result<JsBip39Phrase, JsValue> {
        let phrase = self.inner.phrase(phrase).map_err_to_js()?;
        Ok(JsBip39Phrase::from(phrase))
    }

    #[wasm_bindgen(js_name = shortPhrase)]
    /// Validates a whole BIP39 mnemonic phrase and returns an intermediate object similar to {@link phrase}. This method is only for
    /// compatibility with other wallets. Check the BIP39 standard for the number of words allowed.
    pub fn short_phrase(&self, phrase: &str) -> Result<JsBip39Phrase, JsValue> {
        let phrase = self.inner.short_phrase(phrase).map_err_to_js()?;
        Ok(JsBip39Phrase::from(phrase))
    }
}

/// An intermediate object that represents a BIP39 phrase with a known language
#[wasm_bindgen(js_name = Bip39Phrase)]
pub struct JsBip39Phrase {
    inner: Bip39Phrase,
}

#[wasm_bindgen(js_class = Bip39Phrase)]
impl JsBip39Phrase {
    /// Creates a {@link Seed} from the phrase with the given password. Give empty string when the user did not provide any password.
    pub fn password(&self, password: &str) -> JsSeed {
        JsSeed::from(self.inner.password(password))
    }

    /// Returns the phrase as a readable string
    #[wasm_bindgen(getter = phrase)]
    pub fn phrase(&self) -> String {
        self.inner.as_phrase().to_string()
    }
}

impl From<Bip39Phrase> for JsBip39Phrase {
    fn from(inner: Bip39Phrase) -> Self {
        Self { inner }
    }
}

impl Wraps<Bip39Phrase> for JsBip39Phrase {
    fn inner(&self) -> &Bip39Phrase {
        &self.inner
    }
}