rango_sdk/quote/
mod.rs

1use serde::{Deserialize, Serialize};
2
3use crate::{
4    error::SdkErr,
5    meta::swappers::{SwapperMeta, SwapperType},
6};
7
8#[derive(Serialize, Deserialize, Debug)]
9#[serde(rename_all = "camelCase")]
10pub struct Token {
11    pub blockchain: String,
12    pub chain_id: Option<String>,
13    pub address: Option<String>,
14    pub symbol: String,
15    pub name: Option<String>,
16    pub decimals: u32,
17    pub image: String,
18    pub blockchain_image: String,
19    pub usd_price: Option<f64>,
20    pub is_popular: bool,
21}
22
23#[derive(Serialize, Deserialize, Debug, Clone)]
24pub struct Asset {
25    pub blockchain: String,
26    pub address: Option<String>,
27    pub symbol: String,
28}
29
30#[derive(Serialize, Deserialize, Debug)]
31#[serde(rename_all = "camelCase")]
32pub struct QuoteRequest {
33    pub from: Asset,
34    pub to: Asset,
35    pub amount: String,
36    pub swappers: Option<Vec<String>>,
37    pub swappers_exclude: Option<bool>,
38    pub swapper_groups: Option<Vec<String>>,
39    pub swappers_groups_exclude: Option<bool>,
40    pub messaging_protocols: Option<Vec<String>>,
41    pub source_contract: Option<String>,
42    pub destination_contract: Option<String>,
43    pub im_message: Option<String>,
44    pub contract_call: Option<bool>,
45}
46
47impl QuoteRequest {
48    pub fn into_qs(&self) -> Result<String, SdkErr> {
49        let from = match self.from.address.clone() {
50            None => format!("{}.{}", self.from.blockchain, self.from.symbol),
51            Some(address) => format!("{}.{}--{}", self.from.blockchain, self.from.symbol, address),
52        };
53        let to = match self.to.address.clone() {
54            None => format!("{}.{}", self.to.blockchain, self.to.symbol),
55            Some(address) => format!("{}.{}--{}", self.to.blockchain, self.to.symbol, address),
56        };
57
58        let request = QuoteRequestQs {
59            from,
60            to,
61            amount: self.amount.clone(),
62            contract_call: self.contract_call,
63            destination_contract: self.destination_contract.clone(),
64            im_message: self.im_message.clone(),
65            source_contract: self.source_contract.clone(),
66            messaging_protocols: match self.messaging_protocols.clone() {
67                Some(protocols) => Some(protocols.join(",")),
68                None => None,
69            },
70            swapper_groups: match self.swapper_groups.clone() {
71                Some(groups) => Some(groups.join(",")),
72                None => None,
73            },
74            swappers: match self.swappers.clone() {
75                Some(swappers) => Some(swappers.join(",")),
76                None => None,
77            },
78            swappers_exclude: self.swappers_exclude,
79            swappers_groups_exclude: self.swappers_groups_exclude,
80        };
81
82        let qs = serde_urlencoded::to_string(request)?;
83
84        Ok(qs)
85    }
86}
87
88#[derive(Serialize, Deserialize, Debug)]
89#[serde(rename_all = "camelCase")]
90struct QuoteRequestQs {
91    from: String,
92    to: String,
93    amount: String,
94    swappers: Option<String>,
95    swappers_exclude: Option<bool>,
96    swapper_groups: Option<String>,
97    swappers_groups_exclude: Option<bool>,
98    messaging_protocols: Option<String>,
99    source_contract: Option<String>,
100    destination_contract: Option<String>,
101    im_message: Option<String>,
102    contract_call: Option<bool>,
103}
104
105#[derive(Deserialize, Debug)]
106#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
107pub enum RoutingResultType {
108    Ok,
109    HighImpact,
110    NoRoute,
111    InputLimitIssue,
112}
113
114#[derive(Deserialize, Debug)]
115#[serde(rename_all = "camelCase")]
116pub struct QuoteResponse {
117    pub request_id: String,
118    pub result_type: RoutingResultType,
119    pub route: Option<QuoteSimulationResult>,
120    pub error: Option<String>,
121}
122
123#[derive(Deserialize, Debug)]
124#[serde(rename_all = "camelCase")]
125pub struct QuoteSimulationResult {
126    pub from: Token,
127    pub to: Token,
128    pub output_amount: String,
129    pub output_amount_min: String,
130    pub output_amount_usd: Option<f64>,
131    pub swapper: SwapperMeta,
132    pub path: Option<Vec<QuotePath>>,
133    pub fee: Vec<SwapFee>,
134    pub fee_usd: Option<f64>,
135    pub amount_restriction: Option<AmountRestriction>,
136    pub estimated_time_in_seconds: u64,
137}
138
139#[derive(Deserialize, Debug)]
140pub enum AmountRestrictionTypes {
141    INCLUSIVE,
142    EXCLUSIVE,
143}
144
145#[derive(Deserialize, Debug)]
146pub struct AmountRestriction {
147    pub min: Option<String>,
148    pub max: Option<String>,
149    pub r#type: AmountRestrictionTypes,
150}
151
152#[derive(Deserialize, Debug)]
153#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
154pub enum ExpenseType {
155    FromSourceWallet,
156    DecreaseFromOutput,
157    FromDestinationWallet,
158}
159
160#[derive(Deserialize, Debug)]
161#[serde(rename_all = "camelCase")]
162pub struct SwapFee {
163    pub name: String,
164    pub token: Token,
165    pub expense_type: ExpenseType,
166    pub amount: String,
167}
168
169#[derive(Deserialize, Debug)]
170#[serde(rename_all = "camelCase")]
171pub struct QuotePath {
172    pub from: Token,
173    pub to: Token,
174    pub swapper_type: SwapperType,
175    pub swapper: SwapperMeta,
176    pub expected_output: String,
177    pub estimated_time_in_seconds: u64,
178}