Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/get all live opps #205

Merged
merged 9 commits into from
Nov 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -150,6 +150,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 @@ -161,10 +164,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 @@ -678,8 +685,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 @@ -699,7 +706,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 @@ -729,7 +736,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,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good catch, I wonder how this was working correctly so far 🤔

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
4 changes: 2 additions & 2 deletions sdk/js/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion sdk/js/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@pythnetwork/express-relay-js",
"version": "0.13.0",
"version": "0.13.1",
"description": "Utilities for interacting with the express relay protocol",
"homepage": "https://github.com/pyth-network/per/tree/main/sdk/js",
"author": "Douro Labs",
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
Loading