Skip to content

Commit

Permalink
add math
Browse files Browse the repository at this point in the history
  • Loading branch information
anthontaylor committed Aug 28, 2024
1 parent 0399d7d commit 3f523c4
Show file tree
Hide file tree
Showing 6 changed files with 119 additions and 6 deletions.
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,5 @@ thiserror = "1.0.50"
tokio = { version = "1.39.2", features = ["full"] }
tokio-tungstenite = "0.16"
url = "2.5"
num-derive = "^0.3"
num-traits = "^0.2"
1 change: 0 additions & 1 deletion src/jupiter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,6 @@ impl Arber {
pub async fn jupiter_swap_tx(&self, quote: Quote) -> Result<VersionedTransaction> {
let url = format!("{}/swap", self.jupiter_quote_url.as_ref().unwrap());

println!("Quote: {:?}", quote);
let request = SwapRequest {
user_public_key: self.signer().pubkey(),
wrap_and_unwrap_SOL: Some(true),
Expand Down
1 change: 1 addition & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ mod etherfuse;
mod field_as_string;
mod jito;
mod jupiter;
mod math;
mod purchase;
mod run;
mod transaction;
Expand Down
106 changes: 106 additions & 0 deletions src/math.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
#![allow(dead_code)]

use anyhow::{anyhow, Result};
use std::fmt::Display;

pub fn checked_as_f64<T>(arg: T) -> Result<f64>
where
T: Display + num_traits::ToPrimitive + Clone,
{
let option: Option<f64> = num_traits::NumCast::from(arg.clone());
if let Some(res) = option {
Ok(res)
} else {
Err(anyhow!("Math overflow"))
}
}

pub fn checked_as_u64<T>(arg: T) -> Result<u64>
where
T: Display + num_traits::ToPrimitive + Clone,
{
let option: Option<u64> = num_traits::NumCast::from(arg.clone());
if let Some(res) = option {
Ok(res)
} else {
return Err(anyhow!("Math overflow"));
}
}

pub fn checked_div<T>(arg1: T, arg2: T) -> Result<T>
where
T: num_traits::PrimInt + Display,
{
if let Some(res) = arg1.checked_div(&arg2) {
Ok(res)
} else {
return Err(anyhow!("Math overflow"));
}
}

pub fn checked_float_div<T>(arg1: T, arg2: T) -> Result<T>
where
T: num_traits::Float + Display,
{
if arg2 == T::zero() {
return Err(anyhow!("Math overflow"));
}
let res = arg1 / arg2;
if !res.is_finite() {
return Err(anyhow!("Math overflow"));
} else {
Ok(res)
}
}

pub fn checked_mul<T>(arg1: T, arg2: T) -> Result<T>
where
T: num_traits::PrimInt + Display,
{
if let Some(res) = arg1.checked_mul(&arg2) {
Ok(res)
} else {
return Err(anyhow!("Math overflow"));
}
}

pub fn checked_float_mul<T>(arg1: T, arg2: T) -> Result<T>
where
T: num_traits::Float + Display,
{
let res = arg1 * arg2;
if !res.is_finite() {
return Err(anyhow!("Math overflow"));
} else {
Ok(res)
}
}

pub fn checked_powi(arg: f64, exp: i32) -> Result<f64> {
let res = if exp > 0 {
f64::powi(arg, exp)
} else {
// wrokaround due to f64::powi() not working properly on-chain with negative
// exponent
checked_float_div(1.0, f64::powi(arg, -exp))?
};
if res.is_finite() {
Ok(res)
} else {
return Err(anyhow!("Math overflow"));
}
}

pub fn to_ui_amount(amount: u64, decimals: u8) -> Result<f64> {
checked_float_div(
checked_as_f64(amount)?,
checked_powi(10.0, decimals as i32)?,
)
}

pub fn to_token_amount(ui_amount: f64, decimals: u8) -> Result<u64> {
checked_as_u64(checked_float_mul(
ui_amount,
checked_powi(10.0, decimals as i32)?,
)?)
}
13 changes: 8 additions & 5 deletions src/run.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::args::{JupiterQuoteArgs, RunArgs};
use crate::constants::{MIN_USDC_AMOUNT, STABLEBOND_DECIMALS, USDC_DECIMALS, USDC_MINT};
use crate::jupiter::Quote;
use crate::math;
use crate::{Arber, PurchaseArgs};

use anyhow::Result;
Expand All @@ -14,6 +15,7 @@ impl Arber {
let mut interval = tokio::time::interval(std::time::Duration::from_secs(60));
loop {
interval.tick().await;
println!("Checking for arb opportunity");
self.check_arb(args.clone()).await?;
}
}
Expand All @@ -22,12 +24,13 @@ impl Arber {
let usdc_balance = self.update_usdc_balance().await?;
// get etherfuse price of token
let stablebond_price_to_usd = self.get_etherfuse_price(args.etherfuse_token).await?;
let max_usdc_ui_amount_to_purchase = usdc_balance * 0.99;
let max_usdc_ui_amount_to_purchase = math::checked_float_mul(usdc_balance, 0.99)?;
let mut usdc_token_amount = to_token_amount(max_usdc_ui_amount_to_purchase, USDC_DECIMALS);

let stablebond_ui_amount = max_usdc_ui_amount_to_purchase / stablebond_price_to_usd;
let stablebond_ui_amount =
math::checked_float_div(max_usdc_ui_amount_to_purchase, stablebond_price_to_usd)?;
let mut stablebond_token_amount =
to_token_amount(stablebond_ui_amount, STABLEBOND_DECIMALS);
math::to_token_amount(stablebond_ui_amount, STABLEBOND_DECIMALS)?;
// get jupiter price of token based on quoted amount of USDC in users wallet
let (mut jup_price_token_to_usd, mut quote) = self
.sell_quote(args.clone(), stablebond_token_amount)
Expand All @@ -37,8 +40,8 @@ impl Arber {
&& (jup_price_token_to_usd < stablebond_price_to_usd)
{
// reduce the amount of tokens to purchase to see if arb exists on smaller trade
stablebond_token_amount /= 2;
usdc_token_amount /= 2;
usdc_token_amount = math::checked_div(usdc_token_amount, 2)?;
stablebond_token_amount = math::checked_div(stablebond_token_amount, 2)?;
(jup_price_token_to_usd, quote) = self
.sell_quote(args.clone(), stablebond_token_amount)
.await?;
Expand Down

0 comments on commit 3f523c4

Please sign in to comment.