1use anyhow::{anyhow, Result};
2use futures::stream::TryStreamExt;
3use penumbra_sdk_dex::lp::position::{Position, State};
4use penumbra_sdk_proto::core::component::dex::v1::{
5 query_service_client::QueryServiceClient as DexQueryServiceClient,
6 LiquidityPositionsByIdRequest,
7};
8use penumbra_sdk_view::ViewClient;
9
10use crate::{command::utils, App};
11
12#[derive(Debug, clap::Args)]
13pub struct LiquidityPositionsCmd {}
14
15impl LiquidityPositionsCmd {
16 pub fn offline(&self) -> bool {
17 false
18 }
19
20 pub async fn exec(&self, app: &mut App) -> Result<()> {
21 let my_position_ids = app
22 .view()
23 .owned_position_ids(Some(State::Opened), None)
24 .await?;
25 let mut dex_client = DexQueryServiceClient::new(app.pd_channel().await?);
26
27 let positions_stream = dex_client
28 .liquidity_positions_by_id(LiquidityPositionsByIdRequest {
29 position_id: my_position_ids.into_iter().map(Into::into).collect(),
30 })
31 .await?
32 .into_inner()
33 .map_err(|e| anyhow!("error fetching liquidity positions: {}", e))
34 .and_then(|msg| async move {
35 msg.data
36 .ok_or_else(|| anyhow!("missing liquidity position in response"))
37 .map(Position::try_from)?
38 });
39
40 let asset_cache = app.view().assets().await?;
41
42 let positions = positions_stream.try_collect::<Vec<_>>().await?;
43
44 println!("{}", utils::render_positions(&asset_cache, &positions));
45
46 Ok(())
47 }
48}