Skip to content

Commit

Permalink
Move business logic outside api
Browse files Browse the repository at this point in the history
  • Loading branch information
m30m committed Feb 28, 2024
1 parent 0a3bf6e commit af66e2b
Show file tree
Hide file tree
Showing 6 changed files with 218 additions and 232 deletions.
18 changes: 4 additions & 14 deletions auction-server/src/api.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,8 @@
use {
crate::{
api::{
bid::{
Bid,
BidResult,
},
liquidation::{
OpportunityBid,
OpportunityParamsWithMetadata,
},
bid::BidResult,
liquidation::OpportunityParamsWithMetadata,
ws::{
ClientMessage,
ClientRequest,
Expand All @@ -17,7 +11,9 @@ use {
ServerUpdateResponse,
},
},
auction::Bid,
config::RunOptions,
liquidation_adapter::OpportunityBid,
server::{
EXIT_CHECK_INTERVAL,
SHOULD_EXIT,
Expand Down Expand Up @@ -83,8 +79,6 @@ pub enum RestError {
BidNotFound,
/// Internal error occurred during processing the request
TemporarilyUnavailable,
/// A catch-all error for all other types of errors that could occur during processing.
Unknown,
}

impl RestError {
Expand Down Expand Up @@ -117,10 +111,6 @@ impl RestError {
StatusCode::SERVICE_UNAVAILABLE,
"This service is temporarily unavailable".to_string(),
),
RestError::Unknown => (
StatusCode::INTERNAL_SERVER_ERROR,
"An unknown error occurred processing the request".to_string(),
),
}
}
}
Expand Down
89 changes: 3 additions & 86 deletions auction-server/src/api/bid.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,11 @@ use {
RestError,
},
auction::{
simulate_bids,
SimulationError,
handle_bid,
Bid,
},
state::{
BidStatus,
SimulatedBid,
Store,
},
},
Expand All @@ -21,16 +20,7 @@ use {
},
Json,
},
ethers::{
abi::Address,
contract::EthError,
middleware::contract::ContractError,
signers::Signer,
types::{
Bytes,
U256,
},
},
ethers::signers::Signer,
serde::{
Deserialize,
Serialize,
Expand All @@ -43,79 +33,6 @@ use {
uuid::Uuid,
};

#[derive(Serialize, Deserialize, ToSchema, Clone, Debug)]
pub struct Bid {
/// The permission key to bid on.
#[schema(example = "0xdeadbeef", value_type=String)]
pub permission_key: Bytes,
/// The chain id to bid on.
#[schema(example = "sepolia", value_type=String)]
pub chain_id: String,
/// The contract address to call.
#[schema(example = "0xcA11bde05977b3631167028862bE2a173976CA11",value_type = String)]
pub contract: Address,
/// Calldata for the contract call.
#[schema(example = "0xdeadbeef", value_type=String)]
pub calldata: Bytes,
/// Amount of bid in wei.
#[schema(example = "10", value_type=String)]
#[serde(with = "crate::serde::u256")]
pub amount: U256,
}

pub async fn handle_bid(store: Arc<Store>, bid: Bid) -> Result<Uuid, RestError> {
let chain_store = store
.chains
.get(&bid.chain_id)
.ok_or(RestError::InvalidChainId)?;
let call = simulate_bids(
store.per_operator.address(),
chain_store.provider.clone(),
chain_store.config.clone(),
bid.permission_key.clone(),
vec![bid.contract],
vec![bid.calldata.clone()],
vec![bid.amount],
);

if let Err(e) = call.await {
return match e {
SimulationError::LogicalError { result, reason } => {
Err(RestError::SimulationError { result, reason })
}
SimulationError::ContractError(e) => match e {
ContractError::Revert(reason) => Err(RestError::BadParameters(format!(
"Contract Revert Error: {}",
String::decode_with_selector(&reason)
.unwrap_or("unable to decode revert".to_string())
))),
ContractError::MiddlewareError { e: _ } => Err(RestError::TemporarilyUnavailable),
ContractError::ProviderError { e: _ } => Err(RestError::TemporarilyUnavailable),
_ => Err(RestError::BadParameters(format!("Error: {}", e))),
},
};
};

let bid_id = Uuid::new_v4();
chain_store
.bids
.write()
.await
.entry(bid.permission_key.clone())
.or_default()
.push(SimulatedBid {
contract: bid.contract,
calldata: bid.calldata.clone(),
bid: bid.amount,
id: bid_id,
});
store
.bid_status_store
.set_and_broadcast(bid_id, BidStatus::Pending)
.await;
Ok(bid_id)
}

#[derive(Serialize, Deserialize, ToResponse, ToSchema, Clone)]
pub struct BidResult {
pub status: String,
Expand Down
125 changes: 4 additions & 121 deletions auction-server/src/api/liquidation.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,16 @@
use {
crate::{
api::{
bid::{
handle_bid,
BidResult,
},
bid::BidResult,
ws::UpdateEvent::NewOpportunity,
ErrorBodyResponse,
RestError,
},
config::ChainId,
liquidation_adapter::{
make_liquidator_calldata,
parse_revert_error,
handle_liquidation_bid,
verify_opportunity,
OpportunityBid,
},
state::{
LiquidationOpportunity,
Expand All @@ -31,15 +28,7 @@ use {
},
Json,
},
ethers::{
abi::Address,
core::types::Signature,
signers::Signer,
types::{
Bytes,
U256,
},
},
ethers::signers::Signer,
serde::{
Deserialize,
Serialize,
Expand All @@ -59,7 +48,6 @@ use {
uuid::Uuid,
};


/// Similar to OpportunityParams, but with the opportunity id included.
#[derive(Serialize, Deserialize, ToSchema, Clone, ToResponse)]
pub struct OpportunityParamsWithMetadata {
Expand Down Expand Up @@ -210,30 +198,6 @@ pub async fn get_opportunities(
Ok(opportunities.into())
}

#[derive(Serialize, Deserialize, ToSchema, Clone)]
pub struct OpportunityBid {
/// The opportunity permission key
#[schema(example = "0xdeadbeefcafe", value_type=String)]
pub permission_key: Bytes,
/// The bid amount in wei.
#[schema(example = "1000000000000000000", value_type=String)]
#[serde(with = "crate::serde::u256")]
pub amount: U256,
/// How long the bid will be valid for.
#[schema(example = "1000000000000000000", value_type=String)]
#[serde(with = "crate::serde::u256")]
pub valid_until: U256,
/// Liquidator address
#[schema(example = "0x5FbDB2315678afecb367f032d93F642f64180aa2", value_type=String)]
pub liquidator: Address,
#[schema(
example = "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef12",
value_type=String
)]
#[serde(with = "crate::serde::signature")]
pub signature: Signature,
}

/// Bid on liquidation opportunity
#[utoipa::path(post, path = "/v1/liquidation/opportunities/{opportunity_id}/bids", request_body=OpportunityBid,
params(("opportunity_id"=String, description = "Opportunity id to bid on")), responses(
Expand All @@ -255,84 +219,3 @@ pub async fn bid(
Err(e) => Err(e),
}
}

pub async fn handle_liquidation_bid(
store: Arc<Store>,
opportunity_id: OpportunityId,
opportunity_bid: &OpportunityBid,
) -> Result<Uuid, RestError> {
let opportunities = store
.liquidation_store
.opportunities
.get(&opportunity_bid.permission_key)
.ok_or(RestError::OpportunityNotFound)?
.clone();

let opportunity = opportunities
.iter()
.find(|o| o.id == opportunity_id)
.ok_or(RestError::OpportunityNotFound)?;

// TODO: move this logic to searcher side
if opportunity.bidders.contains(&opportunity_bid.liquidator) {
return Err(RestError::BadParameters(
"Liquidator already bid on this opportunity".to_string(),
));
}

let OpportunityParams::V1(params) = &opportunity.params;

let chain_store = store
.chains
.get(&params.chain_id)
.ok_or(RestError::InvalidChainId)?;

let per_calldata = make_liquidator_calldata(
params.clone(),
opportunity_bid.clone(),
chain_store.provider.clone(),
chain_store.config.adapter_contract,
)
.await
.map_err(|e| RestError::BadParameters(e.to_string()))?;
match handle_bid(
store.clone(),
crate::api::bid::Bid {
permission_key: params.permission_key.clone(),
chain_id: params.chain_id.clone(),
contract: chain_store.config.adapter_contract,
calldata: per_calldata,
amount: opportunity_bid.amount,
},
)
.await
{
Ok(id) => {
let opportunities = store
.liquidation_store
.opportunities
.get_mut(&opportunity_bid.permission_key);
if let Some(mut opportunities) = opportunities {
let opportunity = opportunities
.iter_mut()
.find(|o| o.id == opportunity_id)
.ok_or(RestError::OpportunityNotFound)?;
opportunity.bidders.insert(opportunity_bid.liquidator);
}
Ok(id)
}
Err(e) => match e {
RestError::SimulationError { result, reason } => {
let parsed = parse_revert_error(&result);
match parsed {
Some(decoded) => Err(RestError::BadParameters(decoded)),
None => {
tracing::info!("Could not parse revert reason: {}", reason);
Err(RestError::SimulationError { result, reason })
}
}
}
_ => Err(e),
},
}
}
18 changes: 8 additions & 10 deletions auction-server/src/api/ws.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,15 @@
use {
crate::{
api::{
bid::{
handle_bid,
Bid,
},
liquidation::{
handle_liquidation_bid,
OpportunityBid,
OpportunityParamsWithMetadata,
},
api::liquidation::OpportunityParamsWithMetadata,
auction::{
handle_bid,
Bid,
},
config::ChainId,
liquidation_adapter::{
handle_liquidation_bid,
OpportunityBid,
},
server::{
EXIT_CHECK_INTERVAL,
SHOULD_EXIT,
Expand Down
Loading

0 comments on commit af66e2b

Please sign in to comment.