sui_graphql_rpc/types/
display.rsuse async_graphql::*;
use diesel::{ExpressionMethods, OptionalExtension, QueryDsl};
use diesel_async::scoped_futures::ScopedFutureExt;
use move_core_types::annotated_value as A;
use sui_display::v1::Format;
use sui_indexer::{models::display::StoredDisplay, schema::display};
use sui_types::TypeTag;
use crate::{
data::{Db, DbConnection, QueryExecutor},
error::Error,
};
pub(crate) struct Display {
pub stored: StoredDisplay,
}
const MAX_DEPTH: usize = 10;
const MAX_OUTPUT_SIZE: usize = 1024 * 1024;
#[derive(Debug, SimpleObject)]
pub(crate) struct DisplayEntry {
pub key: String,
pub value: Option<String>,
pub error: Option<String>,
}
impl Display {
pub(crate) async fn query(db: &Db, type_: TypeTag) -> Result<Option<Display>, Error> {
let stored: Option<StoredDisplay> = db
.execute(move |conn| {
async move {
conn.first(move || {
use display::dsl;
dsl::display.filter(
dsl::object_type.eq(type_.to_canonical_string(true)),
)
})
.await
.optional()
}
.scope_boxed()
})
.await?;
Ok(stored.map(|stored| Display { stored }))
}
pub(crate) fn render(
&self,
bytes: &[u8],
layout: &A::MoveTypeLayout,
) -> Result<Vec<DisplayEntry>, Error> {
let fields = self
.stored
.to_display_update_event()
.map_err(|e| Error::Internal(e.to_string()))?
.fields;
let mut rendered = vec![];
for (field, value) in Format::parse(MAX_DEPTH, &fields)
.map_err(|e| Error::Client(e.to_string()))?
.display(MAX_OUTPUT_SIZE, bytes, layout)
.map_err(|e| Error::Client(e.to_string()))?
{
rendered.push(match value {
Ok(v) => DisplayEntry::create_value(field, v),
Err(e) => DisplayEntry::create_error(field, e.to_string()),
});
}
Ok(rendered)
}
}
impl DisplayEntry {
pub(crate) fn create_value(key: String, value: String) -> Self {
Self {
key,
value: Some(value),
error: None,
}
}
pub(crate) fn create_error(key: String, error: String) -> Self {
Self {
key,
value: None,
error: Some(error),
}
}
}