Skip to content

Commit

Permalink
Feat/get all live opps (#205)
Browse files Browse the repository at this point in the history
* auction server get all live opps changes

* typescript sdk changes

* python sdk changes

* update fromTime to date

* convert OPPORTUNITY_PAGE_SIZE_CAP to usize

* update constraint comment

* document with maximum

* bump versions

* unbump versions
  • Loading branch information
anihamde authored Nov 4, 2024
1 parent f35e44b commit 8e311d3
Show file tree
Hide file tree
Showing 9 changed files with 51 additions and 18 deletions.
19 changes: 13 additions & 6 deletions auction-server/src/opportunity/api.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use {
super::{
repository,
repository::OPPORTUNITY_PAGE_SIZE_CAP,
service::{
add_opportunity::AddOpportunityInput,
get_opportunities::GetOpportunitiesInput,
Expand Down Expand Up @@ -151,6 +151,9 @@ pub enum Opportunity {
fn default_opportunity_mode() -> OpportunityMode {
OpportunityMode::Live
}
fn default_limit() -> usize {
20
}
#[derive(Clone, Serialize, Deserialize, IntoParams)]
pub struct GetOpportunitiesQueryParams {
#[param(example = "op_sepolia", value_type = Option < String >)]
Expand All @@ -162,10 +165,14 @@ pub struct GetOpportunitiesQueryParams {
/// The permission key to filter the opportunities by. Used only in historical mode.
#[param(example = "0xdeadbeef", value_type = Option< String >)]
pub permission_key: Option<Bytes>,
/// The time to get the opportunities from. Used only in historical mode.
/// The time to get the opportunities from.
#[param(example="2024-05-23T21:26:57.329954Z", value_type = Option<String>)]
#[serde(default, with = "crate::serde::nullable_datetime")]
pub from_time: Option<OffsetDateTime>,
/// The maximum number of opportunities to return. Capped at 100; if more than 100 requested, at most 100 will be returned.
#[param(example = "20", value_type = usize, maximum = 100)]
#[serde(default = "default_limit")]
limit: usize,
}

// ----- Evm types -----
Expand Down Expand Up @@ -679,8 +686,8 @@ pub async fn post_opportunity(

/// Fetch opportunities ready for execution or historical opportunities
/// depending on the mode. You need to provide `chain_id` for historical mode.
/// Opportunities are sorted by creation time in ascending order in historical mode.
/// Total number of opportunities returned is limited by 20.
/// Opportunities are sorted by creation time in ascending order.
/// Total number of opportunities returned is capped by the server to preserve bandwidth.
#[utoipa::path(get, path = "/v1/opportunities", responses(
(status = 200, description = "Array of opportunities ready for bidding", body = Vec < Opportunity >),
(status = 400, response = ErrorBodyResponse),
Expand All @@ -700,7 +707,7 @@ pub async fn get_opportunities(
let opportunities_svm = store
.opportunity_service_svm
.get_opportunities(GetOpportunitiesInput {
query_params: query_params.0,
query_params: query_params.clone().0,
})
.await;

Expand Down Expand Up @@ -730,7 +737,7 @@ pub async fn get_opportunities(
Ok(Json(
opportunities
.into_iter()
.take(repository::OPPORTUNITY_PAGE_SIZE as usize)
.take(std::cmp::min(query_params.limit, OPPORTUNITY_PAGE_SIZE_CAP))
.collect(),
))
}
Expand Down
2 changes: 1 addition & 1 deletion auction-server/src/opportunity/entities/opportunity_evm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ impl TryFrom<repository::Opportunity<repository::OpportunityMetadataEvm>> for Op
Ok(OpportunityEvm {
core_fields: OpportunityCoreFields {
id: val.id,
creation_time: val.creation_time.assume_utc().unix_timestamp_nanos(),
creation_time: val.creation_time.assume_utc().unix_timestamp_nanos() / 1000,
permission_key: PermissionKey::from(val.permission_key),
chain_id: val.chain_id,
sell_tokens,
Expand Down
2 changes: 1 addition & 1 deletion auction-server/src/opportunity/entities/opportunity_svm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ impl TryFrom<repository::Opportunity<repository::OpportunityMetadataSvm>> for Op
Ok(OpportunitySvm {
core_fields: OpportunityCoreFields {
id: val.id,
creation_time: val.creation_time.assume_utc().unix_timestamp_nanos(),
creation_time: val.creation_time.assume_utc().unix_timestamp_nanos() / 1000,
permission_key: PermissionKey::from(val.permission_key),
chain_id: val.chain_id,
sell_tokens,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ impl<T: InMemoryStore> Repository<T> {
query.push_bind(from_time);
}
query.push(" ORDER BY creation_time ASC LIMIT ");
query.push_bind(super::OPPORTUNITY_PAGE_SIZE);
query.push_bind(super::OPPORTUNITY_PAGE_SIZE_CAP as i64);
let opps: Vec<models::Opportunity<<T::Opportunity as entities::Opportunity>::ModelMetadata>> = query
.build_query_as()
.fetch_all(db)
Expand Down
2 changes: 1 addition & 1 deletion auction-server/src/opportunity/repository/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ mod remove_opportunities;
mod remove_opportunity;

pub use models::*;
pub const OPPORTUNITY_PAGE_SIZE: i32 = 20;
pub const OPPORTUNITY_PAGE_SIZE_CAP: usize = 100;

#[derive(Debug)]
pub struct Repository<T: InMemoryStore> {
Expand Down
11 changes: 9 additions & 2 deletions auction-server/src/opportunity/service/get_opportunities.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,18 @@ impl<T: ChainType> Service<T> {
opportunity.clone()
})
.filter(|opportunity| {
if let Some(chain_id) = &query_params.chain_id {
let filter_time = if let Some(from_time) = query_params.from_time {
opportunity.creation_time >= from_time.unix_timestamp_nanos() / 1000
} else {
true
};

let filter_chain_id = if let Some(chain_id) = &query_params.chain_id {
opportunity.chain_id == *chain_id
} else {
true
}
};
filter_time && filter_chain_id
})
.collect()),
OpportunityMode::Historical => {
Expand Down
12 changes: 10 additions & 2 deletions sdk/js/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -265,12 +265,20 @@ export class Client {
/**
* Fetches opportunities
* @param chainId Chain id to fetch opportunities for. e.g: sepolia
* @param fromTime A date object representing the datetime to fetch opportunities from. If undefined, fetches from the beginning of time.
* @param limit Number of opportunities to return
* @returns List of opportunities
*/
async getOpportunities(chainId?: string): Promise<Opportunity[]> {
async getOpportunities(
chainId?: string,
fromTime?: Date,
limit?: number
): Promise<Opportunity[]> {
const client = createClient<paths>(this.clientOptions);
const opportunities = await client.GET("/v1/opportunities", {
params: { query: { chain_id: chainId } },
params: {
query: { chain_id: chainId, from_time: fromTime?.toISOString(), limit },
},
});
if (opportunities.data === undefined) {
throw new ClientError("No opportunities found");
Expand Down
11 changes: 8 additions & 3 deletions sdk/js/src/serverTypes.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export interface paths {
/**
* Fetch opportunities ready for execution or historical opportunities
* @description depending on the mode. You need to provide `chain_id` for historical mode.
* Opportunities are sorted by creation time in ascending order in historical mode.
* Opportunities are sorted by creation time in ascending order.
* Total number of opportunities returned is limited by 20.
*/
get: operations["get_opportunities"];
Expand Down Expand Up @@ -900,7 +900,7 @@ export interface operations {
/**
* Fetch opportunities ready for execution or historical opportunities
* @description depending on the mode. You need to provide `chain_id` for historical mode.
* Opportunities are sorted by creation time in ascending order in historical mode.
* Opportunities are sorted by creation time in ascending order.
* Total number of opportunities returned is limited by 20.
*/
get_opportunities: {
Expand All @@ -916,10 +916,15 @@ export interface operations {
*/
permission_key?: string | null;
/**
* @description The time to get the opportunities from. Used only in historical mode.
* @description The time to get the opportunities from.
* @example 2024-05-23T21:26:57.329954Z
*/
from_time?: string | null;
/**
* @description The maximum number of opportunities to return. Capped at 100.
* @example 20
*/
limit?: number;
};
};
responses: {
Expand Down
8 changes: 7 additions & 1 deletion sdk/python/express_relay/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -385,18 +385,24 @@ async def ws_handler(
future = self.ws_msg_futures.pop(msg_json["id"])
future.set_result(msg_json)

async def get_opportunities(self, chain_id: str | None = None) -> list[Opportunity]:
async def get_opportunities(self, chain_id: str | None = None, from_time: datetime | None = None, limit: int | None = None) -> list[Opportunity]:
"""
Connects to the server and fetches opportunities.
Args:
chain_id: The chain ID to fetch opportunities for. If None, fetches opportunities across all chains.
from_time: The datetime to fetch opportunities from. If None, fetches from the beginning of time.
limit: Number of opportunities to fetch. If None, uses the default server limit.
Returns:
A list of opportunities.
"""
params = {}
if chain_id:
params["chain_id"] = chain_id
if from_time:
params["from_time"] = from_time.astimezone().isoformat(timespec="microseconds")
if limit:
params["limit"] = str(limit)

async with httpx.AsyncClient(**self.http_options) as client:
resp = await client.get(
Expand Down

0 comments on commit 8e311d3

Please sign in to comment.