rain_sdk/api/applications.rs
1//! Applications API
2//!
3//! This module provides functionality to manage company and user applications in the Rain API.
4//!
5//! # Examples
6//!
7//! This module provides functionality to manage company and user applications.
8//!
9//! See the individual function documentation for examples.
10
11use crate::client::RainClient;
12use crate::error::Result;
13use crate::models::applications::*;
14use uuid::Uuid;
15
16impl RainClient {
17 // ============================================================================
18 // Company Application Methods
19 // ============================================================================
20
21 /// Create a company application
22 ///
23 /// # Arguments
24 ///
25 /// * `request` - The company application request
26 ///
27 /// # Returns
28 ///
29 /// Returns a [`CompanyApplicationResponse`] containing the application information.
30 ///
31 /// # Examples
32 ///
33 /// ```no_run
34 /// use rain_sdk::{RainClient, Config, Environment, AuthConfig};
35 /// use rain_sdk::models::applications::*;
36 /// use rain_sdk::models::common::*;
37 ///
38 /// # #[cfg(feature = "async")]
39 /// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
40 /// let config = Config::new(Environment::Dev);
41 /// let auth = AuthConfig::with_api_key("your-api-key".to_string());
42 /// let client = RainClient::new(config, auth)?;
43 ///
44 /// // Note: In practice, you would populate all required fields.
45 /// // This is a simplified example - see the full struct definitions for required fields.
46 /// # let request = todo!();
47 /// let application = client.create_company_application(&request).await?;
48 /// # Ok(())
49 /// # }
50 /// ```
51 #[cfg(feature = "async")]
52 pub async fn create_company_application(
53 &self,
54 request: &CreateCompanyApplicationRequest,
55 ) -> Result<CompanyApplicationResponse> {
56 let path = "/issuing/applications/company";
57 self.post(path, request).await
58 }
59
60 /// Get a company application by ID
61 ///
62 /// # Arguments
63 ///
64 /// * `company_id` - The unique identifier of the company
65 ///
66 /// # Returns
67 ///
68 /// Returns a [`CompanyApplicationResponse`] containing the application information.
69 ///
70 /// # Examples
71 ///
72 /// ```no_run
73 /// use rain_sdk::{RainClient, Config, Environment, AuthConfig};
74 /// use uuid::Uuid;
75 ///
76 /// # #[cfg(feature = "async")]
77 /// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
78 /// let config = Config::new(Environment::Dev);
79 /// let auth = AuthConfig::with_api_key("your-api-key".to_string());
80 /// let client = RainClient::new(config, auth)?;
81 ///
82 /// let company_id = Uuid::new_v4();
83 /// let application = client.get_company_application(&company_id).await?;
84 /// # Ok(())
85 /// # }
86 /// ```
87 #[cfg(feature = "async")]
88 pub async fn get_company_application(
89 &self,
90 company_id: &Uuid,
91 ) -> Result<CompanyApplicationResponse> {
92 let path = format!("/issuing/applications/company/{company_id}");
93 self.get(&path).await
94 }
95
96 /// Update a company application
97 ///
98 /// # Arguments
99 ///
100 /// * `company_id` - The unique identifier of the company
101 /// * `request` - The update request
102 ///
103 /// # Returns
104 ///
105 /// Returns a [`CompanyApplicationResponse`] containing the updated application information.
106 ///
107 /// # Examples
108 ///
109 /// ```no_run
110 /// use rain_sdk::{RainClient, Config, Environment, AuthConfig};
111 /// use rain_sdk::models::applications::UpdateCompanyApplicationRequest;
112 /// use uuid::Uuid;
113 ///
114 /// # #[cfg(feature = "async")]
115 /// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
116 /// let config = Config::new(Environment::Dev);
117 /// let auth = AuthConfig::with_api_key("your-api-key".to_string());
118 /// let client = RainClient::new(config, auth)?;
119 ///
120 /// let company_id = Uuid::new_v4();
121 /// let request = UpdateCompanyApplicationRequest {
122 /// name: Some("Updated Name".to_string()),
123 /// address: None,
124 /// entity: None,
125 /// };
126 /// let application = client.update_company_application(&company_id, &request).await?;
127 /// # Ok(())
128 /// # }
129 /// ```
130 #[cfg(feature = "async")]
131 pub async fn update_company_application(
132 &self,
133 company_id: &Uuid,
134 request: &UpdateCompanyApplicationRequest,
135 ) -> Result<CompanyApplicationResponse> {
136 let path = format!("/issuing/applications/company/{company_id}");
137 self.patch(&path, request).await
138 }
139
140 /// Update an ultimate beneficial owner
141 ///
142 /// # Arguments
143 ///
144 /// * `company_id` - The unique identifier of the company
145 /// * `ubo_id` - The unique identifier of the ultimate beneficial owner
146 /// * `request` - The update request
147 ///
148 /// # Returns
149 ///
150 /// Returns a [`CompanyApplicationResponse`] containing the updated application information.
151 ///
152 /// # Examples
153 ///
154 /// ```no_run
155 /// use rain_sdk::{RainClient, Config, Environment, AuthConfig};
156 /// use rain_sdk::models::applications::UpdateUltimateBeneficialOwnerRequest;
157 /// use uuid::Uuid;
158 ///
159 /// # #[cfg(feature = "async")]
160 /// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
161 /// let config = Config::new(Environment::Dev);
162 /// let auth = AuthConfig::with_api_key("your-api-key".to_string());
163 /// let client = RainClient::new(config, auth)?;
164 ///
165 /// let company_id = Uuid::new_v4();
166 /// let ubo_id = Uuid::new_v4();
167 /// let request = UpdateUltimateBeneficialOwnerRequest {
168 /// first_name: Some("John".to_string()),
169 /// last_name: Some("Doe".to_string()),
170 /// birth_date: None,
171 /// national_id: None,
172 /// country_of_issue: None,
173 /// email: None,
174 /// address: None,
175 /// };
176 /// let application = client.update_ultimate_beneficial_owner(&company_id, &ubo_id, &request).await?;
177 /// # Ok(())
178 /// # }
179 /// ```
180 #[cfg(feature = "async")]
181 pub async fn update_ultimate_beneficial_owner(
182 &self,
183 company_id: &Uuid,
184 ubo_id: &Uuid,
185 request: &UpdateUltimateBeneficialOwnerRequest,
186 ) -> Result<CompanyApplicationResponse> {
187 let path = format!("/issuing/applications/company/{company_id}/ubo/{ubo_id}");
188 self.patch(&path, request).await
189 }
190
191 /// Upload a document for a company application
192 ///
193 /// # Arguments
194 ///
195 /// * `company_id` - The unique identifier of the company
196 /// * `params` - Document upload parameters
197 ///
198 /// # Returns
199 ///
200 /// Returns a success response.
201 ///
202 /// # Examples
203 ///
204 /// ```no_run
205 /// use rain_sdk::{RainClient, Config, Environment, AuthConfig};
206 /// use rain_sdk::models::applications::DocumentUploadParams;
207 /// use uuid::Uuid;
208 ///
209 /// # #[cfg(feature = "async")]
210 /// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
211 /// let config = Config::new(Environment::Dev);
212 /// let auth = AuthConfig::with_api_key("your-api-key".to_string());
213 /// let client = RainClient::new(config, auth)?;
214 ///
215 /// let company_id = Uuid::new_v4();
216 /// let params = DocumentUploadParams {
217 /// document_type: "directorsRegistry".to_string(),
218 /// side: "front".to_string(),
219 /// country: Some("US".to_string()),
220 /// country_code: Some("US".to_string()),
221 /// name: Some("Document Name".to_string()),
222 /// file_path: "/path/to/file.pdf".to_string(),
223 /// };
224 /// client.upload_company_document(&company_id, ¶ms).await?;
225 /// # Ok(())
226 /// # }
227 /// ```
228 #[cfg(feature = "async")]
229 pub async fn upload_company_document(
230 &self,
231 company_id: &Uuid,
232 params: &DocumentUploadParams,
233 ) -> Result<serde_json::Value> {
234 let path = format!("/issuing/applications/company/{company_id}/document");
235 let form = self.build_company_document_form(params)?;
236 self.put_multipart(&path, form).await
237 }
238
239 /// Upload a document for an ultimate beneficial owner
240 ///
241 /// # Arguments
242 ///
243 /// * `company_id` - The unique identifier of the company
244 /// * `ubo_id` - The unique identifier of the ultimate beneficial owner
245 /// * `params` - Document upload parameters
246 ///
247 /// # Returns
248 ///
249 /// Returns a success response.
250 ///
251 /// # Examples
252 ///
253 /// ```no_run
254 /// use rain_sdk::{RainClient, Config, Environment, AuthConfig};
255 /// use rain_sdk::models::applications::DocumentUploadParams;
256 /// use uuid::Uuid;
257 ///
258 /// # #[cfg(feature = "async")]
259 /// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
260 /// let config = Config::new(Environment::Dev);
261 /// let auth = AuthConfig::with_api_key("your-api-key".to_string());
262 /// let client = RainClient::new(config, auth)?;
263 ///
264 /// let company_id = Uuid::new_v4();
265 /// let ubo_id = Uuid::new_v4();
266 /// let params = DocumentUploadParams {
267 /// document_type: "idCard".to_string(),
268 /// side: "front".to_string(),
269 /// country: Some("US".to_string()),
270 /// country_code: Some("US".to_string()),
271 /// name: None,
272 /// file_path: "/path/to/file.pdf".to_string(),
273 /// };
274 /// client.upload_ubo_document(&company_id, &ubo_id, ¶ms).await?;
275 /// # Ok(())
276 /// # }
277 /// ```
278 #[cfg(feature = "async")]
279 pub async fn upload_ubo_document(
280 &self,
281 company_id: &Uuid,
282 ubo_id: &Uuid,
283 params: &DocumentUploadParams,
284 ) -> Result<serde_json::Value> {
285 let path = format!("/issuing/applications/company/{company_id}/ubo/{ubo_id}/document");
286 let form = self.build_user_document_form(params)?;
287 self.put_multipart(&path, form).await
288 }
289
290 // ============================================================================
291 // User Application Methods
292 // ============================================================================
293
294 /// Create a user application
295 ///
296 /// # Arguments
297 ///
298 /// * `request` - The user application request
299 ///
300 /// # Returns
301 ///
302 /// Returns a [`UserApplicationResponse`] containing the application information.
303 ///
304 /// # Examples
305 ///
306 /// ```no_run
307 /// use rain_sdk::{RainClient, Config, Environment, AuthConfig};
308 /// use rain_sdk::models::applications::CreateUserApplicationRequest;
309 ///
310 /// # #[cfg(feature = "async")]
311 /// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
312 /// let config = Config::new(Environment::Dev);
313 /// let auth = AuthConfig::with_api_key("your-api-key".to_string());
314 /// let client = RainClient::new(config, auth)?;
315 ///
316 /// let request = CreateUserApplicationRequest {
317 /// ip_address: "127.0.0.1".to_string(),
318 /// occupation: "Engineer".to_string(),
319 /// annual_salary: "100000".to_string(),
320 /// account_purpose: "Business".to_string(),
321 /// expected_monthly_volume: "5000".to_string(),
322 /// is_terms_of_service_accepted: true,
323 /// sumsub_share_token: "token".to_string(),
324 /// wallet_address: None,
325 /// solana_address: None,
326 /// tron_address: None,
327 /// stellar_address: None,
328 /// chain_id: None,
329 /// contract_address: None,
330 /// source_key: None,
331 /// has_existing_documents: None,
332 /// };
333 /// let application = client.create_user_application(&request).await?;
334 /// # Ok(())
335 /// # }
336 /// ```
337 #[cfg(feature = "async")]
338 pub async fn create_user_application(
339 &self,
340 request: &CreateUserApplicationRequest,
341 ) -> Result<UserApplicationResponse> {
342 let path = "/issuing/applications/user";
343 self.post(path, request).await
344 }
345
346 /// Initiate a user application
347 ///
348 /// # Arguments
349 ///
350 /// * `request` - The initiate user application request
351 ///
352 /// # Returns
353 ///
354 /// Returns a [`UserApplicationResponse`] containing the application information.
355 ///
356 /// # Examples
357 ///
358 /// ```no_run
359 /// use rain_sdk::{RainClient, Config, Environment, AuthConfig};
360 /// use rain_sdk::models::applications::InitiateUserApplicationRequest;
361 ///
362 /// # #[cfg(feature = "async")]
363 /// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
364 /// let config = Config::new(Environment::Dev);
365 /// let auth = AuthConfig::with_api_key("your-api-key".to_string());
366 /// let client = RainClient::new(config, auth)?;
367 ///
368 /// let request = InitiateUserApplicationRequest {
369 /// first_name: Some("John".to_string()),
370 /// last_name: Some("Doe".to_string()),
371 /// email: Some("john@example.com".to_string()),
372 /// wallet_address: None,
373 /// };
374 /// let application = client.initiate_user_application(&request).await?;
375 /// # Ok(())
376 /// # }
377 /// ```
378 #[cfg(feature = "async")]
379 pub async fn initiate_user_application(
380 &self,
381 request: &InitiateUserApplicationRequest,
382 ) -> Result<UserApplicationResponse> {
383 let path = "/issuing/applications/user/initiate";
384 self.post(path, request).await
385 }
386
387 /// Get a user application by ID
388 ///
389 /// # Arguments
390 ///
391 /// * `user_id` - The unique identifier of the user
392 ///
393 /// # Returns
394 ///
395 /// Returns a [`UserApplicationResponse`] containing the application information.
396 ///
397 /// # Examples
398 ///
399 /// ```no_run
400 /// use rain_sdk::{RainClient, Config, Environment, AuthConfig};
401 /// use uuid::Uuid;
402 ///
403 /// # #[cfg(feature = "async")]
404 /// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
405 /// let config = Config::new(Environment::Dev);
406 /// let auth = AuthConfig::with_api_key("your-api-key".to_string());
407 /// let client = RainClient::new(config, auth)?;
408 ///
409 /// let user_id = Uuid::new_v4();
410 /// let application = client.get_user_application(&user_id).await?;
411 /// # Ok(())
412 /// # }
413 /// ```
414 #[cfg(feature = "async")]
415 pub async fn get_user_application(&self, user_id: &Uuid) -> Result<UserApplicationResponse> {
416 let path = format!("/issuing/applications/user/{user_id}");
417 self.get(&path).await
418 }
419
420 /// Update a user application
421 ///
422 /// # Arguments
423 ///
424 /// * `user_id` - The unique identifier of the user
425 /// * `request` - The update request
426 ///
427 /// # Returns
428 ///
429 /// Returns a [`UserApplicationResponse`] containing the updated application information.
430 ///
431 /// # Examples
432 ///
433 /// ```no_run
434 /// use rain_sdk::{RainClient, Config, Environment, AuthConfig};
435 /// use rain_sdk::models::applications::UpdateUserApplicationRequest;
436 /// use uuid::Uuid;
437 ///
438 /// # #[cfg(feature = "async")]
439 /// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
440 /// let config = Config::new(Environment::Dev);
441 /// let auth = AuthConfig::with_api_key("your-api-key".to_string());
442 /// let client = RainClient::new(config, auth)?;
443 ///
444 /// let user_id = Uuid::new_v4();
445 /// let request = UpdateUserApplicationRequest {
446 /// first_name: Some("John".to_string()),
447 /// last_name: None,
448 /// birth_date: None,
449 /// national_id: None,
450 /// country_of_issue: None,
451 /// address: None,
452 /// ip_address: None,
453 /// occupation: None,
454 /// annual_salary: None,
455 /// account_purpose: None,
456 /// expected_monthly_volume: None,
457 /// is_terms_of_service_accepted: None,
458 /// has_existing_documents: None,
459 /// };
460 /// let application = client.update_user_application(&user_id, &request).await?;
461 /// # Ok(())
462 /// # }
463 /// ```
464 #[cfg(feature = "async")]
465 pub async fn update_user_application(
466 &self,
467 user_id: &Uuid,
468 request: &UpdateUserApplicationRequest,
469 ) -> Result<UserApplicationResponse> {
470 let path = format!("/issuing/applications/user/{user_id}");
471 self.patch(&path, request).await
472 }
473
474 /// Upload a document for a user application
475 ///
476 /// # Arguments
477 ///
478 /// * `user_id` - The unique identifier of the user
479 /// * `params` - Document upload parameters
480 ///
481 /// # Returns
482 ///
483 /// Returns a success response.
484 ///
485 /// # Examples
486 ///
487 /// ```no_run
488 /// use rain_sdk::{RainClient, Config, Environment, AuthConfig};
489 /// use rain_sdk::models::applications::DocumentUploadParams;
490 /// use uuid::Uuid;
491 ///
492 /// # #[cfg(feature = "async")]
493 /// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
494 /// let config = Config::new(Environment::Dev);
495 /// let auth = AuthConfig::with_api_key("your-api-key".to_string());
496 /// let client = RainClient::new(config, auth)?;
497 ///
498 /// let user_id = Uuid::new_v4();
499 /// let params = DocumentUploadParams {
500 /// document_type: "idCard".to_string(),
501 /// side: "front".to_string(),
502 /// country: Some("US".to_string()),
503 /// country_code: Some("US".to_string()),
504 /// name: Some("ID Card".to_string()),
505 /// file_path: "/path/to/file.pdf".to_string(),
506 /// };
507 /// client.upload_user_document(&user_id, ¶ms).await?;
508 /// # Ok(())
509 /// # }
510 /// ```
511 #[cfg(feature = "async")]
512 pub async fn upload_user_document(
513 &self,
514 user_id: &Uuid,
515 params: &DocumentUploadParams,
516 ) -> Result<serde_json::Value> {
517 let path = format!("/issuing/applications/user/{user_id}/document");
518 let form = self.build_user_document_form(params)?;
519 self.put_multipart(&path, form).await
520 }
521
522 // ============================================================================
523 // Helper Methods
524 // ============================================================================
525
526 #[cfg(feature = "async")]
527 fn build_company_document_form(
528 &self,
529 params: &DocumentUploadParams,
530 ) -> Result<reqwest::multipart::Form> {
531 use std::fs;
532
533 let file_bytes = fs::read(¶ms.file_path).map_err(|e| {
534 crate::error::RainError::Other(anyhow::anyhow!("Failed to read file: {e}"))
535 })?;
536
537 let file_name = params
538 .file_path
539 .split('/')
540 .next_back()
541 .unwrap_or("document")
542 .to_string();
543
544 let part = reqwest::multipart::Part::bytes(file_bytes)
545 .file_name(file_name)
546 .mime_str("application/octet-stream")
547 .map_err(|e| {
548 crate::error::RainError::Other(anyhow::anyhow!("Invalid MIME type: {e}"))
549 })?;
550
551 let mut form = reqwest::multipart::Form::new()
552 .part("document", part)
553 .text("type", params.document_type.clone())
554 .text("side", params.side.clone());
555
556 if let Some(ref name) = params.name {
557 form = form.text("name", name.clone());
558 }
559
560 if let Some(ref country) = params.country {
561 form = form.text("country", country.clone());
562 }
563
564 if let Some(ref country_code) = params.country_code {
565 form = form.text("countryCode", country_code.clone());
566 }
567
568 Ok(form)
569 }
570
571 #[cfg(feature = "async")]
572 fn build_user_document_form(
573 &self,
574 params: &DocumentUploadParams,
575 ) -> Result<reqwest::multipart::Form> {
576 use std::fs;
577
578 let file_bytes = fs::read(¶ms.file_path).map_err(|e| {
579 crate::error::RainError::Other(anyhow::anyhow!("Failed to read file: {e}"))
580 })?;
581
582 let file_name = params
583 .file_path
584 .split('/')
585 .next_back()
586 .unwrap_or("document")
587 .to_string();
588
589 let part = reqwest::multipart::Part::bytes(file_bytes)
590 .file_name(file_name)
591 .mime_str("application/octet-stream")
592 .map_err(|e| {
593 crate::error::RainError::Other(anyhow::anyhow!("Invalid MIME type: {e}"))
594 })?;
595
596 let mut form = reqwest::multipart::Form::new()
597 .part("document", part)
598 .text("type", params.document_type.clone())
599 .text("side", params.side.clone());
600
601 if let Some(ref name) = params.name {
602 form = form.text("name", name.clone());
603 }
604
605 if let Some(ref country) = params.country {
606 form = form.text("country", country.clone());
607 }
608
609 if let Some(ref country_code) = params.country_code {
610 form = form.text("countryCode", country_code.clone());
611 }
612
613 Ok(form)
614 }
615
616 // ============================================================================
617 // Blocking Methods
618 // ============================================================================
619
620 /// Create a company application (blocking)
621 #[cfg(feature = "sync")]
622 pub fn create_company_application_blocking(
623 &self,
624 request: &CreateCompanyApplicationRequest,
625 ) -> Result<CompanyApplicationResponse> {
626 let path = "/issuing/applications/company";
627 self.post_blocking(path, request)
628 }
629
630 /// Get a company application by ID (blocking)
631 #[cfg(feature = "sync")]
632 pub fn get_company_application_blocking(
633 &self,
634 company_id: &Uuid,
635 ) -> Result<CompanyApplicationResponse> {
636 let path = format!("/issuing/applications/company/{company_id}");
637 self.get_blocking(&path)
638 }
639
640 /// Update a company application (blocking)
641 #[cfg(feature = "sync")]
642 pub fn update_company_application_blocking(
643 &self,
644 company_id: &Uuid,
645 request: &UpdateCompanyApplicationRequest,
646 ) -> Result<CompanyApplicationResponse> {
647 let path = format!("/issuing/applications/company/{company_id}");
648 self.patch_blocking(&path, request)
649 }
650
651 /// Update an ultimate beneficial owner (blocking)
652 #[cfg(feature = "sync")]
653 pub fn update_ultimate_beneficial_owner_blocking(
654 &self,
655 company_id: &Uuid,
656 ubo_id: &Uuid,
657 request: &UpdateUltimateBeneficialOwnerRequest,
658 ) -> Result<CompanyApplicationResponse> {
659 let path = format!("/issuing/applications/company/{company_id}/ubo/{ubo_id}");
660 self.patch_blocking(&path, request)
661 }
662
663 /// Create a user application (blocking)
664 #[cfg(feature = "sync")]
665 pub fn create_user_application_blocking(
666 &self,
667 request: &CreateUserApplicationRequest,
668 ) -> Result<UserApplicationResponse> {
669 let path = "/issuing/applications/user";
670 self.post_blocking(path, request)
671 }
672
673 /// Initiate a user application (blocking)
674 #[cfg(feature = "sync")]
675 pub fn initiate_user_application_blocking(
676 &self,
677 request: &InitiateUserApplicationRequest,
678 ) -> Result<UserApplicationResponse> {
679 let path = "/issuing/applications/user/initiate";
680 self.post_blocking(path, request)
681 }
682
683 /// Get a user application by ID (blocking)
684 #[cfg(feature = "sync")]
685 pub fn get_user_application_blocking(&self, user_id: &Uuid) -> Result<UserApplicationResponse> {
686 let path = format!("/issuing/applications/user/{user_id}");
687 self.get_blocking(&path)
688 }
689
690 /// Update a user application (blocking)
691 #[cfg(feature = "sync")]
692 pub fn update_user_application_blocking(
693 &self,
694 user_id: &Uuid,
695 request: &UpdateUserApplicationRequest,
696 ) -> Result<UserApplicationResponse> {
697 let path = format!("/issuing/applications/user/{user_id}");
698 self.patch_blocking(&path, request)
699 }
700}