#![warn(missing_docs)]
pub mod arena;
pub mod config;
pub mod feed;
pub mod strategy;
pub mod engine;
use alloy::{
network::{Ethereum, EthereumWallet},
node_bindings::{Anvil, AnvilInstance},
primitives::{Address, Bytes, U256},
providers::{
fillers::{ChainIdFiller, FillProvider, GasFiller, JoinFill, NonceFiller, WalletFiller},
Identity, RootProvider,
},
transports::http::{Client, Http},
};
use crate::{engine::inspector::Inspector, types::PoolManager::PoolKey};
pub type AnvilProvider = FillProvider<
JoinFill<
JoinFill<JoinFill<JoinFill<Identity, GasFiller>, NonceFiller>, ChainIdFiller>,
WalletFiller<EthereumWallet>,
>,
RootProvider<Http<Client>>,
Http<Client>,
Ethereum,
>;
mod types {
#![allow(clippy::too_many_arguments)]
use alloy_sol_macro::sol;
use crate::types::{
Fetcher::PoolKey as FetcherPoolKey, PoolManager::PoolKey as ManagerPoolKey,
};
sol! {
#[sol(rpc)]
#[derive(Debug, Default)]
PoolManager,
"src/artifacts/PoolManager.json"
}
sol! {
#[sol(rpc)]
#[derive(Debug)]
LiquidExchange,
"src/artifacts/LiquidExchange.json"
}
sol! {
#[sol(rpc)]
#[derive(Debug)]
ArenaToken,
"src/artifacts/ArenaToken.json"
}
sol! {
#[sol(rpc)]
#[derive(Debug)]
Fetcher,
"src/artifacts/Fetcher.json"
}
impl From<FetcherPoolKey> for ManagerPoolKey {
fn from(fetcher: FetcherPoolKey) -> Self {
ManagerPoolKey {
currency0: fetcher.currency0,
currency1: fetcher.currency1,
fee: fetcher.fee,
tickSpacing: fetcher.tickSpacing,
hooks: fetcher.hooks,
}
}
}
impl From<ManagerPoolKey> for FetcherPoolKey {
fn from(manager: ManagerPoolKey) -> Self {
FetcherPoolKey {
currency0: manager.currency0,
currency1: manager.currency1,
fee: manager.fee,
tickSpacing: manager.tickSpacing,
hooks: manager.hooks,
}
}
}
}
#[derive(Debug, Clone)]
pub struct Signal {
pub manager: Address,
pub fetcher: Address,
pub pool: PoolKey,
pub current_value: f64,
pub step: Option<usize>,
pub tick: i32,
pub sqrt_price_x96: U256,
}
impl Signal {
pub fn new(
manager: Address,
fetcher: Address,
pool: PoolKey,
current_value: f64,
step: Option<usize>,
tick: i32,
sqrt_price_x96: U256,
) -> Self {
Self {
manager,
fetcher,
pool,
current_value,
step,
tick,
sqrt_price_x96,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::{
arena::{Arena, ArenaBuilder},
config::Config,
engine::{
arbitrageur::{Arbitrageur, DefaultArbitrageur, EmptyArbitrageur},
inspector::EmptyInspector,
},
feed::OrnsteinUhlenbeck,
strategy::Strategy,
};
struct StrategyMock;
impl<V> Strategy<V> for StrategyMock {
fn init(
&self,
_provider: AnvilProvider,
_signal: Signal,
_inspector: &mut Box<dyn Inspector<V>>,
) {
}
fn process(
&self,
_provider: AnvilProvider,
_signal: Signal,
_inspector: &mut Box<dyn Inspector<V>>,
) {
}
}
#[tokio::test]
async fn test_arena() {
let builder: ArenaBuilder<_> = ArenaBuilder::new();
let mut arena: Arena<f64> = builder
.with_strategy(Box::new(StrategyMock {}))
.with_fee(4000)
.with_tick_spacing(2)
.with_feed(Box::new(OrnsteinUhlenbeck::new(0.1, 0.1, 0.1, 0.1, 0.1)))
.with_inspector(Box::new(EmptyInspector {}))
.with_arbitrageur(Box::new(EmptyArbitrageur {}))
.build();
arena.run(Config::new(2)).await;
}
}