iota_client/api/
balance.rs

1// Copyright 2021 IOTA Stiftung
2// SPDX-License-Identifier: Apache-2.0
3
4use crate::{Client, Result};
5use crypto::keys::slip10::Seed;
6
7/// Builder of get_balance API
8pub struct GetBalanceBuilder<'a> {
9    client: &'a Client,
10    seed: &'a Seed,
11    account_index: usize,
12    initial_address_index: usize,
13    gap_limit: usize,
14}
15
16impl<'a> GetBalanceBuilder<'a> {
17    /// Create get_balance builder
18    pub fn new(client: &'a Client, seed: &'a Seed) -> Self {
19        Self {
20            client,
21            seed,
22            account_index: 0,
23            initial_address_index: 0,
24            gap_limit: super::ADDRESS_GAP_RANGE,
25        }
26    }
27
28    /// Sets the account index.
29    pub fn with_account_index(mut self, account_index: usize) -> Self {
30        self.account_index = account_index;
31        self
32    }
33
34    /// Sets the index of the address to start looking for balance.
35    pub fn with_initial_address_index(mut self, initial_address_index: usize) -> Self {
36        self.initial_address_index = initial_address_index;
37        self
38    }
39
40    /// Sets the gap limit to specify how many addresses will be checked each round.
41    /// If gap_limit amount of addresses in a row have no balance the function will return.
42    pub fn with_gap_limit(mut self, gap_limit: usize) -> Self {
43        self.gap_limit = gap_limit;
44        self
45    }
46
47    /// Consume the builder and get the API result
48    pub async fn finish(self) -> Result<u64> {
49        let mut index = self.initial_address_index;
50
51        // get account balance and check with value
52        let mut balance = 0;
53        // Count addresses with zero balances in a row
54        let mut found_zero_balance = 0;
55        loop {
56            let addresses = self
57                .client
58                .get_addresses(self.seed)
59                .with_account_index(self.account_index)
60                .with_range(index..index + self.gap_limit)
61                .get_all()
62                .await?;
63
64            for (address, _) in addresses {
65                let address_balance = self.client.get_address().balance(&address).await?;
66                match address_balance.balance {
67                    0 => found_zero_balance += 1,
68                    _ => {
69                        balance += address_balance.balance;
70                        // reset
71                        found_zero_balance = 0;
72                    }
73                }
74            }
75            // The gap limit is 20 and use reference 40 here because there's public and internal addresses
76            if found_zero_balance >= self.gap_limit * 2 {
77                break;
78            }
79            index += self.gap_limit;
80        }
81
82        Ok(balance)
83    }
84}