From 6ab217514f49c03eafbca1399fe57e19e6a96925 Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Thu, 15 Feb 2024 18:08:11 -0800 Subject: [PATCH] proto: add extra SwapView fields (#3837) --- crates/core/component/dex/src/swap/view.rs | 6 ++ .../src/gen/penumbra.core.component.dex.v1.rs | 31 ++++++ .../penumbra.core.component.dex.v1.serde.rs | 90 ++++++++++++++++++ .../proto/src/gen/proto_descriptor.bin.no_lfs | Bin 344948 -> 346387 bytes .../penumbra/core/component/dex/v1/dex.proto | 18 ++++ 5 files changed, 145 insertions(+) diff --git a/crates/core/component/dex/src/swap/view.rs b/crates/core/component/dex/src/swap/view.rs index 9248191d53..89669107ff 100644 --- a/crates/core/component/dex/src/swap/view.rs +++ b/crates/core/component/dex/src/swap/view.rs @@ -61,6 +61,12 @@ impl From for pb::SwapView { swap_plaintext: Some(swap_plaintext.into()), // Swap claim crossreferencing is not yet supported in the Rust stack. claim_tx: None, + // These fields are also not yet supported in the Rust stack. + asset_1_metadata: None, + asset_2_metadata: None, + batch_swap_output_data: None, + output_1: None, + output_2: None, })), }, SwapView::Opaque { swap } => Self { diff --git a/crates/proto/src/gen/penumbra.core.component.dex.v1.rs b/crates/proto/src/gen/penumbra.core.component.dex.v1.rs index 3fc7302b34..bd5631987f 100644 --- a/crates/proto/src/gen/penumbra.core.component.dex.v1.rs +++ b/crates/proto/src/gen/penumbra.core.component.dex.v1.rs @@ -259,6 +259,37 @@ pub mod swap_view { pub claim_tx: ::core::option::Option< super::super::super::super::txhash::v1::TransactionId, >, + /// Optionally, if the swap has been confirmed, the batch price it received. + /// + /// As soon as the swap is detected, the view server can in principle record + /// the relevant BSOD and provide it as part of the view. This allows providing + /// info about the execution of the swap. + #[prost(message, optional, tag = "20")] + pub batch_swap_output_data: ::core::option::Option, + /// Optionally, if the swap has been confirmed, the output note of asset 1. + /// + /// This is the note that will be minted by the SwapClaim action. + #[prost(message, optional, tag = "30")] + pub output_1: ::core::option::Option< + super::super::super::shielded_pool::v1::NoteView, + >, + /// Optionally, if the swap has been confirmed, the output note of asset 2. + /// + /// This is the note that will be minted by the SwapClaim action. + #[prost(message, optional, tag = "31")] + pub output_2: ::core::option::Option< + super::super::super::shielded_pool::v1::NoteView, + >, + /// Optionally, metadata about asset 1 in the `swap`'s trading pair. + #[prost(message, optional, tag = "40")] + pub asset_1_metadata: ::core::option::Option< + super::super::super::super::asset::v1::Metadata, + >, + /// Optionally, metadata about asset 2 in the `swap`'s trading pair. + #[prost(message, optional, tag = "41")] + pub asset_2_metadata: ::core::option::Option< + super::super::super::super::asset::v1::Metadata, + >, } impl ::prost::Name for Visible { const NAME: &'static str = "Visible"; diff --git a/crates/proto/src/gen/penumbra.core.component.dex.v1.serde.rs b/crates/proto/src/gen/penumbra.core.component.dex.v1.serde.rs index 6b025bbf3f..02b1293bd9 100644 --- a/crates/proto/src/gen/penumbra.core.component.dex.v1.serde.rs +++ b/crates/proto/src/gen/penumbra.core.component.dex.v1.serde.rs @@ -7635,6 +7635,21 @@ impl serde::Serialize for swap_view::Visible { if self.claim_tx.is_some() { len += 1; } + if self.batch_swap_output_data.is_some() { + len += 1; + } + if self.output_1.is_some() { + len += 1; + } + if self.output_2.is_some() { + len += 1; + } + if self.asset_1_metadata.is_some() { + len += 1; + } + if self.asset_2_metadata.is_some() { + len += 1; + } let mut struct_ser = serializer.serialize_struct("penumbra.core.component.dex.v1.SwapView.Visible", len)?; if let Some(v) = self.swap.as_ref() { struct_ser.serialize_field("swap", v)?; @@ -7645,6 +7660,21 @@ impl serde::Serialize for swap_view::Visible { if let Some(v) = self.claim_tx.as_ref() { struct_ser.serialize_field("claimTx", v)?; } + if let Some(v) = self.batch_swap_output_data.as_ref() { + struct_ser.serialize_field("batchSwapOutputData", v)?; + } + if let Some(v) = self.output_1.as_ref() { + struct_ser.serialize_field("output1", v)?; + } + if let Some(v) = self.output_2.as_ref() { + struct_ser.serialize_field("output2", v)?; + } + if let Some(v) = self.asset_1_metadata.as_ref() { + struct_ser.serialize_field("asset1Metadata", v)?; + } + if let Some(v) = self.asset_2_metadata.as_ref() { + struct_ser.serialize_field("asset2Metadata", v)?; + } struct_ser.end() } } @@ -7660,6 +7690,16 @@ impl<'de> serde::Deserialize<'de> for swap_view::Visible { "swapPlaintext", "claim_tx", "claimTx", + "batch_swap_output_data", + "batchSwapOutputData", + "output_1", + "output1", + "output_2", + "output2", + "asset_1_metadata", + "asset1Metadata", + "asset_2_metadata", + "asset2Metadata", ]; #[allow(clippy::enum_variant_names)] @@ -7667,6 +7707,11 @@ impl<'de> serde::Deserialize<'de> for swap_view::Visible { Swap, SwapPlaintext, ClaimTx, + BatchSwapOutputData, + Output1, + Output2, + Asset1Metadata, + Asset2Metadata, __SkipField__, } impl<'de> serde::Deserialize<'de> for GeneratedField { @@ -7692,6 +7737,11 @@ impl<'de> serde::Deserialize<'de> for swap_view::Visible { "swap" => Ok(GeneratedField::Swap), "swapPlaintext" | "swap_plaintext" => Ok(GeneratedField::SwapPlaintext), "claimTx" | "claim_tx" => Ok(GeneratedField::ClaimTx), + "batchSwapOutputData" | "batch_swap_output_data" => Ok(GeneratedField::BatchSwapOutputData), + "output1" | "output_1" => Ok(GeneratedField::Output1), + "output2" | "output_2" => Ok(GeneratedField::Output2), + "asset1Metadata" | "asset_1_metadata" => Ok(GeneratedField::Asset1Metadata), + "asset2Metadata" | "asset_2_metadata" => Ok(GeneratedField::Asset2Metadata), _ => Ok(GeneratedField::__SkipField__), } } @@ -7714,6 +7764,11 @@ impl<'de> serde::Deserialize<'de> for swap_view::Visible { let mut swap__ = None; let mut swap_plaintext__ = None; let mut claim_tx__ = None; + let mut batch_swap_output_data__ = None; + let mut output_1__ = None; + let mut output_2__ = None; + let mut asset_1_metadata__ = None; + let mut asset_2_metadata__ = None; while let Some(k) = map_.next_key()? { match k { GeneratedField::Swap => { @@ -7734,6 +7789,36 @@ impl<'de> serde::Deserialize<'de> for swap_view::Visible { } claim_tx__ = map_.next_value()?; } + GeneratedField::BatchSwapOutputData => { + if batch_swap_output_data__.is_some() { + return Err(serde::de::Error::duplicate_field("batchSwapOutputData")); + } + batch_swap_output_data__ = map_.next_value()?; + } + GeneratedField::Output1 => { + if output_1__.is_some() { + return Err(serde::de::Error::duplicate_field("output1")); + } + output_1__ = map_.next_value()?; + } + GeneratedField::Output2 => { + if output_2__.is_some() { + return Err(serde::de::Error::duplicate_field("output2")); + } + output_2__ = map_.next_value()?; + } + GeneratedField::Asset1Metadata => { + if asset_1_metadata__.is_some() { + return Err(serde::de::Error::duplicate_field("asset1Metadata")); + } + asset_1_metadata__ = map_.next_value()?; + } + GeneratedField::Asset2Metadata => { + if asset_2_metadata__.is_some() { + return Err(serde::de::Error::duplicate_field("asset2Metadata")); + } + asset_2_metadata__ = map_.next_value()?; + } GeneratedField::__SkipField__ => { let _ = map_.next_value::()?; } @@ -7743,6 +7828,11 @@ impl<'de> serde::Deserialize<'de> for swap_view::Visible { swap: swap__, swap_plaintext: swap_plaintext__, claim_tx: claim_tx__, + batch_swap_output_data: batch_swap_output_data__, + output_1: output_1__, + output_2: output_2__, + asset_1_metadata: asset_1_metadata__, + asset_2_metadata: asset_2_metadata__, }) } } diff --git a/crates/proto/src/gen/proto_descriptor.bin.no_lfs b/crates/proto/src/gen/proto_descriptor.bin.no_lfs index 9fedf447a9a2793d9b047c9ae38fb57b9ce92eb5..64f793dd0227fae6c3b31dd13631b3335ad6b0ec 100644 GIT binary patch delta 10791 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 V;Izl)+}=mvPj=qkCssK0zW_c64=n%y delta 9626 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