From a361b704ac399aaf757eb5947ace4b341d1f0894 Mon Sep 17 00:00:00 2001 From: Will Yang Date: Mon, 10 Aug 2026 19:22:06 -0700 Subject: [PATCH] sui-rpc: add MovePackageService.ListPackages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A server-streaming list of every Move package write — first publishes and upgrades alike — in a checkpoint range, in transaction order, using the ledger-history frame protocol (Watermark / QueryEnd / QueryOptions). Each item is the ObjectReference of one written package version; contents load via LedgerService.GetObject / BatchGetObjects. A transaction that writes several packages yields one item per write, in effects order, and cursors address individual writes so a page may split within a transaction and resume exactly where it left off. Backends that do not index the history this scan requires serve the generated default stub, UNIMPLEMENTED. --- .../proto/generated/sui.rpc.v2.accessors.rs | 188 +++++++++++ .../src/proto/generated/sui.rpc.v2.fds.bin | Bin 61779 -> 62342 bytes .../proto/generated/sui.rpc.v2.field_info.rs | 120 +++++++ .../sui-rpc/src/proto/generated/sui.rpc.v2.rs | 124 +++++++ .../src/proto/generated/sui.rpc.v2.serde.rs | 310 ++++++++++++++++++ .../sui/rpc/v2/move_package_service.proto | 38 +++ 6 files changed, 780 insertions(+) diff --git a/crates/sui-rpc/src/proto/generated/sui.rpc.v2.accessors.rs b/crates/sui-rpc/src/proto/generated/sui.rpc.v2.accessors.rs index fcb0fe40b3..0dfb77a247 100644 --- a/crates/sui-rpc/src/proto/generated/sui.rpc.v2.accessors.rs +++ b/crates/sui-rpc/src/proto/generated/sui.rpc.v2.accessors.rs @@ -10794,6 +10794,194 @@ mod _accessor_impls { self } } + impl super::ListPackagesRequest { + pub const fn const_default() -> Self { + Self { + start_checkpoint: None, + end_checkpoint: None, + options: None, + } + } + #[doc(hidden)] + pub fn default_instance() -> &'static Self { + static DEFAULT: super::ListPackagesRequest = super::ListPackagesRequest::const_default(); + &DEFAULT + } + ///If `start_checkpoint` is set, returns [`Some`] with a mutable reference to the value; otherwise returns [`None`]. + pub fn start_checkpoint_opt_mut(&mut self) -> Option<&mut u64> { + self.start_checkpoint.as_mut().map(|field| field as _) + } + ///Returns a mutable reference to `start_checkpoint`. + ///If the field is unset, it is first initialized with the default value. + pub fn start_checkpoint_mut(&mut self) -> &mut u64 { + self.start_checkpoint.get_or_insert_default() + } + ///If `start_checkpoint` is set, returns [`Some`] with the value; otherwise returns [`None`]. + pub fn start_checkpoint_opt(&self) -> Option { + self.start_checkpoint.as_ref().map(|field| *field) + } + ///Sets `start_checkpoint` with the provided value. + pub fn set_start_checkpoint(&mut self, field: u64) { + self.start_checkpoint = Some(field); + } + ///Sets `start_checkpoint` with the provided value. + pub fn with_start_checkpoint(mut self, field: u64) -> Self { + self.set_start_checkpoint(field); + self + } + ///If `end_checkpoint` is set, returns [`Some`] with a mutable reference to the value; otherwise returns [`None`]. + pub fn end_checkpoint_opt_mut(&mut self) -> Option<&mut u64> { + self.end_checkpoint.as_mut().map(|field| field as _) + } + ///Returns a mutable reference to `end_checkpoint`. + ///If the field is unset, it is first initialized with the default value. + pub fn end_checkpoint_mut(&mut self) -> &mut u64 { + self.end_checkpoint.get_or_insert_default() + } + ///If `end_checkpoint` is set, returns [`Some`] with the value; otherwise returns [`None`]. + pub fn end_checkpoint_opt(&self) -> Option { + self.end_checkpoint.as_ref().map(|field| *field) + } + ///Sets `end_checkpoint` with the provided value. + pub fn set_end_checkpoint(&mut self, field: u64) { + self.end_checkpoint = Some(field); + } + ///Sets `end_checkpoint` with the provided value. + pub fn with_end_checkpoint(mut self, field: u64) -> Self { + self.set_end_checkpoint(field); + self + } + ///Returns the value of `options`, or the default value if `options` is unset. + pub fn options(&self) -> &super::QueryOptions { + self.options + .as_ref() + .map(|field| field as _) + .unwrap_or_else(|| super::QueryOptions::default_instance() as _) + } + ///If `options` is set, returns [`Some`] with a mutable reference to the value; otherwise returns [`None`]. + pub fn options_opt_mut(&mut self) -> Option<&mut super::QueryOptions> { + self.options.as_mut().map(|field| field as _) + } + ///Returns a mutable reference to `options`. + ///If the field is unset, it is first initialized with the default value. + pub fn options_mut(&mut self) -> &mut super::QueryOptions { + self.options.get_or_insert_default() + } + ///If `options` is set, returns [`Some`] with the value; otherwise returns [`None`]. + pub fn options_opt(&self) -> Option<&super::QueryOptions> { + self.options.as_ref().map(|field| field as _) + } + ///Sets `options` with the provided value. + pub fn set_options>(&mut self, field: T) { + self.options = Some(field.into().into()); + } + ///Sets `options` with the provided value. + pub fn with_options>(mut self, field: T) -> Self { + self.set_options(field.into()); + self + } + } + impl super::ListPackagesResponse { + pub const fn const_default() -> Self { + Self { + package: None, + watermark: None, + end: None, + } + } + #[doc(hidden)] + pub fn default_instance() -> &'static Self { + static DEFAULT: super::ListPackagesResponse = super::ListPackagesResponse::const_default(); + &DEFAULT + } + ///Returns the value of `package`, or the default value if `package` is unset. + pub fn package(&self) -> &super::PackageVersion { + self.package + .as_ref() + .map(|field| field as _) + .unwrap_or_else(|| super::PackageVersion::default_instance() as _) + } + ///If `package` is set, returns [`Some`] with a mutable reference to the value; otherwise returns [`None`]. + pub fn package_opt_mut(&mut self) -> Option<&mut super::PackageVersion> { + self.package.as_mut().map(|field| field as _) + } + ///Returns a mutable reference to `package`. + ///If the field is unset, it is first initialized with the default value. + pub fn package_mut(&mut self) -> &mut super::PackageVersion { + self.package.get_or_insert_default() + } + ///If `package` is set, returns [`Some`] with the value; otherwise returns [`None`]. + pub fn package_opt(&self) -> Option<&super::PackageVersion> { + self.package.as_ref().map(|field| field as _) + } + ///Sets `package` with the provided value. + pub fn set_package>(&mut self, field: T) { + self.package = Some(field.into().into()); + } + ///Sets `package` with the provided value. + pub fn with_package>(mut self, field: T) -> Self { + self.set_package(field.into()); + self + } + ///Returns the value of `watermark`, or the default value if `watermark` is unset. + pub fn watermark(&self) -> &super::Watermark { + self.watermark + .as_ref() + .map(|field| field as _) + .unwrap_or_else(|| super::Watermark::default_instance() as _) + } + ///If `watermark` is set, returns [`Some`] with a mutable reference to the value; otherwise returns [`None`]. + pub fn watermark_opt_mut(&mut self) -> Option<&mut super::Watermark> { + self.watermark.as_mut().map(|field| field as _) + } + ///Returns a mutable reference to `watermark`. + ///If the field is unset, it is first initialized with the default value. + pub fn watermark_mut(&mut self) -> &mut super::Watermark { + self.watermark.get_or_insert_default() + } + ///If `watermark` is set, returns [`Some`] with the value; otherwise returns [`None`]. + pub fn watermark_opt(&self) -> Option<&super::Watermark> { + self.watermark.as_ref().map(|field| field as _) + } + ///Sets `watermark` with the provided value. + pub fn set_watermark>(&mut self, field: T) { + self.watermark = Some(field.into().into()); + } + ///Sets `watermark` with the provided value. + pub fn with_watermark>(mut self, field: T) -> Self { + self.set_watermark(field.into()); + self + } + ///Returns the value of `end`, or the default value if `end` is unset. + pub fn end(&self) -> &super::QueryEnd { + self.end + .as_ref() + .map(|field| field as _) + .unwrap_or_else(|| super::QueryEnd::default_instance() as _) + } + ///If `end` is set, returns [`Some`] with a mutable reference to the value; otherwise returns [`None`]. + pub fn end_opt_mut(&mut self) -> Option<&mut super::QueryEnd> { + self.end.as_mut().map(|field| field as _) + } + ///Returns a mutable reference to `end`. + ///If the field is unset, it is first initialized with the default value. + pub fn end_mut(&mut self) -> &mut super::QueryEnd { + self.end.get_or_insert_default() + } + ///If `end` is set, returns [`Some`] with the value; otherwise returns [`None`]. + pub fn end_opt(&self) -> Option<&super::QueryEnd> { + self.end.as_ref().map(|field| field as _) + } + ///Sets `end` with the provided value. + pub fn set_end>(&mut self, field: T) { + self.end = Some(field.into().into()); + } + ///Sets `end` with the provided value. + pub fn with_end>(mut self, field: T) -> Self { + self.set_end(field.into()); + self + } + } impl super::ListTransactionsRequest { pub const fn const_default() -> Self { Self { diff --git a/crates/sui-rpc/src/proto/generated/sui.rpc.v2.fds.bin b/crates/sui-rpc/src/proto/generated/sui.rpc.v2.fds.bin index b2d33302e09a9f9e7599c4ae1ab1b9af2ed36e48..a4de29fec0692d092847c76d05733e0e0379c5f9 100644 GIT binary patch delta 318 zcmccoh`H@K^M+a3ERO}aR3~4|7N5K|+j6qdGR4jBvol#tl7n8MXIkOIIY6Jr^=>oGka%lmx_j8YbaC8w( diff --git a/crates/sui-rpc/src/proto/generated/sui.rpc.v2.field_info.rs b/crates/sui-rpc/src/proto/generated/sui.rpc.v2.field_info.rs index 0972b1df5e..970747494b 100644 --- a/crates/sui-rpc/src/proto/generated/sui.rpc.v2.field_info.rs +++ b/crates/sui-rpc/src/proto/generated/sui.rpc.v2.field_info.rs @@ -6051,6 +6051,126 @@ pub(crate) mod _field_impls { self.finish() } } + impl ListPackagesRequest { + pub const START_CHECKPOINT_FIELD: &'static MessageField = &MessageField { + name: "start_checkpoint", + json_name: "startCheckpoint", + number: 1i32, + message_fields: None, + }; + pub const END_CHECKPOINT_FIELD: &'static MessageField = &MessageField { + name: "end_checkpoint", + json_name: "endCheckpoint", + number: 2i32, + message_fields: None, + }; + pub const OPTIONS_FIELD: &'static MessageField = &MessageField { + name: "options", + json_name: "options", + number: 3i32, + message_fields: Some(QueryOptions::FIELDS), + }; + } + impl MessageFields for ListPackagesRequest { + const FIELDS: &'static [&'static MessageField] = &[ + Self::START_CHECKPOINT_FIELD, + Self::END_CHECKPOINT_FIELD, + Self::OPTIONS_FIELD, + ]; + } + impl ListPackagesRequest { + pub fn path_builder() -> ListPackagesRequestFieldPathBuilder { + ListPackagesRequestFieldPathBuilder::new() + } + } + pub struct ListPackagesRequestFieldPathBuilder { + path: Vec<&'static str>, + } + impl ListPackagesRequestFieldPathBuilder { + #[allow(clippy::new_without_default)] + pub fn new() -> Self { + Self { path: Default::default() } + } + #[doc(hidden)] + pub fn new_with_base(base: Vec<&'static str>) -> Self { + Self { path: base } + } + pub fn finish(self) -> String { + self.path.join(".") + } + pub fn start_checkpoint(mut self) -> String { + self.path.push(ListPackagesRequest::START_CHECKPOINT_FIELD.name); + self.finish() + } + pub fn end_checkpoint(mut self) -> String { + self.path.push(ListPackagesRequest::END_CHECKPOINT_FIELD.name); + self.finish() + } + pub fn options(mut self) -> QueryOptionsFieldPathBuilder { + self.path.push(ListPackagesRequest::OPTIONS_FIELD.name); + QueryOptionsFieldPathBuilder::new_with_base(self.path) + } + } + impl ListPackagesResponse { + pub const PACKAGE_FIELD: &'static MessageField = &MessageField { + name: "package", + json_name: "package", + number: 1i32, + message_fields: Some(PackageVersion::FIELDS), + }; + pub const WATERMARK_FIELD: &'static MessageField = &MessageField { + name: "watermark", + json_name: "watermark", + number: 2i32, + message_fields: Some(Watermark::FIELDS), + }; + pub const END_FIELD: &'static MessageField = &MessageField { + name: "end", + json_name: "end", + number: 3i32, + message_fields: Some(QueryEnd::FIELDS), + }; + } + impl MessageFields for ListPackagesResponse { + const FIELDS: &'static [&'static MessageField] = &[ + Self::PACKAGE_FIELD, + Self::WATERMARK_FIELD, + Self::END_FIELD, + ]; + } + impl ListPackagesResponse { + pub fn path_builder() -> ListPackagesResponseFieldPathBuilder { + ListPackagesResponseFieldPathBuilder::new() + } + } + pub struct ListPackagesResponseFieldPathBuilder { + path: Vec<&'static str>, + } + impl ListPackagesResponseFieldPathBuilder { + #[allow(clippy::new_without_default)] + pub fn new() -> Self { + Self { path: Default::default() } + } + #[doc(hidden)] + pub fn new_with_base(base: Vec<&'static str>) -> Self { + Self { path: base } + } + pub fn finish(self) -> String { + self.path.join(".") + } + pub fn package(mut self) -> PackageVersionFieldPathBuilder { + self.path.push(ListPackagesResponse::PACKAGE_FIELD.name); + PackageVersionFieldPathBuilder::new_with_base(self.path) + } + pub fn watermark(mut self) -> WatermarkFieldPathBuilder { + self.path.push(ListPackagesResponse::WATERMARK_FIELD.name); + WatermarkFieldPathBuilder::new_with_base(self.path) + } + pub fn end(mut self) -> QueryEndFieldPathBuilder { + self.path.push(ListPackagesResponse::END_FIELD.name); + QueryEndFieldPathBuilder::new_with_base(self.path) + } + } impl LookupNameRequest { pub const NAME_FIELD: &'static MessageField = &MessageField { name: "name", diff --git a/crates/sui-rpc/src/proto/generated/sui.rpc.v2.rs b/crates/sui-rpc/src/proto/generated/sui.rpc.v2.rs index 54dc9521dd..79f3a10870 100644 --- a/crates/sui-rpc/src/proto/generated/sui.rpc.v2.rs +++ b/crates/sui-rpc/src/proto/generated/sui.rpc.v2.rs @@ -4026,6 +4026,42 @@ pub struct PackageVersion { #[prost(uint64, optional, tag = "2")] pub version: ::core::option::Option, } +/// Request message for MovePackageService.ListPackages. +#[non_exhaustive] +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct ListPackagesRequest { + /// Optional. Start of the checkpoint range to query (inclusive). Defaults to + /// genesis. + #[prost(uint64, optional, tag = "1")] + pub start_checkpoint: ::core::option::Option, + /// Optional. End of the checkpoint range to query (exclusive). Defaults to + /// the current indexed ledger tip. + #[prost(uint64, optional, tag = "2")] + pub end_checkpoint: ::core::option::Option, + /// Optional cursor-bounded query options. If unspecified, reads in ascending + /// order with the default item limit. The server enforces a maximum item + /// limit and silently coerces larger values down to it. To paginate, pass + /// the last received `Watermark.cursor` as `options.after` (ascending) or + /// `options.before` (descending). + #[prost(message, optional, tag = "3")] + pub options: ::core::option::Option, +} +/// Response message for MovePackageService.ListPackages. +#[non_exhaustive] +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct ListPackagesResponse { + /// One package write: the written package version. + #[prost(message, optional, tag = "1")] + pub package: ::core::option::Option, + /// Progress watermark as of this frame. Present on every frame. A + /// ScanLimit terminal watermark may repeat the previous frame's cursor when + /// its authoritative scan frontier was already emitted. + #[prost(message, optional, tag = "2")] + pub watermark: ::core::option::Option, + /// Set exactly once, on the final frame of a successful query stream. + #[prost(message, optional, tag = "3")] + pub end: ::core::option::Option, +} /// Generated client implementations. pub mod move_package_service_client { #![allow( @@ -4218,6 +4254,35 @@ pub mod move_package_service_client { ); self.inner.unary(req, path, codec).await } + /// List package writes (publishes and upgrades) in a checkpoint range, + /// ordered by transaction and, within a transaction, by the order the + /// writes appear in its effects. + pub async fn list_packages( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response>, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic_prost::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/sui.rpc.v2.MovePackageService/ListPackages", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert( + GrpcMethod::new("sui.rpc.v2.MovePackageService", "ListPackages"), + ); + self.inner.server_streaming(req, path, codec).await + } } } /// Generated server implementations. @@ -4269,6 +4334,18 @@ pub mod move_package_service_server { > { Err(tonic::Status::unimplemented("Not yet implemented")) } + /// List package writes (publishes and upgrades) in a checkpoint range, + /// ordered by transaction and, within a transaction, by the order the + /// writes appear in its effects. + async fn list_packages( + &self, + request: tonic::Request, + ) -> std::result::Result< + tonic::Response>, + tonic::Status, + > { + Err(tonic::Status::unimplemented("Not yet implemented")) + } } #[derive(Debug)] pub struct MovePackageServiceServer { @@ -4533,6 +4610,53 @@ pub mod move_package_service_server { }; Box::pin(fut) } + "/sui.rpc.v2.MovePackageService/ListPackages" => { + #[allow(non_camel_case_types)] + struct ListPackagesSvc(pub Arc); + impl< + T: MovePackageService, + > tonic::server::ServerStreamingService + for ListPackagesSvc { + type Response = super::ListPackagesResponse; + type ResponseStream = BoxStream; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { + ::list_packages(&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 method = ListPackagesSvc(inner); + let codec = tonic_prost::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.server_streaming(method, req).await; + Ok(res) + }; + Box::pin(fut) + } _ => { Box::pin(async move { let mut response = http::Response::new( diff --git a/crates/sui-rpc/src/proto/generated/sui.rpc.v2.serde.rs b/crates/sui-rpc/src/proto/generated/sui.rpc.v2.serde.rs index 0a75620aa6..467280dc03 100644 --- a/crates/sui-rpc/src/proto/generated/sui.rpc.v2.serde.rs +++ b/crates/sui-rpc/src/proto/generated/sui.rpc.v2.serde.rs @@ -19084,6 +19084,316 @@ impl<'de> serde::Deserialize<'de> for ListPackageVersionsResponse { ) } } +impl serde::Serialize for ListPackagesRequest { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0usize; + if self.start_checkpoint.is_some() { + len += 1; + } + if self.end_checkpoint.is_some() { + len += 1; + } + if self.options.is_some() { + len += 1; + } + let mut struct_ser = serializer + .serialize_struct("sui.rpc.v2.ListPackagesRequest", len)?; + if let Some(v) = self.start_checkpoint.as_ref() { + #[allow(clippy::needless_borrow)] + #[allow(clippy::needless_borrows_for_generic_args)] + struct_ser + .serialize_field("startCheckpoint", ToString::to_string(&v).as_str())?; + } + if let Some(v) = self.end_checkpoint.as_ref() { + #[allow(clippy::needless_borrow)] + #[allow(clippy::needless_borrows_for_generic_args)] + struct_ser + .serialize_field("endCheckpoint", ToString::to_string(&v).as_str())?; + } + if let Some(v) = self.options.as_ref() { + struct_ser.serialize_field("options", v)?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for ListPackagesRequest { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "start_checkpoint", + "startCheckpoint", + "end_checkpoint", + "endCheckpoint", + "options", + ]; + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + StartCheckpoint, + EndCheckpoint, + Options, + __SkipField__, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize( + deserializer: D, + ) -> std::result::Result + 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( + self, + value: &str, + ) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "startCheckpoint" | "start_checkpoint" => { + Ok(GeneratedField::StartCheckpoint) + } + "endCheckpoint" | "end_checkpoint" => { + Ok(GeneratedField::EndCheckpoint) + } + "options" => Ok(GeneratedField::Options), + _ => Ok(GeneratedField::__SkipField__), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + #[allow(clippy::useless_conversion)] + #[allow(clippy::unit_arg)] + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = ListPackagesRequest; + fn expecting( + &self, + formatter: &mut std::fmt::Formatter<'_>, + ) -> std::fmt::Result { + formatter.write_str("struct sui.rpc.v2.ListPackagesRequest") + } + fn visit_map( + self, + mut map_: V, + ) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut start_checkpoint__ = None; + let mut end_checkpoint__ = None; + let mut options__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::StartCheckpoint => { + if start_checkpoint__.is_some() { + return Err( + serde::de::Error::duplicate_field("startCheckpoint"), + ); + } + start_checkpoint__ = map_ + .next_value::< + ::std::option::Option>, + >()? + .map(|x| x.0); + } + GeneratedField::EndCheckpoint => { + if end_checkpoint__.is_some() { + return Err( + serde::de::Error::duplicate_field("endCheckpoint"), + ); + } + end_checkpoint__ = map_ + .next_value::< + ::std::option::Option>, + >()? + .map(|x| x.0); + } + GeneratedField::Options => { + if options__.is_some() { + return Err(serde::de::Error::duplicate_field("options")); + } + options__ = map_.next_value()?; + } + GeneratedField::__SkipField__ => { + let _ = map_.next_value::()?; + } + } + } + Ok(ListPackagesRequest { + start_checkpoint: start_checkpoint__, + end_checkpoint: end_checkpoint__, + options: options__, + }) + } + } + deserializer + .deserialize_struct( + "sui.rpc.v2.ListPackagesRequest", + FIELDS, + GeneratedVisitor, + ) + } +} +impl serde::Serialize for ListPackagesResponse { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0usize; + if self.package.is_some() { + len += 1; + } + if self.watermark.is_some() { + len += 1; + } + if self.end.is_some() { + len += 1; + } + let mut struct_ser = serializer + .serialize_struct("sui.rpc.v2.ListPackagesResponse", len)?; + if let Some(v) = self.package.as_ref() { + struct_ser.serialize_field("package", v)?; + } + if let Some(v) = self.watermark.as_ref() { + struct_ser.serialize_field("watermark", v)?; + } + if let Some(v) = self.end.as_ref() { + struct_ser.serialize_field("end", v)?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for ListPackagesResponse { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &["package", "watermark", "end"]; + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + Package, + Watermark, + End, + __SkipField__, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize( + deserializer: D, + ) -> std::result::Result + 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( + self, + value: &str, + ) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "package" => Ok(GeneratedField::Package), + "watermark" => Ok(GeneratedField::Watermark), + "end" => Ok(GeneratedField::End), + _ => Ok(GeneratedField::__SkipField__), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + #[allow(clippy::useless_conversion)] + #[allow(clippy::unit_arg)] + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = ListPackagesResponse; + fn expecting( + &self, + formatter: &mut std::fmt::Formatter<'_>, + ) -> std::fmt::Result { + formatter.write_str("struct sui.rpc.v2.ListPackagesResponse") + } + fn visit_map( + self, + mut map_: V, + ) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut package__ = None; + let mut watermark__ = None; + let mut end__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::Package => { + if package__.is_some() { + return Err(serde::de::Error::duplicate_field("package")); + } + package__ = map_.next_value()?; + } + GeneratedField::Watermark => { + if watermark__.is_some() { + return Err(serde::de::Error::duplicate_field("watermark")); + } + watermark__ = map_.next_value()?; + } + GeneratedField::End => { + if end__.is_some() { + return Err(serde::de::Error::duplicate_field("end")); + } + end__ = map_.next_value()?; + } + GeneratedField::__SkipField__ => { + let _ = map_.next_value::()?; + } + } + } + Ok(ListPackagesResponse { + package: package__, + watermark: watermark__, + end: end__, + }) + } + } + deserializer + .deserialize_struct( + "sui.rpc.v2.ListPackagesResponse", + FIELDS, + GeneratedVisitor, + ) + } +} impl serde::Serialize for ListTransactionsRequest { #[allow(deprecated)] fn serialize(&self, serializer: S) -> std::result::Result diff --git a/crates/sui-rpc/vendored/proto/sui/rpc/v2/move_package_service.proto b/crates/sui-rpc/vendored/proto/sui/rpc/v2/move_package_service.proto index 05245dd165..bbc32b5c7b 100644 --- a/crates/sui-rpc/vendored/proto/sui/rpc/v2/move_package_service.proto +++ b/crates/sui-rpc/vendored/proto/sui/rpc/v2/move_package_service.proto @@ -6,12 +6,18 @@ syntax = "proto3"; package sui.rpc.v2; import "sui/rpc/v2/move_package.proto"; +import "sui/rpc/v2/query_options.proto"; service MovePackageService { rpc GetPackage(GetPackageRequest) returns (GetPackageResponse); rpc GetDatatype(GetDatatypeRequest) returns (GetDatatypeResponse); rpc GetFunction(GetFunctionRequest) returns (GetFunctionResponse); rpc ListPackageVersions(ListPackageVersionsRequest) returns (ListPackageVersionsResponse); + + // List package writes (publishes and upgrades) in a checkpoint range, + // ordered by transaction and, within a transaction, by the order the + // writes appear in its effects. + rpc ListPackages(ListPackagesRequest) returns (stream ListPackagesResponse); } message GetPackageRequest { @@ -89,3 +95,35 @@ message PackageVersion { // The version number optional uint64 version = 2; } + +// Request message for MovePackageService.ListPackages. +message ListPackagesRequest { + // Optional. Start of the checkpoint range to query (inclusive). Defaults to + // genesis. + optional uint64 start_checkpoint = 1; + + // Optional. End of the checkpoint range to query (exclusive). Defaults to + // the current indexed ledger tip. + optional uint64 end_checkpoint = 2; + + // Optional cursor-bounded query options. If unspecified, reads in ascending + // order with the default item limit. The server enforces a maximum item + // limit and silently coerces larger values down to it. To paginate, pass + // the last received `Watermark.cursor` as `options.after` (ascending) or + // `options.before` (descending). + optional QueryOptions options = 3; +} + +// Response message for MovePackageService.ListPackages. +message ListPackagesResponse { + // One package write: the written package version. + optional PackageVersion package = 1; + + // Progress watermark as of this frame. Present on every frame. A + // ScanLimit terminal watermark may repeat the previous frame's cursor when + // its authoritative scan frontier was already emitted. + optional Watermark watermark = 2; + + // Set exactly once, on the final frame of a successful query stream. + optional QueryEnd end = 3; +}