rain_sdk/api/
contracts.rs

1//! Contracts API
2//!
3//! This module provides functionality to manage smart contracts.
4
5use crate::client::RainClient;
6use crate::error::Result;
7use crate::models::contracts::*;
8use uuid::Uuid;
9
10impl RainClient {
11    /// Get smart contract information for a company
12    ///
13    /// # Arguments
14    ///
15    /// * `company_id` - The unique identifier of the company
16    ///
17    /// # Returns
18    ///
19    /// Returns a [`Vec<Contract>`] containing the list of contracts.
20    ///
21    /// # Errors
22    ///
23    /// This method can return the following errors:
24    /// - `401` - Invalid authorization
25    /// - `404` - Company not found
26    /// - `500` - Internal server error
27    ///
28    /// # Examples
29    ///
30    /// ```no_run
31    /// use rain_sdk::{RainClient, Config, Environment, AuthConfig};
32    /// use uuid::Uuid;
33    ///
34    /// # #[cfg(feature = "async")]
35    /// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
36    /// let config = Config::new(Environment::Dev);
37    /// let auth = AuthConfig::with_api_key("your-api-key".to_string());
38    /// let client = RainClient::new(config, auth)?;
39    ///
40    /// let company_id = Uuid::new_v4();
41    /// let contracts = client.get_company_contracts(&company_id).await?;
42    /// # Ok(())
43    /// # }
44    /// ```
45    #[cfg(feature = "async")]
46    pub async fn get_company_contracts(&self, company_id: &Uuid) -> Result<Vec<Contract>> {
47        let path = format!("/companies/{company_id}/contracts");
48        self.get(&path).await
49    }
50
51    /// Create a smart contract for a company
52    ///
53    /// # Arguments
54    ///
55    /// * `company_id` - The unique identifier of the company
56    /// * `request` - The contract creation request
57    ///
58    /// # Returns
59    ///
60    /// Returns success (202 Accepted) with no response body.
61    ///
62    /// # Errors
63    ///
64    /// This method can return the following errors:
65    /// - `400` - Invalid request
66    /// - `401` - Invalid authorization
67    /// - `404` - Company not found
68    /// - `409` - Company already has a contract on this chain
69    /// - `500` - Internal server error
70    ///
71    /// # Examples
72    ///
73    /// ```no_run
74    /// use rain_sdk::{RainClient, Config, Environment, AuthConfig};
75    /// use rain_sdk::models::contracts::CreateCompanyContractRequest;
76    /// use uuid::Uuid;
77    ///
78    /// # #[cfg(feature = "async")]
79    /// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
80    /// let config = Config::new(Environment::Dev);
81    /// let auth = AuthConfig::with_api_key("your-api-key".to_string());
82    /// let client = RainClient::new(config, auth)?;
83    ///
84    /// let company_id = Uuid::new_v4();
85    /// let request = CreateCompanyContractRequest {
86    ///     chain_id: 1, // Ethereum mainnet
87    ///     owner_address: "0x1234...".to_string(),
88    /// };
89    /// client.create_company_contract(&company_id, &request).await?;
90    /// # Ok(())
91    /// # }
92    /// ```
93    #[cfg(feature = "async")]
94    pub async fn create_company_contract(
95        &self,
96        company_id: &Uuid,
97        request: &CreateCompanyContractRequest,
98    ) -> Result<()> {
99        let path = format!("/companies/{company_id}/contracts");
100        // Returns 202 Accepted with no body - handle gracefully
101        let _: serde_json::Value = self.post(&path, request).await?;
102        Ok(())
103    }
104
105    /// Get smart contract information for an authorized user tenant
106    ///
107    /// # Returns
108    ///
109    /// Returns a [`Vec<Contract>`] containing the list of contracts.
110    ///
111    /// # Errors
112    ///
113    /// This method can return the following errors:
114    /// - `401` - Invalid authorization
115    /// - `500` - Internal server error
116    ///
117    /// # Examples
118    ///
119    /// ```no_run
120    /// use rain_sdk::{RainClient, Config, Environment, AuthConfig};
121    ///
122    /// # #[cfg(feature = "async")]
123    /// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
124    /// let config = Config::new(Environment::Dev);
125    /// let auth = AuthConfig::with_api_key("your-api-key".to_string());
126    /// let client = RainClient::new(config, auth)?;
127    ///
128    /// let contracts = client.get_contracts().await?;
129    /// println!("Found {} contracts", contracts.len());
130    /// # Ok(())
131    /// # }
132    /// ```
133    #[cfg(feature = "async")]
134    pub async fn get_contracts(&self) -> Result<Vec<Contract>> {
135        let path = "/contracts";
136        self.get(path).await
137    }
138
139    /// Update a smart contract
140    ///
141    /// # Arguments
142    ///
143    /// * `contract_id` - The unique identifier of the contract
144    /// * `request` - The contract update request
145    ///
146    /// # Returns
147    ///
148    /// Returns success (200 OK) with response body.
149    ///
150    /// # Errors
151    ///
152    /// This method can return the following errors:
153    /// - `400` - Invalid request
154    /// - `401` - Invalid authorization
155    /// - `404` - Contract not found
156    /// - `500` - Internal server error
157    ///
158    /// # Examples
159    ///
160    /// ```no_run
161    /// use rain_sdk::{RainClient, Config, Environment, AuthConfig};
162    /// use rain_sdk::models::contracts::UpdateContractRequest;
163    /// use uuid::Uuid;
164    ///
165    /// # #[cfg(feature = "async")]
166    /// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
167    /// let config = Config::new(Environment::Dev);
168    /// let auth = AuthConfig::with_api_key("your-api-key".to_string());
169    /// let client = RainClient::new(config, auth)?;
170    ///
171    /// let contract_id = Uuid::new_v4();
172    /// let request = UpdateContractRequest {
173    ///     onramp: true,
174    /// };
175    /// let response: serde_json::Value = client.update_contract(&contract_id, &request).await?;
176    /// # Ok(())
177    /// # }
178    /// ```
179    #[cfg(feature = "async")]
180    pub async fn update_contract(
181        &self,
182        contract_id: &Uuid,
183        request: &UpdateContractRequest,
184    ) -> Result<serde_json::Value> {
185        let path = format!("/contracts/{contract_id}");
186        self.put(&path, request).await
187    }
188
189    /// Get smart contract information for a user
190    ///
191    /// # Arguments
192    ///
193    /// * `user_id` - The unique identifier of the user
194    ///
195    /// # Returns
196    ///
197    /// Returns a [`Vec<Contract>`] containing the list of contracts.
198    ///
199    /// # Errors
200    ///
201    /// This method can return the following errors:
202    /// - `401` - Invalid authorization
203    /// - `404` - User not found
204    /// - `500` - Internal server error
205    ///
206    /// # Examples
207    ///
208    /// ```no_run
209    /// use rain_sdk::{RainClient, Config, Environment, AuthConfig};
210    /// use uuid::Uuid;
211    ///
212    /// # #[cfg(feature = "async")]
213    /// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
214    /// let config = Config::new(Environment::Dev);
215    /// let auth = AuthConfig::with_api_key("your-api-key".to_string());
216    /// let client = RainClient::new(config, auth)?;
217    ///
218    /// let user_id = Uuid::new_v4();
219    /// let contracts = client.get_user_contracts(&user_id).await?;
220    /// # Ok(())
221    /// # }
222    /// ```
223    #[cfg(feature = "async")]
224    pub async fn get_user_contracts(&self, user_id: &Uuid) -> Result<Vec<Contract>> {
225        let path = format!("/users/{user_id}/contracts");
226        self.get(&path).await
227    }
228
229    /// Create a smart contract for a user
230    ///
231    /// # Arguments
232    ///
233    /// * `user_id` - The unique identifier of the user (must have EVM or Solana address)
234    /// * `request` - The contract creation request
235    ///
236    /// # Returns
237    ///
238    /// Returns success (202 Accepted) with no response body.
239    ///
240    /// # Errors
241    ///
242    /// This method can return the following errors:
243    /// - `400` - Invalid request
244    /// - `401` - Invalid authorization
245    /// - `404` - User not found
246    /// - `409` - User already has a contract on this chain
247    /// - `500` - Internal server error
248    ///
249    /// # Examples
250    ///
251    /// ```no_run
252    /// use rain_sdk::{RainClient, Config, Environment, AuthConfig};
253    /// use rain_sdk::models::contracts::CreateUserContractRequest;
254    /// use uuid::Uuid;
255    ///
256    /// # #[cfg(feature = "async")]
257    /// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
258    /// let config = Config::new(Environment::Dev);
259    /// let auth = AuthConfig::with_api_key("your-api-key".to_string());
260    /// let client = RainClient::new(config, auth)?;
261    ///
262    /// let user_id = Uuid::new_v4();
263    /// let request = CreateUserContractRequest {
264    ///     chain_id: 1, // Ethereum mainnet
265    /// };
266    /// client.create_user_contract(&user_id, &request).await?;
267    /// # Ok(())
268    /// # }
269    /// ```
270    #[cfg(feature = "async")]
271    pub async fn create_user_contract(
272        &self,
273        user_id: &Uuid,
274        request: &CreateUserContractRequest,
275    ) -> Result<()> {
276        let path = format!("/users/{user_id}/contracts");
277        // Returns 202 Accepted with no body - handle gracefully
278        let _: serde_json::Value = self.post(&path, request).await?;
279        Ok(())
280    }
281
282    // ============================================================================
283    // Blocking Methods
284    // ============================================================================
285
286    /// Get smart contract information for a company (blocking)
287    #[cfg(feature = "sync")]
288    pub fn get_company_contracts_blocking(&self, company_id: &Uuid) -> Result<Vec<Contract>> {
289        let path = format!("/companies/{company_id}/contracts");
290        self.get_blocking(&path)
291    }
292
293    /// Create a smart contract for a company (blocking)
294    #[cfg(feature = "sync")]
295    pub fn create_company_contract_blocking(
296        &self,
297        company_id: &Uuid,
298        request: &CreateCompanyContractRequest,
299    ) -> Result<()> {
300        let path = format!("/companies/{company_id}/contracts");
301        // Returns 202 Accepted with no body - handle gracefully
302        let _: serde_json::Value = self.post_blocking(&path, request)?;
303        Ok(())
304    }
305
306    /// Get smart contract information for an authorized user tenant (blocking)
307    #[cfg(feature = "sync")]
308    pub fn get_contracts_blocking(&self) -> Result<Vec<Contract>> {
309        let path = "/contracts";
310        self.get_blocking(path)
311    }
312
313    /// Update a smart contract (blocking)
314    #[cfg(feature = "sync")]
315    pub fn update_contract_blocking(
316        &self,
317        contract_id: &Uuid,
318        request: &UpdateContractRequest,
319    ) -> Result<serde_json::Value> {
320        let path = format!("/contracts/{contract_id}");
321        self.put_blocking(&path, request)
322    }
323
324    /// Get smart contract information for a user (blocking)
325    #[cfg(feature = "sync")]
326    pub fn get_user_contracts_blocking(&self, user_id: &Uuid) -> Result<Vec<Contract>> {
327        let path = format!("/users/{user_id}/contracts");
328        self.get_blocking(&path)
329    }
330
331    /// Create a smart contract for a user (blocking)
332    #[cfg(feature = "sync")]
333    pub fn create_user_contract_blocking(
334        &self,
335        user_id: &Uuid,
336        request: &CreateUserContractRequest,
337    ) -> Result<()> {
338        let path = format!("/users/{user_id}/contracts");
339        // Returns 202 Accepted with no body - handle gracefully
340        let _: serde_json::Value = self.post_blocking(&path, request)?;
341        Ok(())
342    }
343}