1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
use crate::client::core_types::Coin;

use crate::{LCDResult, Message, Terra};
use rust_decimal::Decimal;

use crate::messages::market::MsgSwap;
use futures::future::join_all;

/// Market functions. mainly around swapping tokens
pub struct Market<'a> {
    terra: &'a Terra,
}
impl Market<'_> {
    pub fn create(terra: &'_ Terra) -> Market<'_> {
        Market { terra }
    }
    /// obtain how much a coin is worth in a secondary coin
    pub async fn swap(&self, offer: &Coin, ask_denom: &str) -> anyhow::Result<LCDResult<Coin>> {
        let response = self
            .terra
            .send_cmd::<LCDResult<Coin>>(
                "/market/swap",
                Some(&format!(
                    "?offer_coin={}&ask_denom={}",
                    offer.to_string(),
                    ask_denom
                )),
            )
            .await?;
        Ok(response)
    }
    /// generate a set of transactions to swap a account's tokens into another, as long as they are above a certain threshold
    pub async fn generate_sweep_messages(
        &self,
        from: String,
        to_coin: String,
        threshold: Decimal,
    ) -> anyhow::Result<Vec<Message>> {
        let account_balances = self.terra.bank().balances(&from).await?;
        let potential_coins = account_balances
            .result
            .into_iter()
            .filter(|c| c.denom != to_coin);
        //.collect::<Vec<Coin>>();
        let into_currency_futures = potential_coins
            .into_iter()
            .map(|c| async {
                let resp = self
                    .terra
                    .market()
                    .swap(&c.clone(), &to_coin)
                    .await
                    .map(|f| (c, f.result));
                resp
            })
            .collect::<Vec<_>>();

        let into_currency = join_all(into_currency_futures).await;

        let mut err = None;
        let to_convert = &into_currency
            .into_iter()
            .flat_map(|f| match f {
                Ok(coins) => {
                    if coins.1.amount > threshold {
                        Some(coins)
                    } else {
                        None
                    }
                }
                Err(e) => {
                    eprintln!("Error  {}", e.to_string());
                    err = Some(e);
                    None
                }
            })
            .collect::<Vec<_>>();
        match err {
            Some(e) => Err(e),
            None => {
                let mut messages = Vec::new();
                for swap_coins in to_convert {
                    let message =
                        MsgSwap::create(swap_coins.0.clone(), to_coin.clone(), from.clone())?;
                    messages.push(message);
                }
                Ok(messages)
            }
        }
    }
}