iota_grpc_client/api/state/
dynamic_fields.rs

1// Copyright (c) 2026 IOTA Stiftung
2// SPDX-License-Identifier: Apache-2.0
3
4//! High-level API for listing dynamic fields.
5//!
6//! # Available Read Mask Fields
7//!
8//! - `kind` - the kind of dynamic field (field or object)
9//! - `parent` - the parent object ID
10//! - `field_id` - the field object ID
11//! - `child_id` - the child object ID (for dynamic object fields)
12//! - `name` - BCS-encoded field name
13//! - `value` - BCS-encoded field value
14//! - `value_type` - the Move type of the value
15//! - `field_object` - the full field object (sub-fields match `GetObjects`)
16//! - `child_object` - the full child object (sub-fields match `GetObjects`)
17
18use iota_grpc_types::v1::{
19    dynamic_field::DynamicField,
20    state_service::{ListDynamicFieldsRequest, state_service_client::StateServiceClient},
21};
22use iota_sdk_types::ObjectId;
23
24use crate::{
25    Client, InterceptedChannel,
26    api::{
27        LIST_DYNAMIC_FIELDS_READ_MASK, define_list_query, field_mask_with_default, proto_object_id,
28    },
29};
30
31define_list_query! {
32    /// Builder for listing dynamic fields of a parent object.
33    ///
34    /// Created by [`Client::list_dynamic_fields`]. Await directly for a
35    /// single page, or call [`.collect(limit)`](Self::collect) to
36    /// auto-paginate.
37    pub struct ListDynamicFieldsQuery {
38        service_client: StateServiceClient<InterceptedChannel>,
39        request: ListDynamicFieldsRequest,
40        item: DynamicField,
41        rpc_method: list_dynamic_fields,
42        items_field: dynamic_fields,
43    }
44}
45
46impl Client {
47    /// List dynamic fields owned by a parent object.
48    ///
49    /// Returns a query builder. Await it directly for a single page
50    /// (with access to `next_page_token`), or call `.collect(limit)` to
51    /// auto-paginate through all results.
52    ///
53    /// # Parameters
54    ///
55    /// - `parent` - The object ID of the parent object.
56    /// - `page_size` - Optional maximum number of fields per page.
57    /// - `page_token` - Optional continuation token from a previous page.
58    /// - `read_mask` - Optional field mask. If `None`, uses
59    ///   [`LIST_DYNAMIC_FIELDS_READ_MASK`].
60    ///
61    /// # Examples
62    ///
63    /// Single page:
64    /// ```no_run
65    /// # use iota_grpc_client::Client;
66    /// # use iota_sdk_types::ObjectId;
67    /// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
68    /// let client = Client::connect("http://localhost:9000").await?;
69    /// let parent: ObjectId = "0x2".parse()?;
70    ///
71    /// let page = client.list_dynamic_fields(parent, None, None, None).await?;
72    /// for field in &page.body().items {
73    ///     println!("Dynamic field: {:?}", field);
74    /// }
75    /// # Ok(())
76    /// # }
77    /// ```
78    ///
79    /// Auto-paginate:
80    /// ```no_run
81    /// # use iota_grpc_client::Client;
82    /// # use iota_sdk_types::ObjectId;
83    /// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
84    /// let client = Client::connect("http://localhost:9000").await?;
85    /// let parent: ObjectId = "0x2".parse()?;
86    ///
87    /// let all = client
88    ///     .list_dynamic_fields(parent, Some(50), None, None)
89    ///     .collect(None)
90    ///     .await?;
91    /// for field in all.body() {
92    ///     println!("Dynamic field: {:?}", field);
93    /// }
94    /// # Ok(())
95    /// # }
96    /// ```
97    pub fn list_dynamic_fields(
98        &self,
99        parent: ObjectId,
100        page_size: Option<u32>,
101        page_token: Option<prost::bytes::Bytes>,
102        read_mask: Option<&str>,
103    ) -> ListDynamicFieldsQuery {
104        let base_request = ListDynamicFieldsRequest::default()
105            .with_parent(proto_object_id(parent))
106            .with_read_mask(field_mask_with_default(
107                read_mask,
108                LIST_DYNAMIC_FIELDS_READ_MASK,
109            ));
110
111        ListDynamicFieldsQuery::new(
112            self.state_service_client(),
113            base_request,
114            self.max_decoding_message_size(),
115            page_size,
116            page_token,
117        )
118    }
119}