pcli/command/query/
community_pool.rs

1use crate::App;
2use anyhow::{Context, Result};
3use futures::TryStreamExt;
4use penumbra_sdk_asset::Value;
5use penumbra_sdk_proto::{
6    core::component::community_pool::v1::CommunityPoolAssetBalancesRequest,
7    penumbra::core::component::community_pool::v1::query_service_client::QueryServiceClient as CommunityPoolQueryServiceClient,
8};
9use penumbra_sdk_view::ViewClient;
10use std::io::{stdout, Write};
11
12#[derive(Debug, clap::Subcommand)]
13pub enum CommunityPoolCmd {
14    /// Get the balance in the Community Pool, or the balance of a specific asset.
15    Balance {
16        /// Get only the balance of the specified asset.
17        asset: Option<String>,
18    },
19}
20
21impl CommunityPoolCmd {
22    pub async fn exec(&self, app: &mut App) -> Result<()> {
23        match self {
24            CommunityPoolCmd::Balance { asset } => self.print_balance(app, asset).await,
25        }
26    }
27
28    pub async fn print_balance(&self, app: &mut App, asset: &Option<String>) -> Result<()> {
29        let asset_id = asset.as_ref().map(|asset| {
30            // Try to parse as an asset ID, then if it's not an asset ID, assume it's a unit name
31            if let Ok(asset_id) = asset.parse() {
32                asset_id
33            } else {
34                penumbra_sdk_asset::asset::REGISTRY
35                    .parse_unit(asset.as_str())
36                    .id()
37            }
38        });
39
40        let mut client = CommunityPoolQueryServiceClient::new(app.pd_channel().await?);
41        let balances = client
42            .community_pool_asset_balances(CommunityPoolAssetBalancesRequest {
43                asset_ids: asset_id.map_or_else(std::vec::Vec::new, |id| vec![id.into()]),
44            })
45            .await?
46            .into_inner()
47            .try_collect::<Vec<_>>()
48            .await
49            .context("cannot process Community Pool balance data")?;
50
51        let asset_cache = app.view().assets().await?;
52        let mut writer = stdout();
53        for balance_response in balances {
54            let balance: Value = balance_response
55                .balance
56                .expect("balance should always be set")
57                .try_into()
58                .context("cannot parse balance")?;
59            let value_str = balance.format(&asset_cache);
60
61            writeln!(writer, "{value_str}")?;
62        }
63
64        Ok(())
65    }
66}