1use crate::{
2 fuel_core_graphql_api::query_costs,
3 graphql_api::IntoApiResult,
4 schema::{
5 ReadViewProvider,
6 scalars::{
7 BlobId,
8 HexString,
9 },
10 },
11};
12use async_graphql::{
13 Context,
14 Object,
15};
16use fuel_core_storage::{
17 not_found,
18 tables::BlobData,
19};
20use fuel_core_types::fuel_types;
21
22pub struct Blob(fuel_types::BlobId);
23
24#[Object]
25impl Blob {
26 async fn id(&self) -> BlobId {
27 self.0.into()
28 }
29
30 #[graphql(complexity = "query_costs().bytecode_read")]
31 async fn bytecode(&self, ctx: &Context<'_>) -> async_graphql::Result<HexString> {
32 let query = ctx.read_view()?;
33 query
34 .blob_bytecode(self.0)
35 .map(HexString)
36 .map_err(async_graphql::Error::from)
37 }
38}
39
40impl From<fuel_types::BlobId> for Blob {
41 fn from(value: fuel_types::BlobId) -> Self {
42 Self(value)
43 }
44}
45
46#[derive(Default)]
47pub struct BlobQuery;
48
49#[Object]
50impl BlobQuery {
51 #[graphql(complexity = "query_costs().storage_read + child_complexity")]
52 async fn blob(
53 &self,
54 ctx: &Context<'_>,
55 #[graphql(desc = "ID of the Blob")] id: BlobId,
56 ) -> async_graphql::Result<Option<Blob>> {
57 let query = ctx.read_view()?;
58 query
59 .blob_exists(id.0)
60 .and_then(|blob_exists| {
61 if blob_exists {
62 Ok(id.0)
63 } else {
64 Err(not_found!(BlobData))
65 }
66 })
67 .into_api_result()
68 }
69}