use std::time::Duration;
use propamm::common::helpers::{
apply_slippage, deadline_in, format_ether, format_units, parse_address, parse_ether,
parse_units,
};
use propamm::common::tokens::{ETH_SENTINEL, USDC};
use propamm::router::SwapParams;
use propamm::{ContractClient, PropAmmRouter};
const USDC_DECIMALS: u32 = 6;
#[tokio::main(flavor = "current_thread")]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let rpc_url = std::env::var("RPC_URL").unwrap_or_else(|_| "http://localhost:8545".into());
let private_key = std::env::var("PRIVATE_KEY").unwrap_or_else(|_| {
"0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80".into()
});
let router_address = parse_address(
&std::env::var("ROUTER_ADDRESS")
.unwrap_or_else(|_| "0x4DdF368080CD7946db5b459aD591c350158175e1".into()),
)?;
let slippage_bps: u32 = std::env::var("SLIPPAGE_BPS")
.unwrap_or_else(|_| "50".into())
.parse()?;
let amount_in = parse_ether(&std::env::var("AMOUNT_IN").unwrap_or_else(|_| "1".into()))?;
let threshold = parse_units(
&std::env::var("THRESHOLD").map_err(|_| "THRESHOLD is required (USDC floor to sell at)")?,
USDC_DECIMALS,
)?;
let poll = Duration::from_secs(
std::env::var("POLL_SECS")
.unwrap_or_else(|_| "2".into())
.parse()?,
);
let client = ContractClient::connect_with_signer(&rpc_url, &private_key)?;
let me = client.signer_address().expect("signer configured");
let router = PropAmmRouter::new(client, router_address);
println!(
"watching: sell {} ETH when its quote drops below {} USDC (every {}s)",
format_ether(amount_in),
format_units(threshold, USDC_DECIMALS),
poll.as_secs(),
);
let quote = loop {
let quote = router.quote(ETH_SENTINEL, USDC, amount_in).await?;
println!(
"quote: {} ETH -> {} USDC",
format_ether(amount_in),
format_units(quote.amount_out, USDC_DECIMALS),
);
if quote.amount_out < threshold {
break quote;
}
tokio::time::sleep(poll).await;
};
let result = router
.swap_and_wait(&SwapParams {
token_in: ETH_SENTINEL,
token_out: USDC,
amount_in,
amount_out_min: apply_slippage(quote.amount_out, slippage_bps)?,
recipient: me,
deadline: deadline_in(300), })
.await?;
println!(
"sold: received {} USDC via {:#x} (tx {:#x})",
format_units(result.amount_out, USDC_DECIMALS),
result.executed_venue,
result.hash,
);
Ok(())
}