terra_rust_api/client/
market.rs

1use crate::client::core_types::Coin;
2
3use crate::{LCDResult, Message, Terra};
4use rust_decimal::Decimal;
5
6use crate::messages::market::MsgSwap;
7use futures::future::join_all;
8
9/// Market functions. mainly around swapping tokens
10pub struct Market<'a> {
11    terra: &'a Terra,
12}
13impl Market<'_> {
14    pub fn create(terra: &'_ Terra) -> Market<'_> {
15        Market { terra }
16    }
17    /// obtain how much a coin is worth in a secondary coin
18    pub async fn swap(&self, offer: &Coin, ask_denom: &str) -> anyhow::Result<LCDResult<Coin>> {
19        let response = self
20            .terra
21            .send_cmd::<LCDResult<Coin>>(
22                "/market/swap",
23                Some(&format!("?offer_coin={}&ask_denom={}", offer, ask_denom)),
24            )
25            .await?;
26        Ok(response)
27    }
28    /// generate a set of transactions to swap a account's tokens into another, as long as they are above a certain threshold
29    pub async fn generate_sweep_messages(
30        &self,
31        from: String,
32        to_coin: String,
33        threshold: Decimal,
34    ) -> anyhow::Result<Vec<Message>> {
35        let account_balances = self.terra.bank().balances(&from).await?;
36        let potential_coins = account_balances
37            .result
38            .into_iter()
39            .filter(|c| c.denom != to_coin);
40        //.collect::<Vec<Coin>>();
41        let into_currency_futures = potential_coins
42            .into_iter()
43            .map(|c| async {
44                let resp = self
45                    .terra
46                    .market()
47                    .swap(&c.clone(), &to_coin)
48                    .await
49                    .map(|f| (c, f.result));
50                resp
51            })
52            .collect::<Vec<_>>();
53
54        let into_currency = join_all(into_currency_futures).await;
55
56        let mut err = None;
57        let to_convert = &into_currency
58            .into_iter()
59            .flat_map(|f| match f {
60                Ok(coins) => {
61                    if coins.1.amount > threshold {
62                        Some(coins)
63                    } else {
64                        None
65                    }
66                }
67                Err(e) => {
68                    eprintln!("Error  {}", e);
69                    err = Some(e);
70                    None
71                }
72            })
73            .collect::<Vec<_>>();
74        match err {
75            Some(e) => Err(e),
76            None => {
77                let mut messages = Vec::new();
78                for swap_coins in to_convert {
79                    let message =
80                        MsgSwap::create(swap_coins.0.clone(), to_coin.clone(), from.clone())?;
81                    messages.push(message);
82                }
83                Ok(messages)
84            }
85        }
86    }
87}