penumbra_sdk_shielded_pool/component/rpc/
transfer_query.rs1use anyhow::Context;
2use async_trait::async_trait;
3use futures::StreamExt;
4use ibc_proto::ibc::applications::transfer::v1::query_server::Query as TransferQuery;
5use ibc_proto::ibc::apps::transfer::v1::{
6 DenomTrace, QueryDenomHashRequest, QueryDenomHashResponse, QueryDenomTraceRequest,
7 QueryDenomTraceResponse, QueryDenomTracesRequest, QueryDenomTracesResponse,
8 QueryEscrowAddressRequest, QueryEscrowAddressResponse, QueryParamsRequest, QueryParamsResponse,
9 QueryTotalEscrowForDenomRequest, QueryTotalEscrowForDenomResponse,
10};
11use penumbra_sdk_asset::asset::Metadata;
12use penumbra_sdk_proto::StateReadProto as _;
13
14use crate::state_key;
15
16use super::Server;
17
18#[async_trait]
19impl TransferQuery for Server {
20 async fn total_escrow_for_denom(
21 &self,
22 _: tonic::Request<QueryTotalEscrowForDenomRequest>,
23 ) -> std::result::Result<tonic::Response<QueryTotalEscrowForDenomResponse>, tonic::Status> {
24 Err(tonic::Status::unimplemented("not implemented"))
25 }
26
27 async fn escrow_address(
28 &self,
29 _: tonic::Request<QueryEscrowAddressRequest>,
30 ) -> std::result::Result<tonic::Response<QueryEscrowAddressResponse>, tonic::Status> {
31 Err(tonic::Status::unimplemented("not implemented"))
32 }
33
34 async fn denom_hash(
35 &self,
36 _: tonic::Request<QueryDenomHashRequest>,
37 ) -> std::result::Result<tonic::Response<QueryDenomHashResponse>, tonic::Status> {
38 Err(tonic::Status::unimplemented("not implemented"))
39 }
40
41 async fn params(
42 &self,
43 _: tonic::Request<QueryParamsRequest>,
44 ) -> std::result::Result<tonic::Response<QueryParamsResponse>, tonic::Status> {
45 Err(tonic::Status::unimplemented("not implemented"))
46 }
47
48 async fn denom_trace(
49 &self,
50 _: tonic::Request<QueryDenomTraceRequest>,
51 ) -> std::result::Result<tonic::Response<QueryDenomTraceResponse>, tonic::Status> {
52 Err(tonic::Status::unimplemented("not implemented"))
53 }
54
55 async fn denom_traces(
56 &self,
57 _: tonic::Request<QueryDenomTracesRequest>,
58 ) -> std::result::Result<tonic::Response<QueryDenomTracesResponse>, tonic::Status> {
59 let snapshot = self.storage.latest_snapshot();
62 let s = snapshot.prefix(state_key::denom_metadata_by_asset::prefix());
63 let denom_traces = s
64 .filter_map(move |i: anyhow::Result<(String, Metadata)>| async move {
65 if i.is_err() {
66 return Some(Err(i.context("bad denom in state").err().unwrap()));
67 }
68 let (_key, denom) = i.expect("should not be an error");
69
70 match denom.ibc_transfer_path() {
72 Ok(None) => return None,
73 Err(e) => return Some(Err(e)),
74 Ok(Some((path, base_denom))) => Some(Ok(DenomTrace { path, base_denom })),
75 }
76 })
77 .collect::<Vec<_>>()
78 .await
79 .into_iter()
80 .collect::<anyhow::Result<Vec<_>>>()
81 .map_err(|e| tonic::Status::internal(e.to_string()))?;
82 Ok(tonic::Response::new(QueryDenomTracesResponse {
83 denom_traces,
84 pagination: None,
86 }))
87 }
88}