ergo_lib_wasm/wallet/
derivation_path.rs

1//! Derivation path according to
2//! BIP-44 <https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki>
3//! and EIP-3 <https://github.com/ergoplatform/eips/blob/master/eip-0003.md>
4
5use derive_more::FromStr;
6use ergo_lib::wallet::derivation_path::ChildIndexError;
7use ergo_lib::wallet::derivation_path::ChildIndexHardened;
8use ergo_lib::wallet::derivation_path::ChildIndexNormal;
9use ergo_lib::wallet::derivation_path::DerivationPath as InnerDerivationPath;
10use wasm_bindgen::prelude::*;
11
12use crate::error_conversion::to_js;
13
14extern crate derive_more;
15use derive_more::{From, Into};
16
17/// According to
18/// BIP-44 <https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki>
19/// and EIP-3 <https://github.com/ergoplatform/eips/blob/master/eip-0003.md>
20#[wasm_bindgen]
21#[derive(PartialEq, Eq, Debug, Clone, From, Into, FromStr)]
22pub struct DerivationPath(InnerDerivationPath);
23
24#[wasm_bindgen]
25impl DerivationPath {
26    /// Create derivation path for a given account index (hardened) and address indices
27    /// `m / 44' / 429' / acc' / 0 / address[0] / address[1] / ...`
28    /// or `m / 44' / 429' / acc' / 0` if address indices are empty
29    /// change is always zero according to EIP-3
30    /// acc is expected as a 31-bit value (32th bit should not be set)
31    pub fn new(acc: u32, address_indices: &[u32]) -> Result<DerivationPath, JsValue> {
32        let acc = ChildIndexHardened::from_31_bit(acc).map_err(to_js)?;
33        let address_indices = address_indices
34            .iter()
35            .map(|i| ChildIndexNormal::normal(*i))
36            .collect::<Result<Vec<ChildIndexNormal>, ChildIndexError>>()
37            .map_err(to_js)?;
38        Ok(DerivationPath(InnerDerivationPath::new(
39            acc,
40            address_indices,
41        )))
42    }
43
44    /// Create root derivation path
45    pub fn master_path() -> Self {
46        DerivationPath(InnerDerivationPath::master_path())
47    }
48
49    /// Returns the length of the derivation path
50    pub fn depth(&self) -> usize {
51        self.0.depth()
52    }
53
54    /// Returns a new path with the last element of the deriviation path being increased, e.g. m/1/2 -> m/1/3
55    /// Returns an empty path error if the path is empty (master node)
56    pub fn next(&self) -> Result<DerivationPath, JsValue> {
57        Ok(self.0.next().map_err(to_js)?.into())
58    }
59
60    /// String representation of derivation path
61    /// E.g m/44'/429'/0'/0/1
62    #[wasm_bindgen(js_name = toString)]
63    #[allow(clippy::inherent_to_string)]
64    pub fn to_string(&self) -> String {
65        self.0.to_string()
66    }
67
68    /// Create a derivation path from a formatted string
69    /// E.g "m/44'/429'/0'/0/1"
70    pub fn from_string(path: &str) -> Result<DerivationPath, JsValue> {
71        Ok(path.parse::<InnerDerivationPath>().map_err(to_js)?.into())
72    }
73
74    /// For 0x21 Sign Transaction command of Ergo Ledger App Protocol
75    /// P2PK Sign (0x0D) instruction
76    /// Sign calculated TX hash with private key for provided BIP44 path.
77    /// Data:
78    ///
79    /// Field
80    /// Size (B)
81    /// Description
82    ///
83    /// BIP32 path length
84    /// 1
85    /// Value: 0x02-0x0A (2-10). Number of path components
86    ///
87    /// First derivation index
88    /// 4
89    /// Big-endian. Value: 44’
90    ///
91    /// Second derivation index
92    /// 4
93    /// Big-endian. Value: 429’ (Ergo coin id)
94    ///
95    /// Optional Third index
96    /// 4
97    /// Big-endian. Any valid bip44 hardened value.
98    /// ...
99    /// Optional Last index
100    /// 4
101    /// Big-endian. Any valid bip44 value.
102    ///
103    pub fn ledger_bytes(&self) -> Vec<u8> {
104        self.0.ledger_bytes()
105    }
106}