Skip to content

Commit

Permalink
cleanup and note taking
Browse files Browse the repository at this point in the history
  • Loading branch information
Autoparallel committed Apr 26, 2024
1 parent 44231d6 commit 1dd9131
Show file tree
Hide file tree
Showing 7 changed files with 168 additions and 154 deletions.
143 changes: 107 additions & 36 deletions kit/src/behaviors/allocate/mod.rs
Original file line number Diff line number Diff line change
@@ -1,74 +1,145 @@
use self::pool::AllocateOrDeallocate;
use super::*;

pub trait AllocateType<E>
pub trait AllocateType<P, E>
where
P: PoolType,
E: Send + 'static,
{
// TODO: This should probably be how we do it, but this generic `P` gets
// annoying fn change_allocation_amount(&mut self, event: E) ->
// Option<P::AllocationData>;
fn change_allocation_amount(&mut self, event: E) -> Option<Vec<eI256>>;
fn change_allocation_amount(
&mut self,
event: E,
) -> Option<(AllocateOrDeallocate, P::AllocationData)>;
}

#[derive(Clone, Debug, Serialize, Deserialize)]
struct Allocate<A, E, S>
struct Allocate<S, A, P, E>
where
A: AllocateType<E>,
E: Send + 'static,
S: State,
A: AllocateType<P, E>,
P: PoolType,
E: Send + 'static,
{
pub data: S::Data,
pub allocate_type: A,
_phantom_a: PhantomData<A>,
_phantom_e: PhantomData<E>,
_phantom_p: PhantomData<P>,
}

// TODO: This is actually the exact same as the `swap::Config` so... maybe they
// can be combined.
#[derive(Debug, Serialize, Deserialize, State)]
pub struct Config<P: PoolType> {
pub allocation_data: P::AllocationData,
pub token_admin: String,
pub _phantom: PhantomData<P>,
}

#[derive(State)]
pub struct Processing<P, E>
where
P: PoolType,
E: Send + 'static,
{
pub pool: Pool<P>,
pub client: Arc<ArbiterMiddleware>,
pub messager: Messager,
_phantom: PhantomData<E>,
}

#[allow(unused_variables)]
// TODO: This start up is also very much the same as the `Swap` start up. More
// than likely, `Update`, `Swap`, and `Allocate` can all be combined into one
// type of behavior like a `Interact` behavior that just specializes to do
// different things.
#[async_trait::async_trait]
impl<A, P, E> Behavior<E> for Allocate<A, E, Config<P>>
impl<A, P, E> Behavior<E> for Allocate<Config<P>, A, P, E>
where
A: AllocateType<E> + Send,
P: PoolType + Send,
A: AllocateType<P, E> + Send,
P: PoolType + Send + Sync,
E: Send + 'static,
{
type Processor = Allocate<A, E, Processing<P, E>>;
type Processor = Allocate<PoolProcessing<P>, A, P, E>;
async fn startup(
mut self,
client: Arc<ArbiterMiddleware>,
messager: Messager,
mut messager: Messager,
) -> Result<Self::Processor> {
todo!();
// TODO: Here we probably need to filter on the `PoolCreation` so that we get
// the correct pool.
let completed_todo = GetPoolTodo::<P>::complete(&mut messager).await;
let (deployment_data, pool_creation) = (
completed_todo.deployment_data.unwrap(),
completed_todo.pool_creation.unwrap(),
);

let (strategy_contract, solver_contract) =
P::get_contracts(&deployment_data, client.clone());
let dfmm = DFMM::new(deployment_data.dfmm, client.clone());

// TODO: This sort of approval and token loop is also repeated in other places
// like `Swap` and `Allocate`.
// Get the intended tokens for the pool and do approvals.
let mut tokens: Vec<ArbiterToken<ArbiterMiddleware>> = Vec::new();
for token_address in pool_creation.tokens.into_iter() {
let token = ArbiterToken::new(token_address, client.clone());
let name = token.name().call().await?;
messager
.send(
To::Agent(self.data.token_admin.clone()),
TokenAdminQuery::MintRequest(MintRequest {
token: name,
mint_to: client.address(),
mint_amount: parse_ether(100)?,
}),
)
.await
.unwrap();
assert_eq!(
messager.get_next::<Response>().await.unwrap().data,
Response::Success
);
token
.approve(dfmm.address(), MAX)
.send()
.await
.unwrap()
.await
.unwrap();

tokens.push(token);
}

// build pool for processor and stream
let pool = Pool::<P> {
id: pool_creation.id,
dfmm,
instance: P::create_instance(strategy_contract, solver_contract, pool_creation.params),
tokens,
liquidity_token: ERC20::new(pool_creation.liquidity_token, client.clone()),
};

let processor = Self::Processor {
data: PoolProcessing {
messager,
client,
pool,
},
allocate_type: self.allocate_type,
_phantom_e: PhantomData,
_phantom_p: PhantomData,
};

Ok(processor)
}
}

