penumbra_sdk_auction/component/
rpc.rs

1#![allow(unused)] // TODO: remove this when filling in the RPCs
2
3use penumbra_sdk_dex::{component::PositionRead, lp::position};
4use penumbra_sdk_proto::{
5    core::component::auction::v1 as pb,
6    core::component::auction::v1::{
7        query_service_server::QueryService, AuctionStateByIdRequest, AuctionStateByIdResponse,
8        AuctionStateByIdsRequest, AuctionStateByIdsResponse, DutchAuctionState,
9    },
10    DomainType,
11};
12
13use async_stream::try_stream;
14use futures::{StreamExt, TryStreamExt};
15use penumbra_sdk_proto::Message;
16use prost::Name;
17use std::pin::Pin;
18use tonic::Status;
19use tracing::instrument;
20
21use crate::auction::dutch::DutchAuction;
22
23use super::{action_handler::dutch, AuctionStoreRead};
24use cnidarium::Storage;
25
26pub struct Server {
27    storage: Storage,
28}
29
30impl Server {
31    pub fn new(storage: Storage) -> Self {
32        Self { storage }
33    }
34}
35
36#[tonic::async_trait]
37impl QueryService for Server {
38    #[instrument(skip(self, request))]
39    async fn auction_state_by_id(
40        &self,
41        request: tonic::Request<AuctionStateByIdRequest>,
42    ) -> Result<tonic::Response<AuctionStateByIdResponse>, Status> {
43        let state = self.storage.latest_snapshot();
44        let request = request.into_inner();
45
46        let id = request
47            .id
48            .ok_or_else(|| Status::invalid_argument("missing auction id"))?
49            .try_into()
50            .map_err(|_| Status::invalid_argument("invalid auction id"))?;
51
52        let raw_auction = state
53            .get_raw_auction(id)
54            .await
55            .ok_or_else(|| tonic::Status::not_found("auction data not found for specified id"))?;
56
57        // Note: we can easily optimize this by adding a lookup table for auction_id -> position id and
58        // save on deserialization or needing to "support" things in this rpc.
59        let maybe_lp = if raw_auction.type_url == pb::DutchAuction::type_url() {
60            let dutch_auction = DutchAuction::decode(raw_auction.value.as_ref())
61                .map_err(|_| tonic::Status::internal("error deserializing auction state"))?;
62
63            dutch_auction.state.current_position
64        } else {
65            return Err(tonic::Status::unimplemented("unrecognized auction type"));
66        };
67
68        let positions = match maybe_lp {
69            Some(id) => state
70                .position_by_id(&id)
71                .await
72                .map_err(|_| tonic::Status::internal("error fetching position state"))?
73                .into_iter()
74                .map(Into::into)
75                .collect(),
76            None => Vec::new(),
77        };
78
79        Ok(tonic::Response::new(AuctionStateByIdResponse {
80            auction: Some(raw_auction),
81            positions,
82        }))
83    }
84
85    type AuctionStateByIdsStream = Pin<
86        Box<dyn futures::Stream<Item = Result<AuctionStateByIdsResponse, tonic::Status>> + Send>,
87    >;
88
89    #[instrument(skip(self, request))]
90    async fn auction_state_by_ids(
91        &self,
92        request: tonic::Request<AuctionStateByIdsRequest>,
93    ) -> Result<tonic::Response<Self::AuctionStateByIdsStream>, Status> {
94        todo!()
95    }
96}