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;
pub struct Market<'a> {
terra: &'a Terra,
}
impl Market<'_> {
pub fn create(terra: &'_ Terra) -> Market<'_> {
Market { terra }
}
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)
}
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);
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)
}
}
}
}