ergo_lib_c_core/
derivation_path.rs

1//! Derivation Path functionality
2
3use crate::util::const_ptr_as_ref;
4use crate::{util::mut_ptr_as_mut, Error};
5use derive_more::{From, Into};
6use ergo_lib::wallet;
7use ergo_lib::wallet::derivation_path::{
8    ChildIndexError, ChildIndexHardened, ChildIndexNormal, DerivationPath as InnerDerivationPath,
9};
10use std::str::FromStr;
11
12#[derive(From, Into)]
13pub struct DerivationPath(pub InnerDerivationPath);
14pub type DerivationPathPtr = *mut DerivationPath;
15pub type ConstDerivationPathPtr = *const DerivationPath;
16
17/// Create DerivationPath from account index and address indices
18pub unsafe fn derivation_path_new(
19    account: u32,
20    address_indices: &[u32],
21    derivation_path_out: *mut DerivationPathPtr,
22) -> Result<(), Error> {
23    let derivation_path_out = mut_ptr_as_mut(derivation_path_out, "derivation_path_out")?;
24    let acc = ChildIndexHardened::from_31_bit(account)?;
25    let address_indices = address_indices
26        .iter()
27        .map(|i| ChildIndexNormal::normal(*i))
28        .collect::<Result<Vec<ChildIndexNormal>, ChildIndexError>>()
29        .map_err(Error::misc)?;
30    let derivation_path = DerivationPath(InnerDerivationPath::new(acc, address_indices));
31    *derivation_path_out = Box::into_raw(Box::new(derivation_path));
32    Ok(())
33}
34
35/// Create derivation path from string
36/// String should be in the form of: m/44/429/acc'/0/addr
37pub unsafe fn derivation_path_from_str(
38    derivation_path_str: &str,
39    derivation_path_out: *mut DerivationPathPtr,
40) -> Result<(), Error> {
41    let derivation_path_out = mut_ptr_as_mut(derivation_path_out, "derivation_path_out")?;
42    let derivation_path = wallet::derivation_path::DerivationPath::from_str(derivation_path_str)
43        .map_err(Error::misc)?;
44    *derivation_path_out = Box::into_raw(Box::new(DerivationPath(derivation_path)));
45    Ok(())
46}
47
48/// Get derivation path as string in the m/44/429/acc'/0/addr format
49pub unsafe fn derivation_path_to_str(
50    derivation_path_ptr: ConstDerivationPathPtr,
51) -> Result<String, Error> {
52    let derivation_path = const_ptr_as_ref(derivation_path_ptr, "derivation_path_ptr")?;
53    let s = derivation_path.0.to_string();
54    Ok(s)
55}
56
57/// Returns the length of the derivation path
58pub unsafe fn derivation_path_depth(
59    derivation_path_ptr: ConstDerivationPathPtr,
60) -> Result<usize, Error> {
61    let derivation_path = const_ptr_as_ref(derivation_path_ptr, "derivation_path_ptr")?;
62    Ok(derivation_path.0.depth())
63}
64
65/// Returns a new derivation path with the last element of the derivation path being increased, e.g. m/1/2 -> m/1/3
66pub unsafe fn derivation_path_next(
67    derivation_path_ptr: ConstDerivationPathPtr,
68    derivation_path_out: *mut DerivationPathPtr,
69) -> Result<(), Error> {
70    let derivation_path = const_ptr_as_ref(derivation_path_ptr, "derivation_path_ptr")?;
71    let derivation_path_out = mut_ptr_as_mut(derivation_path_out, "derivation_path_out")?;
72    *derivation_path_out = Box::into_raw(Box::new(DerivationPath(
73        derivation_path.0.next().map_err(Error::misc)?,
74    )));
75    Ok(())
76}