iop_keyvault_wasm/
bip32.rs

1use super::*;
2
3/// Entry point to generate extended private keys in a hierarchical deterministic wallet starting from a seed based
4/// on the [BIP-0032](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki) standard
5/// (and the [SLIP-0010](https://github.com/satoshilabs/slips/blob/master/slip-0010.md) for crypto suites other than Secp256k1).
6#[wasm_bindgen(js_name = Bip32)]
7#[derive(Clone, Debug)]
8pub struct JsBip32;
9
10#[wasm_bindgen(js_class = Bip32)]
11impl JsBip32 {
12    /// Calculates the master extended private key based on the crypto suite used by the given network. (At the moment
13    /// only Secp256k1-based networks are supported in the WASM wrappers)
14    ///
15    /// @see allNetworkNames, validateNetworkName
16    pub fn master(seed: &JsSeed, name: &str) -> Result<JsBip32Node, JsValue> {
17        let network = Networks::by_name(name).map_err_to_js()?;
18        let node = Bip32.master(seed.inner(), network.subtree());
19        Ok(JsBip32Node::from(node))
20    }
21}
22
23/// In BIP-0032 each extended private key has the same operations, independently from the actual path. This struct represents such
24/// an extended private key in a given subtree.
25#[wasm_bindgen(js_name = Bip32Node)]
26#[derive(Clone, Debug)]
27pub struct JsBip32Node {
28    inner: Bip32Node<Secp256k1>,
29}
30
31#[wasm_bindgen(js_class = Bip32Node)]
32impl JsBip32Node {
33    /// Name of the network this node was generated for
34    #[wasm_bindgen(getter)]
35    pub fn network(&self) -> String {
36        self.inner.subtree().name().to_owned()
37    }
38
39    /// The BIP32 path of this node
40    #[wasm_bindgen(getter)]
41    pub fn path(&self) -> String {
42        self.inner.path().to_string()
43    }
44
45    /// Create a new node with normal (public) derivation with the given index.
46    #[wasm_bindgen(js_name = deriveNormal)]
47    pub fn derive_normal(&self, idx: i32) -> Result<JsBip32Node, JsValue> {
48        let child = self.inner.derive_normal(idx).map_err_to_js()?;
49        Ok(JsBip32Node::from(child))
50    }
51
52    /// Create a new node with hardened (private) derivation with the given index.
53    #[wasm_bindgen(js_name = deriveHardened)]
54    pub fn derive_hardened(&self, idx: i32) -> Result<JsBip32Node, JsValue> {
55        let child = self.inner.derive_hardened(idx).map_err_to_js()?;
56        Ok(JsBip32Node::from(child))
57    }
58
59    /// Creates the {@SecpPrivateKey} that belongs to this node for authenticating actions.
60    #[wasm_bindgen(js_name = privateKey)]
61    pub fn to_private_key(&self) -> JsSecpPrivateKey {
62        JsSecpPrivateKey::from(self.inner.private_key())
63    }
64
65    /// Removes the ability to sign and derive hardened keys. The public node it returns is still able to provide
66    /// normal derivation and signature verifications.
67    #[wasm_bindgen(js_name = neuter)]
68    pub fn neuter(&self) -> JsBip32PublicNode {
69        let inner = self.inner.neuter();
70        JsBip32PublicNode::from(inner)
71    }
72
73    // Secp specific methods...
74
75    /// Returns the extended private key in the BIP32 readable format with the version bytes of the network.
76    ///
77    /// This is a secret that must not be kept unencrypted in transit or in rest!
78    #[wasm_bindgen(js_name = toXprv)]
79    pub fn to_xprv(&self, name: &str) -> Result<String, JsValue> {
80        let network = Networks::by_name(name).map_err_to_js()?;
81        Ok(self.inner.to_xprv(network))
82    }
83
84    /// Returns the private key in the Wallet Import Format with the version byte of the network.
85    ///
86    /// This is a secret that must not be kept unencrypted in transit or in rest!
87    ///
88    /// @see SecpPrivateKey.toWif
89    #[wasm_bindgen(js_name = toWif)]
90    pub fn to_wif(&self, name: &str) -> Result<String, JsValue> {
91        let network = Networks::by_name(name).map_err_to_js()?;
92        Ok(self.inner.to_wif(network))
93    }
94}
95
96impl From<Bip32Node<Secp256k1>> for JsBip32Node {
97    fn from(inner: Bip32Node<Secp256k1>) -> Self {
98        Self { inner }
99    }
100}
101
102impl Wraps<Bip32Node<Secp256k1>> for JsBip32Node {
103    fn inner(&self) -> &Bip32Node<Secp256k1> {
104        &self.inner
105    }
106}
107
108/// In BIP-0032 a neutered extended private key is an extended public key. This object represents
109/// such an extended public key in a given subtree. It is able to do normal (public) derivation,
110/// signature verification, creating and validating key identifiers
111#[wasm_bindgen(js_name = Bip32PublicNode)]
112#[derive(Clone, Debug)]
113pub struct JsBip32PublicNode {
114    inner: Bip32PublicNode<Secp256k1>,
115}
116
117#[wasm_bindgen(js_class = Bip32PublicNode)]
118impl JsBip32PublicNode {
119    /// Name of the network this node was generated for
120    #[wasm_bindgen(getter)]
121    pub fn network(&self) -> String {
122        self.inner.subtree().name().to_owned()
123    }
124
125    /// The BIP32 path of this node
126    #[wasm_bindgen(getter)]
127    pub fn path(&self) -> String {
128        self.inner.path().to_string()
129    }
130
131    /// Create a new node with normal (public) derivation with the given index.
132    #[wasm_bindgen(js_name = deriveNormal)]
133    pub fn derive_normal(&self, idx: i32) -> Result<JsBip32PublicNode, JsValue> {
134        let child = self.inner.derive_normal(idx).map_err_to_js()?;
135        Ok(JsBip32PublicNode::from(child))
136    }
137
138    /// Creates the public key that belongs to this node for verifying authentications done by the corresponding private key.
139    #[wasm_bindgen(js_name = publicKey)]
140    pub fn to_public_key(&self) -> JsSecpPublicKey {
141        JsSecpPublicKey::from(self.inner.public_key())
142    }
143
144    /// Creates the key identifier for the public key. This is an extra layer of security for single-use keys, so the
145    /// revealing of the public key can be delayed to the point when the authenticated action (spending some coin or
146    /// revoking access) makes the public key irrelevant after the action is successful.
147    ///
148    /// Ark (and therefore Hydra) uses a different algorithm for calculating key identifiers. That is only available at
149    /// {@link SecpPublicKey.arkKeyId}
150    #[wasm_bindgen(js_name = keyId)]
151    pub fn to_key_id(&self) -> JsSecpKeyId {
152        JsSecpKeyId::from(self.inner.key_id())
153    }
154
155    // Secp specific methods...
156
157    /// Returns the extended public key in the BIP32 readable format with the version bytes of the network.
158    #[wasm_bindgen(js_name = toXpub)]
159    pub fn to_xpub(&self, name: &str) -> Result<String, JsValue> {
160        let network = Networks::by_name(name).map_err_to_js()?;
161        Ok(self.inner.to_xpub(network))
162    }
163
164    /// Returns the P2PKH address that belongs to this node using the version byte of the network.
165    #[wasm_bindgen(js_name = toP2pkh)]
166    pub fn to_p2pkh_addr(&self, name: &str) -> Result<String, JsValue> {
167        let network = Networks::by_name(name).map_err_to_js()?;
168        Ok(self.inner.to_p2pkh_addr(network))
169    }
170}
171
172impl From<Bip32PublicNode<Secp256k1>> for JsBip32PublicNode {
173    fn from(inner: Bip32PublicNode<Secp256k1>) -> Self {
174        Self { inner }
175    }
176}
177
178impl Wraps<Bip32PublicNode<Secp256k1>> for JsBip32PublicNode {
179    fn inner(&self) -> &Bip32PublicNode<Secp256k1> {
180        &self.inner
181    }
182}