Skip to content

Commit

Permalink
view: restore denom metadata queries to view service
Browse files Browse the repository at this point in the history
This was previously removed as being duplicative. But it isn't, because
something might want to request specifically from a view server, which can
respond with more opinionated denom metadata than the chain.
  • Loading branch information
hdevalence committed Jan 30, 2024
1 parent 5ea633f commit 391a8a8
Show file tree
Hide file tree
Showing 7 changed files with 928 additions and 421 deletions.
Binary file modified crates/cnidarium/src/gen/proto_descriptor.bin.no_lfs
Binary file not shown.
134 changes: 132 additions & 2 deletions crates/proto/src/gen/penumbra.view.v1alpha1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1282,6 +1282,39 @@ impl ::prost::Name for OwnedPositionIdsResponse {
::prost::alloc::format!("penumbra.view.v1alpha1.{}", Self::NAME)
}
}
/// Requests information on an asset by asset id
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct DenomMetadataByIdRequest {
/// The asset id to request information on.
#[prost(message, optional, tag = "2")]
pub asset_id: ::core::option::Option<super::super::core::asset::v1alpha1::AssetId>,
}
impl ::prost::Name for DenomMetadataByIdRequest {
const NAME: &'static str = "DenomMetadataByIdRequest";
const PACKAGE: &'static str = "penumbra.view.v1alpha1";
fn full_name() -> ::prost::alloc::string::String {
::prost::alloc::format!("penumbra.view.v1alpha1.{}", Self::NAME)
}
}
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct DenomMetadataByIdResponse {
/// If present, information on the requested asset.
///
/// If the requested asset was unknown, this field will not be present.
#[prost(message, optional, tag = "1")]
pub denom_metadata: ::core::option::Option<
super::super::core::asset::v1alpha1::DenomMetadata,
>,
}
impl ::prost::Name for DenomMetadataByIdResponse {
const NAME: &'static str = "DenomMetadataByIdResponse";
const PACKAGE: &'static str = "penumbra.view.v1alpha1";
fn full_name() -> ::prost::alloc::string::String {
::prost::alloc::format!("penumbra.view.v1alpha1.{}", Self::NAME)
}
}
/// Generated client implementations.
#[cfg(feature = "rpc")]
pub mod view_protocol_service_client {
Expand Down Expand Up @@ -1495,7 +1528,7 @@ pub mod view_protocol_service_client {
);
self.inner.server_streaming(req, path, codec).await
}
/// Queries for assets.
/// Queries for metadata about known assets.
/// Returns a stream of `AssetsResponse`s.
pub async fn assets(
&mut self,
Expand Down Expand Up @@ -1527,6 +1560,41 @@ pub mod view_protocol_service_client {
);
self.inner.server_streaming(req, path, codec).await
}
/// Query for metadata about a specific asset, by asset ID.
///
/// This is the same as the method on the shielded pool's `QueryService`, but exposing it
/// here allows a view server to provide more specific or opinionated asset metadata -- like
/// using an asset registry to provide tickers, symbols, etc.
pub async fn denom_metadata_by_id(
&mut self,
request: impl tonic::IntoRequest<super::DenomMetadataByIdRequest>,
) -> std::result::Result<
tonic::Response<super::DenomMetadataByIdResponse>,
tonic::Status,
> {
self.inner
.ready()
.await
.map_err(|e| {
tonic::Status::new(
tonic::Code::Unknown,
format!("Service was not ready: {}", e.into()),
)
})?;
let codec = tonic::codec::ProstCodec::default();
let path = http::uri::PathAndQuery::from_static(
"/penumbra.view.v1alpha1.ViewProtocolService/DenomMetadataById",
);
let mut req = request.into_request();
req.extensions_mut()
.insert(
GrpcMethod::new(
"penumbra.view.v1alpha1.ViewProtocolService",
"DenomMetadataById",
),
);
self.inner.unary(req, path, codec).await
}
/// Query for the current app parameters.
pub async fn app_parameters(
&mut self,
Expand Down Expand Up @@ -2236,12 +2304,24 @@ pub mod view_protocol_service_server {
>
+ Send
+ 'static;
/// Queries for assets.
/// Queries for metadata about known assets.
/// Returns a stream of `AssetsResponse`s.
async fn assets(
&self,
request: tonic::Request<super::AssetsRequest>,
) -> std::result::Result<tonic::Response<Self::AssetsStream>, tonic::Status>;
/// Query for metadata about a specific asset, by asset ID.
///
/// This is the same as the method on the shielded pool's `QueryService`, but exposing it
/// here allows a view server to provide more specific or opinionated asset metadata -- like
/// using an asset registry to provide tickers, symbols, etc.
async fn denom_metadata_by_id(
&self,
request: tonic::Request<super::DenomMetadataByIdRequest>,
) -> std::result::Result<
tonic::Response<super::DenomMetadataByIdResponse>,
tonic::Status,
>;
/// Query for the current app parameters.
async fn app_parameters(
&self,
Expand Down Expand Up @@ -2795,6 +2875,56 @@ pub mod view_protocol_service_server {
};
Box::pin(fut)
}
"/penumbra.view.v1alpha1.ViewProtocolService/DenomMetadataById" => {
#[allow(non_camel_case_types)]
struct DenomMetadataByIdSvc<T: ViewProtocolService>(pub Arc<T>);
impl<
T: ViewProtocolService,
> tonic::server::UnaryService<super::DenomMetadataByIdRequest>
for DenomMetadataByIdSvc<T> {
type Response = super::DenomMetadataByIdResponse;
type Future = BoxFuture<
tonic::Response<Self::Response>,
tonic::Status,
>;
fn call(
&mut self,
request: tonic::Request<super::DenomMetadataByIdRequest>,
) -> Self::Future {
let inner = Arc::clone(&self.0);
let fut = async move {
<T as ViewProtocolService>::denom_metadata_by_id(
&inner,
request,
)
.await
};
Box::pin(fut)
}
}
let accept_compression_encodings = self.accept_compression_encodings;
let send_compression_encodings = self.send_compression_encodings;
let max_decoding_message_size = self.max_decoding_message_size;
let max_encoding_message_size = self.max_encoding_message_size;
let inner = self.inner.clone();
let fut = async move {
let inner = inner.0;
let method = DenomMetadataByIdSvc(inner);
let codec = tonic::codec::ProstCodec::default();
let mut grpc = tonic::server::Grpc::new(codec)
.apply_compression_config(
accept_compression_encodings,
send_compression_encodings,
)
.apply_max_message_size_config(
max_decoding_message_size,
max_encoding_message_size,
);
let res = grpc.unary(method, req).await;
Ok(res)
};
Box::pin(fut)
}
"/penumbra.view.v1alpha1.ViewProtocolService/AppParameters" => {
#[allow(non_camel_case_types)]
struct AppParametersSvc<T: ViewProtocolService>(pub Arc<T>);
Expand Down
184 changes: 184 additions & 0 deletions crates/proto/src/gen/penumbra.view.v1alpha1.serde.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1660,6 +1660,190 @@ impl<'de> serde::Deserialize<'de> for broadcast_transaction_response::Confirmed
deserializer.deserialize_struct("penumbra.view.v1alpha1.BroadcastTransactionResponse.Confirmed", FIELDS, GeneratedVisitor)
}
}
impl serde::Serialize for DenomMetadataByIdRequest {
#[allow(deprecated)]
fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
use serde::ser::SerializeStruct;
let mut len = 0;
if self.asset_id.is_some() {
len += 1;
}
let mut struct_ser = serializer.serialize_struct("penumbra.view.v1alpha1.DenomMetadataByIdRequest", len)?;
if let Some(v) = self.asset_id.as_ref() {
struct_ser.serialize_field("assetId", v)?;
}
struct_ser.end()
}
}
impl<'de> serde::Deserialize<'de> for DenomMetadataByIdRequest {
#[allow(deprecated)]
fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
const FIELDS: &[&str] = &[
"asset_id",
"assetId",
];

#[allow(clippy::enum_variant_names)]
enum GeneratedField {
AssetId,
}
impl<'de> serde::Deserialize<'de> for GeneratedField {
fn deserialize<D>(deserializer: D) -> std::result::Result<GeneratedField, D::Error>
where
D: serde::Deserializer<'de>,
{
struct GeneratedVisitor;

impl<'de> serde::de::Visitor<'de> for GeneratedVisitor {
type Value = GeneratedField;

fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(formatter, "expected one of: {:?}", &FIELDS)
}

#[allow(unused_variables)]
fn visit_str<E>(self, value: &str) -> std::result::Result<GeneratedField, E>
where
E: serde::de::Error,
{
match value {
"assetId" | "asset_id" => Ok(GeneratedField::AssetId),
_ => Err(serde::de::Error::unknown_field(value, FIELDS)),
}
}
}
deserializer.deserialize_identifier(GeneratedVisitor)
}
}
struct GeneratedVisitor;
impl<'de> serde::de::Visitor<'de> for GeneratedVisitor {
type Value = DenomMetadataByIdRequest;

fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
formatter.write_str("struct penumbra.view.v1alpha1.DenomMetadataByIdRequest")
}

