use std::sync::Arc;
use async_trait::async_trait;
use serde::{Deserialize, Serialize};
use starknet::{
core::types::{Felt, StarknetError},
providers::Provider,
};
use super::jediswap::pool::JediswapPool;
use crate::amm::tenkswap::pool::TenkSwapPool;
#[async_trait]
pub trait AutomatedMarketMaker {
fn address(&self) -> Felt;
fn tokens(&self) -> Vec<Felt>;
async fn sync<P>(&mut self, provider: Arc<P>) -> Result<(), StarknetError>
where
P: Provider + Send + Sync;
fn calculate_price(&self, base_token: Felt, quote_token: Felt) -> Result<f64, StarknetError>;
async fn simulate_swap<P>(
&self,
base_token: Felt,
amount_in: Felt,
provider: Arc<P>,
) -> Result<Felt, StarknetError>
where
P: Provider + Send + Sync;
fn simulate_swap_mut(
&mut self,
base_token: Felt,
quote_token: Felt,
amount_in: Felt,
) -> Result<Felt, StarknetError>;
}
macro_rules! amm {
($($pool_type:ident),+ $(,)?) => {
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum AMM {
$($pool_type($pool_type),)+
}
#[async_trait]
impl AutomatedMarketMaker for AMM {
fn address(&self) -> Felt{
match self {
$(AMM::$pool_type(pool) => pool.address(),)+
}
}
fn tokens(&self) -> Vec<Felt> {
match self {
$(AMM::$pool_type(pool) => pool.tokens(),)+
}
}
async fn sync<P>(&mut self, middleware: Arc<P>) -> Result<(), StarknetError>
where
P: Provider + Send + Sync,
{
match self {
$(AMM::$pool_type(pool) => pool.sync(middleware).await,)+
}
}
async fn simulate_swap<P>(&self, base_token: Felt, amount_in: Felt, provider: Arc<P>) -> Result<Felt, StarknetError> where P: Provider + Send + Sync {
match self {
$(AMM::$pool_type(pool) => pool.simulate_swap(base_token, amount_in, provider).await,)+
}
}
fn simulate_swap_mut(&mut self, base_token: Felt, quote_token: Felt, amount_in: Felt) -> Result<Felt, StarknetError> {
match self {
$(AMM::$pool_type(pool) => pool.simulate_swap_mut(base_token, quote_token, amount_in),)+
}
}
fn calculate_price(&self, base_token: Felt, quote_token: Felt) -> Result<f64, StarknetError> {
match self {
$(AMM::$pool_type(pool) => pool.calculate_price(base_token, quote_token),)+
}
}
}
impl PartialEq for AMM {
fn eq(&self, other: &Self) -> bool {
self.address() == other.address()
}
}
impl Eq for AMM {}
};
}
amm!(JediswapPool, TenkSwapPool);