diff --git a/Cargo.lock b/Cargo.lock index 1dd2455c..c22c09f0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -653,7 +653,7 @@ dependencies = [ [[package]] name = "auction-server" -version = "0.30.1" +version = "0.31.0" dependencies = [ "anchor-lang", "anchor-lang-idl", diff --git a/auction-server/Cargo.toml b/auction-server/Cargo.toml index 8863d68b..89dde203 100644 --- a/auction-server/Cargo.toml +++ b/auction-server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "auction-server" -version = "0.30.1" +version = "0.31.0" edition = "2021" license-file = "license.txt" diff --git a/auction-server/clickhouse_migrations/0015_alter_bid_limo_add_submission_time.sql b/auction-server/clickhouse_migrations/0015_alter_bid_limo_add_submission_time.sql new file mode 100644 index 00000000..68b25165 --- /dev/null +++ b/auction-server/clickhouse_migrations/0015_alter_bid_limo_add_submission_time.sql @@ -0,0 +1 @@ +ALTER TABLE bid_limo ADD COLUMN submission_time Nullable(DateTime64(6)); diff --git a/auction-server/clickhouse_migrations/0016_alter_bid_swap_add_submission_time.sql b/auction-server/clickhouse_migrations/0016_alter_bid_swap_add_submission_time.sql new file mode 100644 index 00000000..f0f29887 --- /dev/null +++ b/auction-server/clickhouse_migrations/0016_alter_bid_swap_add_submission_time.sql @@ -0,0 +1 @@ +ALTER TABLE bid_swap ADD COLUMN submission_time Nullable(DateTime64(6)); diff --git a/auction-server/src/auction/entities/bid.rs b/auction-server/src/auction/entities/bid.rs index 4648017c..82a5c2f1 100644 --- a/auction-server/src/auction/entities/bid.rs +++ b/auction-server/src/auction/entities/bid.rs @@ -206,10 +206,13 @@ pub struct Bid { pub id: BidId, pub chain_id: ChainId, pub initiation_time: OffsetDateTime, - pub profile_id: Option, + + pub profile_id: Option, + pub opportunity_id: Option, pub creation_time: OffsetDateTime, pub conclusion_time: Option, + pub submission_time: Option, pub amount: BidAmountSvm, pub status: BidStatusSvm, @@ -306,6 +309,13 @@ impl BidChainDataCreateSvm { BidChainDataCreateSvm::Swap(data) => &data.transaction, } } + + pub fn get_opportunity_id(&self) -> Option { + match self { + BidChainDataCreateSvm::OnChain(_) => None, + BidChainDataCreateSvm::Swap(data) => Some(data.opportunity_id), + } + } } pub type BidAmountSvm = u64; diff --git a/auction-server/src/auction/repository/add_bid.rs b/auction-server/src/auction/repository/add_bid.rs index e2c1d9c1..e2a5c31d 100644 --- a/auction-server/src/auction/repository/add_bid.rs +++ b/auction-server/src/auction/repository/add_bid.rs @@ -20,7 +20,7 @@ impl Repository { amount: &entities::BidAmountSvm, ) -> Result { let bid_model = Bid::new(bid_create.clone(), amount, chain_data); - let bid = bid_model.get_bid_entity(None).map_err(|e| { + let bid = bid_model.get_bid_entity(None, bid_create.chain_data.get_opportunity_id()).map_err(|e| { tracing::error!(error = e.to_string(), bid_create = ?bid_create, "Failed to convert bid to entity"); RestError::TemporarilyUnavailable })?; diff --git a/auction-server/src/auction/repository/add_bid_analytics.rs b/auction-server/src/auction/repository/add_bid_analytics.rs index c19d91d9..128482f4 100644 --- a/auction-server/src/auction/repository/add_bid_analytics.rs +++ b/auction-server/src/auction/repository/add_bid_analytics.rs @@ -53,6 +53,7 @@ impl Repository { bid_amount: bid.amount, auction_id: bid.status.get_auction_id(), + submission_time: bid.submission_time, conclusion_time: bid.conclusion_time, status: serde_json::to_string(&Svm::convert_bid_status(&bid.status))?, @@ -105,14 +106,14 @@ impl Repository { id: bid.id, creation_time: bid.creation_time, initiation_time: bid.initiation_time, + submission_time: bid.submission_time, permission_key: bid.chain_data.get_permission_key().to_string(), chain_id: bid.chain_id, transaction, bid_amount: bid.amount, auction_id: bid.status.get_auction_id(), - // TODO Fill this in - opportunity_id: None, + opportunity_id: bid.opportunity_id, conclusion_time: bid.conclusion_time, searcher_token_mint: mint_searcher.to_string(), diff --git a/auction-server/src/auction/repository/get_bid.rs b/auction-server/src/auction/repository/get_bid.rs index ad8b1f18..27defa96 100644 --- a/auction-server/src/auction/repository/get_bid.rs +++ b/auction-server/src/auction/repository/get_bid.rs @@ -14,7 +14,7 @@ impl Repository { None => None, }; - bid.get_bid_entity(auction).map_err(|e| { + bid.get_bid_entity(auction, None).map_err(|e| { tracing::error!(error = e.to_string(), bid = ?bid, "Failed to convert bid to entity"); RestError::TemporarilyUnavailable }) diff --git a/auction-server/src/auction/repository/get_bids.rs b/auction-server/src/auction/repository/get_bids.rs index feae1a7d..473a0dac 100644 --- a/auction-server/src/auction/repository/get_bids.rs +++ b/auction-server/src/auction/repository/get_bids.rs @@ -27,7 +27,7 @@ impl Repository { Some(auction_id) => auctions.clone().into_iter().find(|a| a.id == auction_id), None => None, }; - b.get_bid_entity(auction.clone()) + b.get_bid_entity(auction.clone(), None) .map_err(|e| { tracing::error!( error = e.to_string(), diff --git a/auction-server/src/auction/repository/models.rs b/auction-server/src/auction/repository/models.rs index c57d132d..cd2e7015 100644 --- a/auction-server/src/auction/repository/models.rs +++ b/auction-server/src/auction/repository/models.rs @@ -521,19 +521,32 @@ impl Bid { } } - pub fn get_bid_entity(&self, auction: Option) -> anyhow::Result { + pub fn get_bid_entity( + &self, + auction: Option, + opportunity_id: Option, + ) -> anyhow::Result { + let submission_time = auction + .as_ref() + .and_then(|a| a.submission_time) + .map(|t| t.assume_offset(UtcOffset::UTC)); + Ok(entities::Bid { - id: self.id, - chain_id: self.chain_id.clone(), + id: self.id, + chain_id: self.chain_id.clone(), + initiation_time: self.initiation_time.assume_offset(UtcOffset::UTC), - creation_time: self.creation_time.assume_offset(UtcOffset::UTC), + creation_time: self.creation_time.assume_offset(UtcOffset::UTC), conclusion_time: self .conclusion_time .map(|t| t.assume_offset(UtcOffset::UTC)), - profile_id: self.profile_id, + submission_time, - amount: Svm::get_bid_amount_entity(self)?, - status: Svm::get_bid_status_entity(self, auction)?, + profile_id: self.profile_id, + opportunity_id, + + amount: Svm::get_bid_amount_entity(self)?, + status: Svm::get_bid_status_entity(self, auction)?, chain_data: Svm::get_chain_data_entity(self)?, }) } @@ -844,6 +857,8 @@ pub struct BidAnalyticsSwap { #[serde(with = "clickhouse::serde::uuid::option")] pub auction_id: Option, + #[serde(with = "clickhouse::serde::time::datetime64::micros::option")] + pub submission_time: Option, #[serde(with = "clickhouse::serde::uuid::option")] pub opportunity_id: Option, #[serde(with = "clickhouse::serde::time::datetime64::micros::option")] @@ -890,6 +905,8 @@ pub struct BidAnalyticsLimo { #[serde(with = "clickhouse::serde::uuid::option")] pub auction_id: Option, #[serde(with = "clickhouse::serde::time::datetime64::micros::option")] + pub submission_time: Option, + #[serde(with = "clickhouse::serde::time::datetime64::micros::option")] pub conclusion_time: Option, pub status: String, diff --git a/auction-server/src/auction/repository/submit_auction.rs b/auction-server/src/auction/repository/submit_auction.rs index fccb29cc..623932f9 100644 --- a/auction-server/src/auction/repository/submit_auction.rs +++ b/auction-server/src/auction/repository/submit_auction.rs @@ -10,11 +10,19 @@ impl Repository { &self, auction: entities::Auction, transaction_hash: Signature, + winner_bid_ids: Vec, ) -> anyhow::Result { tracing::Span::current().record("auction_id", auction.id.to_string()); tracing::Span::current().record("tx_hash", format!("{:?}", transaction_hash)); - if let Some(updated_auction) = self.db.submit_auction(&auction, &transaction_hash).await? { + if let Some(mut updated_auction) = + self.db.submit_auction(&auction, &transaction_hash).await? + { + for bid in &mut updated_auction.bids { + if winner_bid_ids.contains(&bid.id) { + bid.submission_time = updated_auction.submission_time; + } + } self.update_in_memory_auction(updated_auction.clone()).await; Ok(updated_auction) } else { diff --git a/auction-server/src/auction/service/handle_auction.rs b/auction-server/src/auction/service/handle_auction.rs index 598fb60a..608e9fd2 100644 --- a/auction-server/src/auction/service/handle_auction.rs +++ b/auction-server/src/auction/service/handle_auction.rs @@ -84,7 +84,10 @@ impl Service { { Ok(tx_hash) => { tracing::debug!(tx_hash = ?tx_hash, "Submitted transaction"); - let auction = self.repo.submit_auction(auction, tx_hash).await?; + let auction = self + .repo + .submit_auction(auction, tx_hash, winner_bids.iter().map(|b| b.id).collect()) + .await?; join_all(auction.bids.iter().map(|bid| { self.update_bid_status(UpdateBidStatusInput { new_status: Service::get_new_status( diff --git a/auction-server/src/auction/service/submit_quote.rs b/auction-server/src/auction/service/submit_quote.rs index d031f2ca..aae8dc35 100644 --- a/auction-server/src/auction/service/submit_quote.rs +++ b/auction-server/src/auction/service/submit_quote.rs @@ -21,6 +21,7 @@ use { signature::Signature, transaction::VersionedTransaction, }, + std::vec, time::OffsetDateTime, }; @@ -69,7 +70,11 @@ impl Service { RestError::TemporarilyUnavailable })?; self.repo - .submit_auction(auction, bid.chain_data.transaction.signatures[0]) + .submit_auction( + auction, + bid.chain_data.transaction.signatures[0], + vec![bid.id], + ) .await .map_err(|e| { tracing::error!(error = ?e, "Error repo submitting auction"); @@ -134,7 +139,7 @@ impl Service { let tx_hash = signed_bid.chain_data.transaction.signatures[0]; let auction = self .repo - .submit_auction(auction, tx_hash) + .submit_auction(auction, tx_hash, vec![signed_bid.id]) .await .map_err(|e| { tracing::error!(error = ?e, "Error repo submitting auction"); diff --git a/auction-server/src/opportunity/service/get_quote.rs b/auction-server/src/opportunity/service/get_quote.rs index bd2aa78c..ef4a58ce 100644 --- a/auction-server/src/opportunity/service/get_quote.rs +++ b/auction-server/src/opportunity/service/get_quote.rs @@ -804,7 +804,9 @@ mod tests { initiation_time: OffsetDateTime::from_unix_timestamp(1200).unwrap(), creation_time: OffsetDateTime::from_unix_timestamp(1199).unwrap(), conclusion_time: None, + submission_time: None, profile_id: None, + opportunity_id: None, amount: amount.unwrap_or(100), status: BidStatusSvm::Pending, chain_data: BidChainDataSvm {