terra_rust_api/client/
tendermint.rs

1use crate::client::tendermint_types::{BlockResult, ValidatorSetResult};
2use crate::errors::TerraRustAPIError::TendermintValidatorSet;
3use crate::{LCDResult, Terra};
4
5pub struct Tendermint<'a> {
6    terra: &'a Terra,
7}
8impl Tendermint<'_> {
9    pub fn create(terra: &'_ Terra) -> Tendermint<'_> {
10        Tendermint { terra }
11    }
12    /// get the latest block
13    pub async fn blocks(&self) -> anyhow::Result<BlockResult> {
14        let response = self
15            .terra
16            .send_cmd::<BlockResult>("/blocks/latest", None)
17            .await?;
18        Ok(response)
19    }
20    /// get a block at a specific height
21    pub async fn blocks_at_height(&self, height: u64) -> anyhow::Result<BlockResult> {
22        let response = self
23            .terra
24            .send_cmd::<BlockResult>(&format!("/blocks/{}", height), None)
25            .await?;
26        Ok(response)
27    }
28
29    /// get the latest validatorset
30    /// @warn the maximum limit (at time of development is 100)
31    pub async fn validatorsets(
32        &self,
33        page: usize,
34        limit: usize,
35    ) -> anyhow::Result<LCDResult<ValidatorSetResult>> {
36        let args = if page == 0 {
37            format!("?limit={}", limit)
38        } else {
39            format!("?page={}&limit={}", page, limit)
40        };
41        let response = self
42            .terra
43            .send_cmd::<LCDResult<ValidatorSetResult>>("/validatorsets/latest", Some(&args))
44            .await?;
45        Ok(response)
46    }
47    /// get the latest full validatorset
48    ///
49    pub async fn validatorsets_full(&self) -> anyhow::Result<LCDResult<ValidatorSetResult>> {
50        // the interesting thing here is that the height returned is not available for the 2nd one.. so need to fire them off at the same time.
51        let part_1_f = self.validatorsets(1, 100);
52        let part_2 = self.validatorsets(2, 100).await?;
53        let part_1 = part_1_f.await?;
54        if part_1.result.block_height != part_2.result.block_height {
55            return Err(TendermintValidatorSet(
56                part_1.result.block_height,
57                part_2.result.block_height,
58            )
59            .into());
60        }
61        let mut combined = part_1.result.validators;
62        combined.extend(part_2.result.validators);
63        let vs_combined = ValidatorSetResult {
64            block_height: part_1.result.block_height,
65            validators: combined,
66        };
67        Ok(LCDResult {
68            height: part_1.height,
69            result: vs_combined,
70        })
71    }
72    /// get the full validatorset at a certain height
73    ///
74    pub async fn validatorsets_full_at_height(
75        &self,
76        height: u64,
77    ) -> anyhow::Result<LCDResult<ValidatorSetResult>> {
78        let part_1 = self.validatorsets_at_height(height, 1, 100).await?;
79        let part_2 = self.validatorsets_at_height(height, 2, 100).await?;
80        if part_1.result.block_height != part_2.result.block_height {
81            return Err(TendermintValidatorSet(
82                part_1.result.block_height,
83                part_2.result.block_height,
84            )
85            .into());
86        }
87        let mut combined = part_1.result.validators;
88        combined.extend(part_2.result.validators);
89        let vs_combined = ValidatorSetResult {
90            block_height: part_1.result.block_height,
91            validators: combined,
92        };
93        Ok(LCDResult {
94            height: part_1.height,
95            result: vs_combined,
96        })
97    }
98
99    /// get a validatorset at a specific height
100    /// @warn the maximum limit (at time of development is 100)
101    pub async fn validatorsets_at_height(
102        &self,
103        height: u64,
104        page: usize,
105        limit: usize,
106    ) -> anyhow::Result<LCDResult<ValidatorSetResult>> {
107        let args = if page == 0 {
108            format!("?limit={}", limit)
109        } else {
110            format!("?page={}&limit={}", page, limit)
111        };
112        let response = self
113            .terra
114            .send_cmd::<LCDResult<ValidatorSetResult>>(
115                &format!("/validatorsets/{}", height),
116                Some(&args),
117            )
118            .await?;
119        Ok(response)
120    }
121}