use crate::tx_builder::TxBuilder;
use cosmrs::cosmwasm::MsgExecuteContract;
use cosmrs::tx::Msg;
use cosmrs::Coin;
use cosmwasm_std::{Addr, Uint128};
use serde::Serialize;
use super::client::RouterAdminClient;
use super::error::RouterError;
impl RouterAdminClient {
pub fn append_swap_exact_in_msg(
&self,
tx_builder: &mut TxBuilder,
swap_amount: u128,
swap_asset: String,
want_out: String,
minimum_base_out: Option<Uint128>,
receiver: Option<String>,
) -> Result<(), RouterError> {
let swap_amount = Coin::new(swap_amount, &swap_asset)?;
let receiver = receiver.map(Addr::unchecked);
let msg = ExecuteMsg {
swap_exact_in: SwapExactInMsg {
want_out,
minimum_base_out,
receiver,
},
};
let contract_msg = serde_json::to_vec(&msg).map_err(RouterError::SerdeJsonError)?;
let msg = MsgExecuteContract {
sender: tx_builder.account_id.clone(),
contract: self.public_router_client.router_contract_address.clone(),
msg: contract_msg,
funds: vec![swap_amount],
};
let msg = msg.to_any().map_err(RouterError::EyreError)?;
tx_builder.add_msg(msg);
Ok(())
}
}
#[derive(Serialize)]
struct SwapExactInMsg {
pub want_out: String,
pub minimum_base_out: Option<Uint128>,
pub receiver: Option<Addr>,
}
#[derive(Serialize)]
struct ExecuteMsg {
pub swap_exact_in: SwapExactInMsg,
}
#[cfg(test)]
mod tests {
use crate::market::client::MarketAdminClient;
use crate::oracle::client::OracleAdminClient;
use crate::router::client::RouterAdminClient;
use crate::test_utils::helpers::{
assert_event_attribute, TEST_ASSET_ARCH_SYMBOL, TEST_ASSET_ETH_SYMBOL,
TEST_ASSET_USDT_SYMBOL,
};
use crate::test_utils::test_scenario::TestScenario;
use crate::tx_builder::TxBuilder;
use cosmrs::tendermint::abci::Code;
use cosmrs::{AccountId, Coin};
use cosmwasm_std::{Decimal256, Uint128};
use serial_test::serial;
use std::ops::Add;
use std::str::FromStr;
use std::time::{Duration, SystemTime, UNIX_EPOCH};
#[tokio::test]
#[serial]
async fn test_append_swap_exact_in_msg() {
let mut test_scenario = TestScenario::new_from_config("config.json".to_string()).await;
let price_threshold_ratio = Decimal256::from_str("0.5").unwrap();
let price_expire_millis = Some(1000);
let oracle_contract_address = test_scenario
.instantiate_oracle_contract(price_threshold_ratio, price_expire_millis)
.await;
let default_protocol_fee = Decimal256::from_str("0.1").unwrap();
let default_lp_fee = Decimal256::from_str("0.1").unwrap();
let router_contract_address = test_scenario
.instantiate_router_contract(
oracle_contract_address.clone(),
oracle_contract_address.clone(),
default_protocol_fee,
default_lp_fee,
)
.await;
let oracle_client =
OracleAdminClient::from_scenario(&test_scenario, &oracle_contract_address)
.expect("Failed to create oracle admin client");
let price_expiry_time = SystemTime::now().add(Duration::from_secs(7200)); let price_expiry_timestamp = price_expiry_time
.duration_since(UNIX_EPOCH)
.expect("Converting to timestamp failed");
test_scenario.set_default_assets(&oracle_client).await;
test_scenario
.set_default_prices(&oracle_client, price_expiry_timestamp, "50000")
.await;
let router_client = RouterAdminClient::from_scenario(
&test_scenario,
router_contract_address.parse().unwrap(),
)
.expect("Failed to create router admin client");
test_scenario
.create_market(
&router_client,
TEST_ASSET_ARCH_SYMBOL,
&[TEST_ASSET_USDT_SYMBOL],
Uint128::new(1),
)
.await;
test_scenario
.create_market(
&router_client,
TEST_ASSET_USDT_SYMBOL,
&[TEST_ASSET_ARCH_SYMBOL, TEST_ASSET_ETH_SYMBOL],
Uint128::new(1),
)
.await;
test_scenario
.create_market(
&router_client,
TEST_ASSET_ETH_SYMBOL,
&[TEST_ASSET_USDT_SYMBOL],
Uint128::new(1),
)
.await;
let market_client = MarketAdminClient::from_scenario(&test_scenario).unwrap();
let admin_account = test_scenario.admin_account();
let markets = router_client.public_router_client.markets().await.unwrap();
for market in markets {
test_scenario
.deposit_base(
&market_client,
AccountId::from_str(market.market_address.as_ref()).unwrap(),
&admin_account,
Coin::new(10000000, &market.base_asset_symbol).unwrap(),
)
.await;
}
let account = router_client
.account(test_scenario.admin_address.clone())
.await
.expect("Failed to get account info");
let mut tx_builder = TxBuilder::new(
test_scenario.admin_mnemonic.clone(),
test_scenario.chain_prefix.clone(),
test_scenario.chain_id.clone(),
test_scenario.derivation_path,
account.sequence,
account.account_number,
)
.expect("Failed to create tx builder");
let want_out = TEST_ASSET_USDT_SYMBOL;
let minimum_base_out = Some(Uint128::new(10));
let receiver = Some(test_scenario.admin_address.clone());
router_client
.append_swap_exact_in_msg(
&mut tx_builder,
10,
TEST_ASSET_ARCH_SYMBOL.to_string(),
want_out.to_string(),
minimum_base_out,
receiver.clone(),
)
.expect("Failed to append swap exact in msg");
tx_builder.set_memo("From test_append_swap_exact_in_msg".to_string());
let gas = 500_000u64;
let amount = 80_000_000_000_000_000u128;
tx_builder.set_fee(amount, &test_scenario.chain_denom, gas);
let signed_bytes = tx_builder
.get_signed_bytes()
.expect("Failed to get signed bytes");
let response = router_client
.broadcast_tx(signed_bytes)
.await
.expect("Failed to broadcast tx");
match response.tx_result.code {
Code::Ok => {
println!("Transaction successful: {:?}", response.hash);
println!("Transaction response: {:?}", response);
let swap_exact_in_event = response
.tx_result
.events
.iter()
.find(|ev| ev.kind == "wasm")
.expect("Failed to find update swap exact in event");
assert_event_attribute(swap_exact_in_event, "quote_asset", TEST_ASSET_ARCH_SYMBOL);
assert_event_attribute(swap_exact_in_event, "base_asset", TEST_ASSET_USDT_SYMBOL);
assert_event_attribute(swap_exact_in_event, "amount_in", "10");
}
Code::Err(code) => {
panic!(
"Transaction failed with code: {:?} response: {:?}",
code, response
);
}
}
let want_out = TEST_ASSET_USDT_SYMBOL;
let minimum_base_out = Some(10);
let response = test_scenario
.swap_exact_in(
&router_client,
want_out,
minimum_base_out,
receiver,
10,
TEST_ASSET_ETH_SYMBOL.to_string(),
)
.await;
match response.tx_result.code {
Code::Ok => {
println!("Transaction successful: {:?}", response.hash);
println!("Transaction response: {:?}", response);
let swap_exact_in_event = response
.tx_result
.events
.iter()
.find(|ev| ev.kind == "wasm")
.expect("Failed to find update swap exact in event");
assert_event_attribute(swap_exact_in_event, "quote_asset", TEST_ASSET_ETH_SYMBOL);
assert_event_attribute(swap_exact_in_event, "base_asset", TEST_ASSET_USDT_SYMBOL);
assert_event_attribute(swap_exact_in_event, "amount_in", "10");
}
Code::Err(code) => {
panic!(
"Transaction failed with code: {:?} response: {:?}",
code, response
);
}
}
}
}