xand_api_client/
mock.rs

1use crate::errors::XandApiClientError;
2use crate::{
3    models::{Paginated, Paging, TransactionUpdate},
4    Result, TransactionStatusStream, VoteProposal, XandApiClientTrait,
5};
6use futures::{stream, StreamExt};
7use pseudo::Mock;
8use std::time::Duration;
9use xand_address::Address;
10use xand_api_proto::proto_models::{
11    AdministrativeTransaction, Blockstamp, CidrBlock, HealthResponse, PendingCreateRequest,
12    PendingRedeemRequest, Proposal, TotalIssuance, Transaction, TransactionFilter, TransactionId,
13    TransactionStatus, ValidatorEmissionProgress, ValidatorEmissionRate, XandTransaction,
14};
15
16type TxUpdateStream = Result<Vec<Result<TransactionUpdate>>>;
17
18#[derive(Clone)]
19#[allow(clippy::module_name_repetitions)]
20pub struct MockXandApiClient {
21    // A list of lists of transaction updates to reply with to calls to `submit_transaction`
22    pub submits: Mock<(Address, XandTransaction), TxUpdateStream>,
23    pub balance: Mock<String, Result<Option<u128>>>,
24    pub pending_create_requests: Mock<(), Result<Paginated<Vec<PendingCreateRequest>>>>,
25    pub pending_redeem_requests: Mock<(), Result<Paginated<Vec<PendingRedeemRequest>>>>,
26    pub transaction_details: Mock<TransactionId, Result<Transaction>>,
27    pub total_issuance: Mock<(), Result<TotalIssuance>>,
28    pub delay: Option<Duration>,
29}
30
31impl MockXandApiClient {
32    #[must_use]
33    pub fn with_delay(self, delay: Duration) -> Self {
34        Self {
35            delay: Some(delay),
36            ..self
37        }
38    }
39
40    async fn pause(&self) {
41        if let Some(d) = self.delay {
42            tokio::time::sleep(d).await;
43        }
44    }
45}
46
47impl Default for MockXandApiClient {
48    fn default() -> Self {
49        MockXandApiClient {
50            submits: Mock::new(Ok(Vec::default())),
51            balance: Mock::new(Ok(Some(0_u128))),
52            pending_create_requests: Mock::new(Ok(Paginated::default())),
53            pending_redeem_requests: Mock::new(Ok(Paginated::default())),
54            transaction_details: Mock::new(Err(XandApiClientError::NotFound { message: "Mock XandApiClient has not been configured to return information about this transaction.".to_string() })),
55            total_issuance: Mock::new(Ok(TotalIssuance { total_issued: 0, blockstamp: Blockstamp {
56                block_number: 0,
57                unix_timestamp_ms: 0,
58                is_stale: false
59            } })),
60            delay: None,
61        }
62    }
63}
64
65#[async_trait::async_trait]
66impl XandApiClientTrait for MockXandApiClient {
67    async fn submit_transaction(
68        &self,
69        address: Address,
70        txn: XandTransaction,
71    ) -> Result<TransactionStatusStream> {
72        self.pause().await;
73        let reply = self.submits.call((address, txn));
74        if let Ok(reply) = reply {
75            Ok(TransactionStatusStream {
76                stream: stream::iter(reply).boxed(),
77            })
78        } else {
79            Err(reply.unwrap_err())
80        }
81    }
82
83    async fn get_transaction_details(&self, id: &TransactionId) -> Result<Transaction> {
84        self.pause().await;
85        self.transaction_details.call(id.clone())
86    }
87
88    async fn get_transaction_history(
89        &self,
90        _paging: Option<Paging>,
91        _filter: &TransactionFilter,
92    ) -> Result<Paginated<Vec<Transaction>>> {
93        unimplemented!()
94    }
95
96    async fn get_balance(&self, address: &str) -> Result<Option<u128>> {
97        self.pause().await;
98        self.balance.call(address.to_string())
99    }
100
101    async fn get_total_issuance(&self) -> Result<TotalIssuance> {
102        self.total_issuance.call(())
103    }
104
105    async fn get_address_transactions(
106        &self,
107        _address: &str,
108        _paging: Option<Paging>,
109    ) -> Result<Paginated<Vec<Transaction>>> {
110        unimplemented!()
111    }
112
113    async fn get_current_block(&self) -> Result<Blockstamp> {
114        unimplemented!()
115    }
116
117    async fn get_pending_create_requests(
118        &self,
119        _paging: Option<Paging>,
120    ) -> Result<Paginated<Vec<PendingCreateRequest>>> {
121        self.pause().await;
122        self.pending_create_requests.call(())
123    }
124
125    async fn get_pending_redeem_requests(
126        &self,
127        _paging: Option<Paging>,
128    ) -> Result<Paginated<Vec<PendingRedeemRequest>>> {
129        self.pause().await;
130        self.pending_redeem_requests.call(())
131    }
132
133    async fn propose_action(
134        &self,
135        _issuer: Address,
136        _admin_txn: AdministrativeTransaction,
137    ) -> Result<TransactionStatusStream, XandApiClientError> {
138        unimplemented!()
139    }
140
141    async fn vote_on_proposal(
142        &self,
143        _issuer: Address,
144        _vote_proposal: VoteProposal,
145    ) -> Result<TransactionStatusStream, XandApiClientError> {
146        unimplemented!()
147    }
148
149    async fn get_proposal(&self, _id: u32) -> Result<Proposal, XandApiClientError> {
150        unimplemented!()
151    }
152
153    async fn get_all_proposals(&self) -> Result<Vec<Proposal>, XandApiClientError> {
154        unimplemented!()
155    }
156
157    async fn get_members(&self) -> Result<Vec<Address>, XandApiClientError> {
158        unimplemented!()
159    }
160
161    async fn get_authority_keys(&self) -> Result<Vec<Address>, XandApiClientError> {
162        unimplemented!()
163    }
164
165    async fn get_trustee(&self) -> Result<Address, XandApiClientError> {
166        unimplemented!()
167    }
168
169    async fn get_allowlist(&self) -> Result<Vec<(Address, CidrBlock)>, XandApiClientError> {
170        unimplemented!()
171    }
172
173    async fn get_limited_agent(&self) -> Result<Option<Address>, XandApiClientError> {
174        unimplemented!()
175    }
176
177    async fn get_validator_emission_rate(&self) -> Result<ValidatorEmissionRate> {
178        unimplemented!()
179    }
180
181    async fn get_validator_emission_progress(
182        &self,
183        _address: Address,
184    ) -> Result<ValidatorEmissionProgress> {
185        unimplemented!()
186    }
187
188    async fn get_pending_create_request_expire_time(&self) -> Result<u64> {
189        unimplemented!()
190    }
191
192    async fn check_health(&self) -> Result<HealthResponse> {
193        unimplemented!()
194    }
195}
196
197#[must_use]
198pub fn committed_status() -> TransactionUpdate {
199    TransactionUpdate {
200        status: TransactionStatus::Committed,
201        id: xand_api_proto::proto_models::TransactionId::default(),
202    }
203}
204
205#[must_use]
206pub fn finalized_status() -> TransactionUpdate {
207    TransactionUpdate {
208        status: TransactionStatus::Finalized,
209        id: xand_api_proto::proto_models::TransactionId::default(),
210    }
211}