#[async_trait::async_trait]
impl<A, P, E> Processor<E> for Allocate<A, E, Processing<P, E>>
impl<A, P, E> Processor<E> for Allocate<PoolProcessing<P>, A, P, E>
where
A: AllocateType<E> + Send,
P: PoolType + Send,
A: AllocateType<P, E> + Send,
P: PoolType + Send + Sync,
E: Send + 'static,
{
async fn get_stream(&mut self) -> Result<Option<EventStream<E>>> {
todo!("We have not implemented the 'get_stream' method yet for the 'Allocate' behavior.");
default async fn get_stream(&mut self) -> Result<Option<EventStream<E>>> {
Ok(None)
}
async fn process(&mut self, _event: E) -> Result<ControlFlow> {
Ok(ControlFlow::Halt)
default async fn process(&mut self, event: E) -> Result<ControlFlow> {
if let Some((allocate_or_deallocate, allocation_data)) =
self.allocate_type.change_allocation_amount(event)
{
self.data
.pool
.change_allocation(allocate_or_deallocate, allocation_data)
.await?;
}

Ok(ControlFlow::Continue)
}
}
12 changes: 7 additions & 5 deletions kit/src/behaviors/creator.rs → kit/src/behaviors/create.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use super::*;
use crate::behaviors::token::Response;

#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct Create<S: State> {
Expand Down Expand Up @@ -28,14 +27,14 @@ where
) -> Result<Self::Processor> {
// Receive the `DeploymentData` from the `Deployer` agent and use it to get the
// contracts.
debug!("Starting the creator");
let deployment_data = messager.get_next::<DeploymentData>().await?.data;

debug!("Creator: Received deployment data {:?}", deployment_data);
let (strategy_contract, solver_contract) =
P::get_contracts(&deployment_data, client.clone());
let dfmm = DFMM::new(deployment_data.dfmm, client.clone());

// TODO: This sort of approval and token loop is also repeated in other places
// like `Swap` and `Allocate`.
// Get the intended tokens for the pool and do approvals.
let mut tokens = Vec::new();
for tkn in self.data.token_list.drain(..) {
Expand Down Expand Up @@ -75,16 +74,19 @@ where

tokens.push(token);
}
// TODO: There is a bit of a misleading thing happening here. The pool
// controller does indeed get set correctly, however, there are some other
// structs that may show incorrect data. This should be consolidated and
// fixed!!!
debug!(
"Setting Controller Address to self address: {:?}",
"Setting controller Address to self address: {:?}",
client.address()
);
if self.data.base_config.controller == eAddress::zero() {
self.data.base_config.controller = client.address();
}
let params = P::set_controller(self.data.params.clone(), client.address());

debug!("creating pool...");
let pool = Pool::<P>::new(
self.data.base_config.clone(),
params.clone(),
Expand Down
17 changes: 8 additions & 9 deletions kit/src/behaviors/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@ use arbiter_engine::{
};
#[allow(unused)]
use arbiter_macros::{Behaviors, State};
use bindings::{arbiter_token::ArbiterToken, dfmm::DFMM};
use bindings::{arbiter_token::ArbiterToken, dfmm::DFMM, erc20::ERC20};
use ethers::utils::parse_ether;
pub use token::{MintRequest, TokenAdminQuery};
pub use token::{MintRequest, Response, TokenAdminQuery};

use self::{
creator::Create,
create::Create,
deploy::{Deploy, DeploymentData},
pool::{PoolCreation, PoolType},
token::TokenAdmin,
Expand All @@ -21,24 +21,20 @@ use super::*;
pub const MAX: eU256 = eU256::MAX;

pub mod allocate;
pub mod creator;
pub mod create;
pub mod deploy;
pub mod swap;
pub mod token;
pub mod update;

#[derive(Debug, Deserialize, Serialize)]
pub enum Behaviors<P: PoolType> {
Create(Create<creator::Config<P>>),
Create(Create<create::Config<P>>),
Deployer(Deploy),
TokenAdmin(TokenAdmin<token::Config>),
Swap(swap::Config<P>),
}

pub trait Configurable<T: for<'a> Deserialize<'a>> {
fn configure(data: T) -> Self;
}

#[derive(Debug, Deserialize, Serialize)]
#[serde(bound = "P: PoolType")]
pub enum MessageTypes<P>
Expand All @@ -55,6 +51,9 @@ where
Update(P::Parameters),
}

// TODO: This is used by `Allocate` and `Swap` at the moment, so it was moved
// here since it was more central. However, there is likely a better way to
// combine all of these things.
#[derive(Debug)]
struct GetPoolTodo<P: PoolType> {
deployment_data: Option<DeploymentData>,
Expand Down
34 changes: 13 additions & 21 deletions kit/src/behaviors/swap/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use self::{bindings::erc20::ERC20, pool::InputToken};
use super::*;
use crate::behaviors::token::Response;
use crate::pool::InputToken;

// TODO: This could depend on the `PoolType` as the `AllocateType` does.
pub trait SwapType<E> {
fn compute_swap_amount(&self, event: E) -> Option<(eU256, InputToken)>;
}
Expand All @@ -14,7 +14,7 @@ where
{
pub data: S::Data,
pub swap_type: T,
pub _phantom: PhantomData<E>,
_phantom: PhantomData<E>,
}

// Should also get some data necessary for mint amounts and what not.
Expand All @@ -27,28 +27,18 @@ where
pub _phantom: PhantomData<P>,
}

#[derive(Debug, Clone, State)]
pub struct Processing<P>
where
P: PoolType,
// T: SwapType<E>,
// E: Send + 'static,
{
pub messager: Messager,
pub client: Arc<ArbiterMiddleware>,
pub pool: Pool<P>,
// pub swap_type: T,
// _phantom: PhantomData<E>,
}

// TODO: This start up is also very much the same as the `Allocate` start up.
// More than likely, `Update`, `Swap`, and `Allocate` can all be combined into
// one type of behavior like a `Interact` behavior that just specializes to do
// different things.
#[async_trait::async_trait]
impl<P, T, E> Behavior<E> for Swap<Config<P>, T, E>
where
P: PoolType + Send + Sync,
T: SwapType<E> + Send + Clone,
E: Send + 'static,
{
type Processor = Swap<Processing<P>, T, E>;
type Processor = Swap<PoolProcessing<P>, T, E>;
async fn startup(
mut self,
client: Arc<ArbiterMiddleware>,
Expand All @@ -66,6 +56,8 @@ where
P::get_contracts(&deployment_data, client.clone());
let dfmm = DFMM::new(deployment_data.dfmm, client.clone());

// TODO: This sort of approval and token loop is also repeated in other places
// like `Allocate` and `Create`.
// Get the intended tokens for the pool and do approvals.
let mut tokens: Vec<ArbiterToken<ArbiterMiddleware>> = Vec::new();
for token_address in pool_creation.tokens.into_iter() {
Expand Down Expand Up @@ -107,7 +99,7 @@ where
};

let processor = Self::Processor {
data: Processing {
data: PoolProcessing {
messager,
client,
pool,
Expand All @@ -123,7 +115,7 @@ where
/// This is the default implementation for any processor that takes in some
/// event E and will work for the `Swap` struct.
#[async_trait::async_trait]
impl<P, T, E> Processor<E> for Swap<Processing<P>, T, E>
impl<P, T, E> Processor<E> for Swap<PoolProcessing<P>, T, E>
where
P: PoolType + Send + Sync,
T: SwapType<E> + Send + Clone,
Expand Down Expand Up @@ -154,7 +146,7 @@ where
/// `SwapType` as long as it streams `Message`s. If you need to stream something
/// else, just copy this specialization and use whatever stream item you'd like!
#[async_trait::async_trait]
impl<P, T> Processor<Message> for Swap<Processing<P>, T, Message>
impl<P, T> Processor<Message> for Swap<PoolProcessing<P>, T, Message>
where
P: PoolType + Send + Sync,
T: SwapType<Message> + Send + Clone,
Expand Down
Loading

0 comments on commit 1dd9131

Please sign in to comment.