iota_client/api/
unspent.rs

1// Copyright 2021 IOTA Stiftung
2// SPDX-License-Identifier: Apache-2.0
3
4use crate::{node::OutputsOptions, Client, Result};
5
6use crypto::keys::slip10::Seed;
7
8/// Builder of get_unspent_address API
9pub struct GetUnspentAddressBuilder<'a> {
10    client: &'a Client,
11    seed: &'a Seed,
12    account_index: Option<usize>,
13    initial_address_index: Option<usize>,
14}
15
16impl<'a> GetUnspentAddressBuilder<'a> {
17    /// Create get_unspent_address builder
18    pub fn new(client: &'a Client, seed: &'a Seed) -> Self {
19        Self {
20            client,
21            seed,
22            account_index: None,
23            initial_address_index: None,
24        }
25    }
26
27    /// Sets the account index.
28    pub fn with_account_index(mut self, account_index: usize) -> Self {
29        self.account_index.replace(account_index);
30        self
31    }
32
33    /// Sets the index of the address to start looking for balance.
34    pub fn with_initial_address_index(mut self, initial_address_index: usize) -> Self {
35        self.initial_address_index.replace(initial_address_index);
36        self
37    }
38
39    /// Consume the builder and get the API result
40    pub async fn get(self) -> Result<(String, usize)> {
41        let account_index = self.account_index.unwrap_or(0);
42
43        let mut index = self.initial_address_index.unwrap_or(0);
44
45        let result = loop {
46            let addresses = self
47                .client
48                .get_addresses(self.seed)
49                .with_account_index(account_index)
50                .with_range(index..index + super::ADDRESS_GAP_RANGE)
51                .finish()
52                .await?;
53
54            let mut address = None;
55            for a in addresses {
56                let address_outputs = self
57                    .client
58                    .get_address()
59                    .outputs(
60                        &a,
61                        OutputsOptions {
62                            include_spent: true,
63                            output_type: None,
64                        },
65                    )
66                    .await?;
67                if address_outputs.is_empty() {
68                    address.replace(a);
69                    break;
70                } else {
71                    index += 1;
72                }
73            }
74
75            if let Some(a) = address {
76                break (a, index);
77            }
78        };
79
80        Ok(result)
81    }
82}