iota_client/api/
address.rs1use crate::{Client, Error, Result};
5
6use bee_message::prelude::{Address, Ed25519Address};
7use core::convert::TryInto;
8use crypto::{
9 hashes::{blake2b::Blake2b256, Digest},
10 keys::slip10::{Chain, Curve, Seed},
11};
12use std::ops::Range;
13
14pub struct GetAddressesBuilder<'a> {
16 client: Option<&'a Client>,
17 seed: Option<&'a Seed>,
18 account_index: usize,
19 range: Range<usize>,
20 bech32_hrp: Option<String>,
21}
22
23impl<'a> Default for GetAddressesBuilder<'a> {
24 fn default() -> Self {
25 Self {
26 client: None,
27 seed: None,
28 account_index: 0,
29 range: 0..super::ADDRESS_GAP_RANGE,
30 bech32_hrp: None,
31 }
32 }
33}
34
35impl<'a> GetAddressesBuilder<'a> {
36 pub fn new(seed: &'a Seed) -> Self {
38 Self {
39 seed: Some(seed),
40 ..Default::default()
41 }
42 }
43
44 pub fn with_client(mut self, client: &'a Client) -> Self {
46 self.client.replace(client);
47 self
48 }
49
50 pub fn with_account_index(mut self, account_index: usize) -> Self {
52 self.account_index = account_index;
53 self
54 }
55
56 pub fn with_range(mut self, range: Range<usize>) -> Self {
58 self.range = range;
59 self
60 }
61
62 pub fn with_bech32_hrp(mut self, bech32_hrp: String) -> Self {
64 self.bech32_hrp.replace(bech32_hrp);
65 self
66 }
67
68 pub async fn finish(self) -> Result<Vec<String>> {
70 Ok(self
71 .get_all()
72 .await?
73 .into_iter()
74 .filter(|(_, internal)| !internal)
75 .map(|(a, _)| a)
76 .collect())
77 }
78
79 pub async fn get_all(self) -> Result<Vec<(String, bool)>> {
81 let bech32_hrp = match self.bech32_hrp.clone() {
82 Some(bech32_hrp) => bech32_hrp,
83 None => {
84 self.client
85 .ok_or(Error::MissingParameter("Client or bech32_hrp"))?
86 .get_bech32_hrp()
87 .await?
88 }
89 };
90 let addresses = self
91 .get_all_raw()
92 .await?
93 .into_iter()
94 .map(|(a, b)| (a.to_bech32(&bech32_hrp), b))
95 .collect();
96
97 Ok(addresses)
98 }
99 pub async fn get_all_raw(self) -> Result<Vec<(Address, bool)>> {
101 let mut addresses = Vec::new();
102 for address_index in self.range {
103 let address = generate_address(
104 self.seed.ok_or(Error::MissingParameter("Seed"))?,
105 self.account_index as u32,
106 address_index as u32,
107 false,
108 )?;
109 let internal_address = generate_address(
110 self.seed.ok_or(Error::MissingParameter("Seed"))?,
111 self.account_index as u32,
112 address_index as u32,
113 true,
114 )?;
115 addresses.push((address, false));
116 addresses.push((internal_address, true));
117 }
118
119 Ok(addresses)
120 }
121}
122
123fn generate_address(seed: &Seed, account_index: u32, address_index: u32, internal: bool) -> Result<Address> {
124 let chain = Chain::from_u32_hardened(vec![44, 4218, account_index, internal as u32, address_index]);
126 let public_key = seed
127 .derive(Curve::Ed25519, &chain)?
128 .secret_key()
129 .public_key()
130 .to_bytes();
131 let result = Blake2b256::digest(&public_key)
133 .try_into()
134 .map_err(|_e| Error::Blake2b256Error("Hashing the public key while generating the address failed."));
135
136 Ok(Address::Ed25519(Ed25519Address::new(result?)))
137}
138
139pub async fn search_address(
141 seed: &Seed,
142 bech32_hrp: &str,
143 account_index: usize,
144 range: Range<usize>,
145 address: &Address,
146) -> Result<(usize, bool)> {
147 let addresses = GetAddressesBuilder::new(seed)
148 .with_bech32_hrp(bech32_hrp.to_owned())
149 .with_account_index(account_index)
150 .with_range(range.clone())
151 .get_all()
152 .await?;
153 let mut index_counter = range.start;
154 for address_internal in addresses {
155 if address_internal.0 == *address.to_bech32(bech32_hrp) {
156 return Ok((index_counter, address_internal.1));
157 }
158 if !address_internal.1 {
159 index_counter += 1;
160 }
161 }
162 Err(crate::error::Error::InputAddressNotFound(
163 address.to_bech32(bech32_hrp),
164 format!("{range:?}"),
165 ))
166}