sui_indexer_alt_jsonrpc/api/objects/
mod.rs1use filter::SuiObjectResponseQuery;
5use futures::future;
6use jsonrpsee::core::RpcResult;
7use jsonrpsee::proc_macros::rpc;
8use mysten_common::ZipDebugEqIteratorExt;
9use sui_json_rpc_types::Page;
10use sui_json_rpc_types::SuiGetPastObjectRequest;
11use sui_json_rpc_types::SuiObjectDataOptions;
12use sui_json_rpc_types::SuiObjectResponse;
13use sui_json_rpc_types::SuiPastObjectResponse;
14use sui_types::base_types::ObjectID;
15use sui_types::base_types::SequenceNumber;
16use sui_types::base_types::SuiAddress;
17
18use crate::api::objects::error::Error;
19use crate::api::rpc_module::RpcModule;
20use crate::context::Context;
21use crate::error::InternalContext;
22use crate::error::invalid_params;
23
24mod error;
25pub(crate) mod filter;
26pub(crate) mod response;
27
28#[rpc(server, namespace = "sui")]
29trait ObjectsApi {
30 #[method(name = "getObject")]
32 async fn get_object(
33 &self,
34 object_id: ObjectID,
36 options: Option<SuiObjectDataOptions>,
38 ) -> RpcResult<SuiObjectResponse>;
39
40 #[method(name = "multiGetObjects")]
42 async fn multi_get_objects(
43 &self,
44 object_ids: Vec<ObjectID>,
46 options: Option<SuiObjectDataOptions>,
48 ) -> RpcResult<Vec<SuiObjectResponse>>;
49
50 #[method(name = "tryGetPastObject")]
56 async fn try_get_past_object(
57 &self,
58 object_id: ObjectID,
60 version: SequenceNumber,
62 options: Option<SuiObjectDataOptions>,
64 ) -> RpcResult<SuiPastObjectResponse>;
65
66 #[method(name = "tryMultiGetPastObjects")]
72 async fn try_multi_get_past_objects(
73 &self,
74 past_objects: Vec<SuiGetPastObjectRequest>,
76 options: Option<SuiObjectDataOptions>,
78 ) -> RpcResult<Vec<SuiPastObjectResponse>>;
79}
80
81#[rpc(server, namespace = "suix")]
82trait QueryObjectsApi {
83 #[method(name = "getOwnedObjects")]
97 async fn get_owned_objects(
98 &self,
99 address: SuiAddress,
101 query: Option<SuiObjectResponseQuery>,
103 cursor: Option<String>,
105 limit: Option<usize>,
107 ) -> RpcResult<Page<SuiObjectResponse, String>>;
108}
109
110pub(crate) struct Objects(pub Context);
111
112pub(crate) struct QueryObjects(pub Context);
113
114#[async_trait::async_trait]
115impl ObjectsApiServer for Objects {
116 async fn get_object(
117 &self,
118 object_id: ObjectID,
119 options: Option<SuiObjectDataOptions>,
120 ) -> RpcResult<SuiObjectResponse> {
121 let Self(ctx) = self;
122 let options = options.unwrap_or_default();
123 Ok(response::live_object(ctx, object_id, &options)
124 .await
125 .with_internal_context(|| {
126 format!("Failed to get object {object_id} at latest version")
127 })?)
128 }
129
130 async fn multi_get_objects(
131 &self,
132 object_ids: Vec<ObjectID>,
133 options: Option<SuiObjectDataOptions>,
134 ) -> RpcResult<Vec<SuiObjectResponse>> {
135 let Self(ctx) = self;
136 let config = &ctx.config().objects;
137 if object_ids.len() > config.max_multi_get_objects {
138 return Err(invalid_params(Error::TooManyKeys {
139 requested: object_ids.len(),
140 max: config.max_multi_get_objects,
141 })
142 .into());
143 }
144
145 let options = options.unwrap_or_default();
146
147 let obj_futures = object_ids
148 .iter()
149 .map(|id| response::live_object(ctx, *id, &options));
150
151 Ok(future::join_all(obj_futures)
152 .await
153 .into_iter()
154 .zip_debug_eq(object_ids)
155 .map(|(r, o)| {
156 r.with_internal_context(|| format!("Failed to get object {o} at latest version"))
157 })
158 .collect::<Result<Vec<_>, _>>()?)
159 }
160
161 async fn try_get_past_object(
162 &self,
163 object_id: ObjectID,
164 version: SequenceNumber,
165 options: Option<SuiObjectDataOptions>,
166 ) -> RpcResult<SuiPastObjectResponse> {
167 let Self(ctx) = self;
168 let options = options.unwrap_or_default();
169 Ok(response::past_object(ctx, object_id, version, &options)
170 .await
171 .with_internal_context(|| {
172 format!(
173 "Failed to get object {object_id} at version {}",
174 version.value()
175 )
176 })?)
177 }
178
179 async fn try_multi_get_past_objects(
180 &self,
181 past_objects: Vec<SuiGetPastObjectRequest>,
182 options: Option<SuiObjectDataOptions>,
183 ) -> RpcResult<Vec<SuiPastObjectResponse>> {
184 let Self(ctx) = self;
185 let config = &ctx.config().objects;
186 if past_objects.len() > config.max_multi_get_objects {
187 return Err(invalid_params(Error::TooManyKeys {
188 requested: past_objects.len(),
189 max: config.max_multi_get_objects,
190 })
191 .into());
192 }
193
194 let options = options.unwrap_or_default();
195
196 let obj_futures = past_objects
197 .iter()
198 .map(|obj| response::past_object(ctx, obj.object_id, obj.version, &options));
199
200 Ok(future::join_all(obj_futures)
201 .await
202 .into_iter()
203 .zip_debug_eq(past_objects)
204 .map(|(r, o)| {
205 let id = o.object_id;
206 let v = o.version;
207 r.with_internal_context(|| format!("Failed to get object {id} at version {v}"))
208 })
209 .collect::<Result<Vec<_>, _>>()?)
210 }
211}
212
213#[async_trait::async_trait]
214impl QueryObjectsApiServer for QueryObjects {
215 async fn get_owned_objects(
216 &self,
217 address: SuiAddress,
218 query: Option<SuiObjectResponseQuery>,
219 cursor: Option<String>,
220 limit: Option<usize>,
221 ) -> RpcResult<Page<SuiObjectResponse, String>> {
222 let Self(ctx) = self;
223
224 let query = query.unwrap_or_default();
225
226 let Page {
227 data: object_ids,
228 next_cursor,
229 has_next_page,
230 } = filter::owned_objects(ctx, address, &query.filter, cursor, limit).await?;
231
232 let options = query.options.unwrap_or_default();
233
234 let obj_futures = object_ids
235 .iter()
236 .map(|id| response::live_object(ctx, *id, &options));
237
238 let data = future::join_all(obj_futures)
239 .await
240 .into_iter()
241 .zip_debug_eq(object_ids)
242 .map(|(r, id)| {
243 r.with_internal_context(|| format!("Failed to get object {id} at latest version"))
244 })
245 .collect::<Result<Vec<_>, _>>()?;
246
247 Ok(Page {
248 data,
249 next_cursor,
250 has_next_page,
251 })
252 }
253}
254
255impl RpcModule for Objects {
256 fn into_impl(self) -> jsonrpsee::RpcModule<Self> {
257 self.into_rpc()
258 }
259}
260
261impl RpcModule for QueryObjects {
262 fn into_impl(self) -> jsonrpsee::RpcModule<Self> {
263 self.into_rpc()
264 }
265}