Skip to content

Commit

Permalink
Merge pull request #31 from bcnmy/dev
Browse files Browse the repository at this point in the history
sync dev and main
  • Loading branch information
AmanRaj1608 authored Jul 16, 2024
2 parents 178c2ba + 87cb690 commit ed63519
Show file tree
Hide file tree
Showing 15 changed files with 2,966 additions and 106 deletions.
14 changes: 0 additions & 14 deletions .env.bak

This file was deleted.

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 bin/reflux/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,12 @@ log = "0.4.21"
simple_logger = "5.0.0"
clap = { version = "4.5.7", features = ["derive"] }
dotenv = "0.15.0"
futures-util = "0.3.30"

# workspace dependencies
account-aggregation = { workspace = true }
storage = { workspace = true }
config = { workspace = true }
routing-engine = { workspace = true }
api = { workspace = true }
thiserror = "1.0.61"
85 changes: 79 additions & 6 deletions bin/reflux/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
use std::collections::HashMap;
use std::fmt::Debug;
use std::sync::Arc;
use std::time::Duration;

use axum::http::Method;
use clap::Parser;
use dotenv::dotenv;
use futures_util::future::join_all;
use log::{debug, error, info};
use tokio::join;
use tokio::sync::Mutex;
use tower_http::cors::{Any, CorsLayer};

Expand All @@ -19,6 +22,10 @@ use routing_engine::settlement_engine::{generate_erc20_instance_map, SettlementE
use storage::{ControlFlow, MessageQueue, RedisClient};
use storage::mongodb_client::MongoDBClient;

use crate::utils::find_lowest_transfer_amount_usd;

mod utils;

#[derive(Parser, Debug)]
struct Args {
/// Run the Solver (default)
Expand All @@ -29,6 +36,10 @@ struct Args {
#[arg(short, long)]
indexer: bool,

/// Run the utility to find the lowest transfer amount in USD for all possible token pairs
#[arg(short, long)]
find_lowest_transfer_amounts_usd: bool,

/// Config file path
#[arg(short, long, default_value = "config.yaml")]
config: String,
Expand All @@ -48,11 +59,6 @@ async fn main() {
panic!("Cannot run both indexer and solver at the same time");
}

if !args.indexer && !args.solver {
args.solver = true;
debug!("Running Solver by default");
}

// Load configuration from yaml
let config =
Arc::new(Config::build_from_file(&args.config).expect("Failed to load config file"));
Expand All @@ -61,6 +67,11 @@ async fn main() {
run_indexer(config).await;
} else if args.solver {
run_solver(config).await;
} else if args.find_lowest_transfer_amounts_usd {
run_find_lowest_transfer_amount_usd(config).await;
} else {
info!("Running Solver by default");
run_solver(config).await;
}
}

Expand Down Expand Up @@ -228,4 +239,66 @@ async fn run_indexer(config: Arc<Config>) {
Ok(_) => info!("Indexer Job Completed"),
Err(e) => error!("Indexer Job Failed: {}", e),
};
}
}

async fn run_find_lowest_transfer_amount_usd(config: Arc<Config>) {
let redis_client = RedisClient::build(&config.infra.redis_url).await.unwrap();
let bungee_client = BungeeClient::new(&config.bungee.base_url, &config.bungee.api_key)
.expect("Failed to Instantiate Bungee Client");
let token_price_provider = Arc::new(Mutex::new(CoingeckoClient::new(
config.coingecko.base_url.clone(),
config.coingecko.api_key.clone(),
redis_client.clone(),
Duration::from_secs(config.coingecko.expiry_sec),
)));

let mut results = Vec::new();

// Intentionally not running these concurrently to avoid rate limiting
for (_, token_a) in config.tokens.iter() {
for (chain_a, _) in token_a.by_chain.iter() {
for (_, token_b) in config.tokens.iter() {
for (chain_b, _) in token_b.by_chain.iter() {
if token_a.symbol != token_b.symbol || chain_a != chain_b {
results.push((
(
*chain_a,
*chain_b,
token_a.symbol.clone(),
token_b.symbol.clone(),
false,
),
find_lowest_transfer_amount_usd(
&config,
*chain_a,
*chain_b,
&token_a.symbol,
&token_b.symbol,
false,
&bungee_client,
Arc::clone(&token_price_provider),
)
.await,
))
}
}
}
}
}

for result in results {
let (route, amount_result) = result;

match amount_result {
Ok(amount) => {
info!(
"Found lowest transfer amount in USD for token {} on chain {} to token {} on chain {}: {}",
route.2, route.0, route.3, route.1, amount
);
}
Err(e) => {
error!("Failed to find lowest transfer amount in USD: {}", e);
}
}
}
}
95 changes: 95 additions & 0 deletions bin/reflux/src/utils.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
use std::sync::Arc;

use log::{debug, info};
use thiserror::Error;
use tokio::sync::Mutex;

use config::Config;
use routing_engine::{CostType, Route, token_price};
use routing_engine::source::RouteSource;
use routing_engine::token_price::TokenPriceProvider;
use routing_engine::token_price::utils::Errors;

const TOKEN_AMOUNT_USD_LOWER_BOUND: f64 = 0.0;
const TOKEN_AMOUNT_USD_UPPER_BOUND: f64 = 25.0;
const DIFFERENCE_THRESHOLD_USD: f64 = 0.5;

pub async fn find_lowest_transfer_amount_usd<
Source: RouteSource,
PriceProvider: TokenPriceProvider,
>(
config: &Config,
from_chain_id: u32,
to_chain_id: u32,
from_token_id: &String,
to_token_id: &String,
is_smart_contract_deposit: bool,
source: &Source,
token_price_provider: Arc<Mutex<PriceProvider>>,
) -> Result<f64, FindLowestTransferAmountErr<Source, PriceProvider>> {
debug!(
"Finding lowest transfer amount in USD for token {} on chain {} to token {} on chain {}",
from_token_id, from_chain_id, to_token_id, to_chain_id
);

let mut low = TOKEN_AMOUNT_USD_LOWER_BOUND;
let mut high = TOKEN_AMOUNT_USD_UPPER_BOUND;

loop {
let route = Route::build(
config,
&from_chain_id,
&to_chain_id,
from_token_id,
to_token_id,
is_smart_contract_deposit,
)?;

if high - low < DIFFERENCE_THRESHOLD_USD {
info!("Found lowest transfer amount in USD: {} for route {}", high, route);
break Ok(high);
}

debug!("Trying with low: {} and high: {} for route {}", low, high, route);

let mid = (low + high) / 2.0;

let from_token_amount_in_wei = token_price::utils::get_token_amount_from_value_in_usd(
&config,
&token_price_provider.lock().await,
from_token_id,
from_chain_id,
&mid,
)
.await
.map_err(FindLowestTransferAmountErr::GetTokenAmountFromValueInUsdErr)?;

let result = source
.fetch_least_cost_route_and_cost_in_usd(
&route,
&from_token_amount_in_wei,
None,
None,
&CostType::Fee,
)
.await;

if result.is_err() {
low = mid;
} else {
high = mid;
}
}
}

#[derive(Error, Debug)]
pub enum FindLowestTransferAmountErr<T: RouteSource, U: TokenPriceProvider> {
#[error("Failed to build route")]
RouteBuildErr(#[from] routing_engine::RouteError),

#[error("Failed to fetch route cost")]
FetchRouteCostErr(T::FetchRouteCostError),

#[error("Failed to get token amount from value in usd")]
GetTokenAmountFromValueInUsdErr(Errors<U::Error>),
}
Loading

0 comments on commit ed63519

Please sign in to comment.