koios_sdk/api/
address.rs

1use crate::{
2    error::Result,
3    models::{
4        address::{AddressAsset, AddressInfo, AddressTransaction},
5        requests::{
6            AddressTransactionsRequest, CredentialTransactionsRequest, CredentialUtxosRequest,
7            PaymentAddressesRequest, PaymentAddressesWithExtendedRequest,
8        },
9        UtxoInfo,
10    },
11    Client,
12};
13use urlencoding::encode;
14
15impl Client {
16    /// Get address info - balance, associated stake address (if any) and UTxO set for given addresses
17    ///
18    /// # Arguments
19    ///
20    /// * `addresses` - List of addresses to query
21    ///
22    /// # Examples
23    ///
24    /// ```no_run
25    /// use koios_sdk::Client;
26    ///
27    /// #[tokio::main]
28    /// async fn main() -> Result<(), Box<dyn std::error::Error>> {
29    ///     let client = Client::new()?;
30    ///     let addresses = vec![
31    ///         "addr1qxqs59lphg8g6qndelq8xwqn60ag3aeyfcp33c2kdp46a09re5df3pzwwmyq946axfcejy5n4x0y99wqpgtp2gd0k09qsgy6pz".to_string()
32    ///     ];
33    ///     let address_info = client.get_address_info(&addresses).await?;
34    ///     println!("Address info: {:?}", address_info);
35    ///     Ok(())
36    /// }
37    /// ```
38    pub async fn get_address_info(&self, addresses: &[String]) -> Result<Vec<AddressInfo>> {
39        let encoded_addresses: Vec<String> = addresses
40            .iter()
41            .map(|addr| encode(addr).into_owned())
42            .collect();
43        let request = PaymentAddressesRequest::new(encoded_addresses);
44        self.post("/address_info", &request).await
45    }
46
47    /// Get UTxO set for given addresses
48    ///
49    /// # Arguments
50    ///
51    /// * `addresses` - List of addresses to query
52    /// * `extended` - Optional flag to include extended information
53    ///
54    /// # Examples
55    ///
56    /// ```no_run
57    /// use koios_sdk::Client;
58    ///
59    /// #[tokio::main]
60    /// async fn main() -> Result<(), Box<dyn std::error::Error>> {
61    ///     let client = Client::new()?;
62    ///     let addresses = vec![
63    ///         "addr1qxqs59lphg8g6qndelq8xwqn60ag3aeyfcp33c2kdp46a09re5df3pzwwmyq946axfcejy5n4x0y99wqpgtp2gd0k09qsgy6pz".to_string()
64    ///     ];
65    ///     let utxos = client.get_address_utxos(&addresses, Some(true)).await?;
66    ///     println!("Address UTXOs: {:?}", utxos);
67    ///     Ok(())
68    /// }
69    /// ```
70    pub async fn get_address_utxos(
71        &self,
72        addresses: &[String],
73        extended: Option<bool>,
74    ) -> Result<Vec<UtxoInfo>> {
75        let encoded_addresses: Vec<String> = addresses
76            .iter()
77            .map(|addr| encode(addr).into_owned())
78            .collect();
79        let request = PaymentAddressesWithExtendedRequest::new(encoded_addresses, extended);
80        self.post("/address_utxos", &request).await
81    }
82
83    /// Get UTxO details for requested payment credentials
84    ///
85    /// # Arguments
86    ///
87    /// * `payment_credentials` - List of payment credentials to query
88    /// * `extended` - Optional flag to include extended information
89    ///
90    /// # Examples
91    ///
92    /// ```no_run
93    /// use koios_sdk::Client;
94    ///
95    /// #[tokio::main]
96    /// async fn main() -> Result<(), Box<dyn std::error::Error>> {
97    ///     let client = Client::new()?;
98    ///     let credentials = vec![
99    ///         "025b0a8f85cb8a46e1dda3fae5d22f07e2d56abb4019a2129c5d6c52".to_string()
100    ///     ];
101    ///     let utxos = client.get_credential_utxos(&credentials, Some(true)).await?;
102    ///     println!("Credential UTXOs: {:?}", utxos);
103    ///     Ok(())
104    /// }
105    /// ```
106    pub async fn get_credential_utxos(
107        &self,
108        payment_credentials: &[String],
109        extended: Option<bool>,
110    ) -> Result<Vec<UtxoInfo>> {
111        let encoded_credentials: Vec<String> = payment_credentials
112            .iter()
113            .map(|cred| encode(cred).into_owned())
114            .collect();
115        let request = CredentialUtxosRequest::new(encoded_credentials, extended);
116        self.post("/credential_utxos", &request).await
117    }
118
119    /// Get the transaction hash list of input address array, optionally filtering after specified block height
120    ///
121    /// # Arguments
122    ///
123    /// * `addresses` - List of addresses to query
124    /// * `after_block_height` - Optional block height to filter from
125    ///
126    /// # Examples
127    ///
128    /// ```no_run
129    /// use koios_sdk::Client;
130    ///
131    /// #[tokio::main]
132    /// async fn main() -> Result<(), Box<dyn std::error::Error>> {
133    ///     let client = Client::new()?;
134    ///     let addresses = vec![
135    ///         "addr1qxqs59lphg8g6qndelq8xwqn60ag3aeyfcp33c2kdp46a09re5df3pzwwmyq946axfcejy5n4x0y99wqpgtp2gd0k09qsgy6pz".to_string()
136    ///     ];
137    ///     let txs = client.get_address_transactions(&addresses, Some(42000000)).await?;
138    ///     println!("Address transactions: {:?}", txs);
139    ///     Ok(())
140    /// }
141    /// ```
142    pub async fn get_address_transactions(
143        &self,
144        addresses: &[String],
145        after_block_height: Option<u64>,
146    ) -> Result<Vec<AddressTransaction>> {
147        let encoded_addresses: Vec<String> = addresses
148            .iter()
149            .map(|addr| encode(addr).into_owned())
150            .collect();
151        let request = AddressTransactionsRequest::new(encoded_addresses, after_block_height);
152        self.post("/address_txs", &request).await
153    }
154
155    /// Get the transaction hash list of input payment credential array, optionally filtering after specified block height
156    ///
157    /// # Arguments
158    ///
159    /// * `payment_credentials` - List of payment credentials to query
160    /// * `after_block_height` - Optional block height to filter from
161    ///
162    /// # Examples
163    ///
164    /// ```no_run
165    /// use koios_sdk::Client;
166    ///
167    /// #[tokio::main]
168    /// async fn main() -> Result<(), Box<dyn std::error::Error>> {
169    ///     let client = Client::new()?;
170    ///     let credentials = vec![
171    ///         "025b0a8f85cb8a46e1dda3fae5d22f07e2d56abb4019a2129c5d6c52".to_string()
172    ///     ];
173    ///     let txs = client.get_credential_transactions(&credentials, Some(42000000)).await?;
174    ///     println!("Credential transactions: {:?}", txs);
175    ///     Ok(())
176    /// }
177    /// ```
178    pub async fn get_credential_transactions(
179        &self,
180        payment_credentials: &[String],
181        after_block_height: Option<u64>,
182    ) -> Result<Vec<AddressTransaction>> {
183        let encoded_credentials: Vec<String> = payment_credentials
184            .iter()
185            .map(|cred| encode(cred).into_owned())
186            .collect();
187        let request = CredentialTransactionsRequest::new(encoded_credentials, after_block_height);
188        self.post("/credential_txs", &request).await
189    }
190
191    /// Get the list of all the assets (policy, name and quantity) for given addresses
192    ///
193    /// # Arguments
194    ///
195    /// * `addresses` - List of addresses to query
196    ///
197    /// # Examples
198    ///
199    /// ```no_run
200    /// use koios_sdk::Client;
201    ///
202    /// #[tokio::main]
203    /// async fn main() -> Result<(), Box<dyn std::error::Error>> {
204    ///     let client = Client::new()?;
205    ///     let addresses = vec![
206    ///         "addr1qxqs59lphg8g6qndelq8xwqn60ag3aeyfcp33c2kdp46a09re5df3pzwwmyq946axfcejy5n4x0y99wqpgtp2gd0k09qsgy6pz".to_string()
207    ///     ];
208    ///     let assets = client.get_address_assets(&addresses).await?;
209    ///     println!("Address assets: {:?}", assets);
210    ///     Ok(())
211    /// }
212    /// ```
213    pub async fn get_address_assets(&self, addresses: &[String]) -> Result<Vec<AddressAsset>> {
214        let encoded_addresses: Vec<String> = addresses
215            .iter()
216            .map(|addr| encode(addr).into_owned())
217            .collect();
218        let request = PaymentAddressesRequest::new(encoded_addresses);
219        self.post("/address_assets", &request).await
220    }
221}
222
223#[cfg(test)]
224mod tests {
225    use super::*;
226    use serde_json::json;
227    use wiremock::matchers::{method, path};
228    use wiremock::{Mock, MockServer, ResponseTemplate};
229
230    #[tokio::test]
231    async fn test_get_address_info() {
232        let mock_server = MockServer::start().await;
233        let client = Client::builder()
234            .base_url(mock_server.uri())
235            .build()
236            .unwrap();
237
238        let address = "addr1qxqs59lphg8g6qndelq8xwqn60ag3aeyfcp33c2kdp46a09re5df3pzwwmyq946axfcejy5n4x0y99wqpgtp2gd0k09qsgy6pz";
239        let mock_response = json!([{
240            "address": address,
241            "balance": "42000000",
242            "stake_address": "stake1u9ylzsgxaa6xctf4juup682ar3juj85n8tx3hthnljg47zctvm3rc",
243            "script_address": false,
244            "utxo_set": []
245        }]);
246
247        Mock::given(method("POST"))
248            .and(path("/address_info"))
249            .respond_with(ResponseTemplate::new(200).set_body_json(&mock_response))
250            .mount(&mock_server)
251            .await;
252
253        let response = client
254            .get_address_info(&[address.to_string()])
255            .await
256            .unwrap();
257        assert_eq!(response.len(), 1);
258        assert_eq!(response[0].address, address);
259    }
260
261    // Add more tests for other endpoints...
262}