fn visit_map<V>(self, mut map_: V) -> std::result::Result<DenomMetadataByIdRequest, V::Error>
where
V: serde::de::MapAccess<'de>,
{
let mut asset_id__ = None;
while let Some(k) = map_.next_key()? {
match k {
GeneratedField::AssetId => {
if asset_id__.is_some() {
return Err(serde::de::Error::duplicate_field("assetId"));
}
asset_id__ = map_.next_value()?;
}
}
}
Ok(DenomMetadataByIdRequest {
asset_id: asset_id__,
})
}
}
deserializer.deserialize_struct("penumbra.view.v1alpha1.DenomMetadataByIdRequest", FIELDS, GeneratedVisitor)
}
}
impl serde::Serialize for DenomMetadataByIdResponse {
#[allow(deprecated)]
fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
use serde::ser::SerializeStruct;
let mut len = 0;
if self.denom_metadata.is_some() {
len += 1;
}
let mut struct_ser = serializer.serialize_struct("penumbra.view.v1alpha1.DenomMetadataByIdResponse", len)?;
if let Some(v) = self.denom_metadata.as_ref() {
struct_ser.serialize_field("denomMetadata", v)?;
}
struct_ser.end()
}
}
impl<'de> serde::Deserialize<'de> for DenomMetadataByIdResponse {
#[allow(deprecated)]
fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
const FIELDS: &[&str] = &[
"denom_metadata",
"denomMetadata",
];

#[allow(clippy::enum_variant_names)]
enum GeneratedField {
DenomMetadata,
}
impl<'de> serde::Deserialize<'de> for GeneratedField {
fn deserialize<D>(deserializer: D) -> std::result::Result<GeneratedField, D::Error>
where
D: serde::Deserializer<'de>,
{
struct GeneratedVisitor;

impl<'de> serde::de::Visitor<'de> for GeneratedVisitor {
type Value = GeneratedField;

fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(formatter, "expected one of: {:?}", &FIELDS)
}

#[allow(unused_variables)]
fn visit_str<E>(self, value: &str) -> std::result::Result<GeneratedField, E>
where
E: serde::de::Error,
{
match value {
"denomMetadata" | "denom_metadata" => Ok(GeneratedField::DenomMetadata),
_ => Err(serde::de::Error::unknown_field(value, FIELDS)),
}
}
}
deserializer.deserialize_identifier(GeneratedVisitor)
}
}
struct GeneratedVisitor;
impl<'de> serde::de::Visitor<'de> for GeneratedVisitor {
type Value = DenomMetadataByIdResponse;

fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
formatter.write_str("struct penumbra.view.v1alpha1.DenomMetadataByIdResponse")
}

fn visit_map<V>(self, mut map_: V) -> std::result::Result<DenomMetadataByIdResponse, V::Error>
where
V: serde::de::MapAccess<'de>,
{
let mut denom_metadata__ = None;
while let Some(k) = map_.next_key()? {
match k {
GeneratedField::DenomMetadata => {
if denom_metadata__.is_some() {
return Err(serde::de::Error::duplicate_field("denomMetadata"));
}
denom_metadata__ = map_.next_value()?;
}
}
}
Ok(DenomMetadataByIdResponse {
denom_metadata: denom_metadata__,
})
}
}
deserializer.deserialize_struct("penumbra.view.v1alpha1.DenomMetadataByIdResponse", FIELDS, GeneratedVisitor)
}
}
impl serde::Serialize for EphemeralAddressRequest {
#[allow(deprecated)]
fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
Expand Down
Binary file modified crates/proto/src/gen/proto_descriptor.bin.no_lfs
Binary file not shown.
Loading

0 comments on commit 391a8a8

Please sign in to comment.