fuel_core/schema/
contract.rs1use crate::{
2 fuel_core_graphql_api::{
3 IntoApiResult,
4 query_costs,
5 },
6 schema::{
7 ReadViewProvider,
8 scalars::{
9 AssetId,
10 ContractId,
11 HexString,
12 Salt,
13 U64,
14 },
15 },
16};
17use async_graphql::{
18 Context,
19 InputObject,
20 Object,
21 connection::{
22 Connection,
23 EmptyFields,
24 },
25};
26use fuel_core_storage::{
27 not_found,
28 tables::ContractsRawCode,
29};
30use fuel_core_types::{
31 fuel_types,
32 services::graphql_api,
33};
34use futures::StreamExt;
35
36pub struct Contract(pub(crate) fuel_types::ContractId);
37
38impl From<fuel_types::ContractId> for Contract {
39 fn from(id: fuel_types::ContractId) -> Self {
40 Self(id)
41 }
42}
43
44#[Object]
45impl Contract {
46 async fn id(&self) -> ContractId {
47 self.0.into()
48 }
49
50 #[graphql(complexity = "query_costs().bytecode_read")]
51 async fn bytecode(&self, ctx: &Context<'_>) -> async_graphql::Result<HexString> {
52 let query = ctx.read_view()?;
53 query
54 .contract_bytecode(self.0)
55 .map(HexString)
56 .map_err(Into::into)
57 }
58
59 #[graphql(complexity = "query_costs().storage_read")]
60 async fn salt(&self, ctx: &Context<'_>) -> async_graphql::Result<Salt> {
61 let query = ctx.read_view()?;
62 query
63 .contract_salt(&self.0)
64 .map(Into::into)
65 .map_err(Into::into)
66 }
67}
68
69#[derive(Default)]
70pub struct ContractQuery;
71
72#[Object]
73impl ContractQuery {
74 #[graphql(complexity = "query_costs().storage_read + child_complexity")]
75 async fn contract(
76 &self,
77 ctx: &Context<'_>,
78 #[graphql(desc = "ID of the Contract")] id: ContractId,
79 ) -> async_graphql::Result<Option<Contract>> {
80 let query = ctx.read_view()?;
81 query
82 .contract_exists(id.0)
83 .and_then(|contract_exists| {
84 if contract_exists {
85 Ok(id.0)
86 } else {
87 Err(not_found!(ContractsRawCode))
88 }
89 })
90 .into_api_result()
91 }
92}
93
94pub struct ContractBalance(graphql_api::ContractBalance);
95
96#[Object]
97impl ContractBalance {
98 async fn contract(&self) -> ContractId {
99 self.0.owner.into()
100 }
101
102 async fn amount(&self) -> U64 {
103 self.0.amount.into()
104 }
105
106 async fn asset_id(&self) -> AssetId {
107 self.0.asset_id.into()
108 }
109}
110
111#[derive(InputObject)]
112struct ContractBalanceFilterInput {
113 contract: ContractId,
115}
116
117#[derive(Default)]
118pub struct ContractBalanceQuery;
119
120#[Object]
121impl ContractBalanceQuery {
122 #[graphql(complexity = "query_costs().storage_read")]
123 async fn contract_balance(
124 &self,
125 ctx: &Context<'_>,
126 contract: ContractId,
127 asset: AssetId,
128 ) -> async_graphql::Result<ContractBalance> {
129 let contract_id = contract.into();
130 let asset_id = asset.into();
131 let query = ctx.read_view()?;
132 query
133 .contract_balance(contract_id, asset_id)
134 .into_api_result()
135 .map(|result| {
136 result.unwrap_or_else(|| {
137 graphql_api::ContractBalance {
138 owner: contract_id,
139 amount: 0,
140 asset_id,
141 }
142 .into()
143 })
144 })
145 }
146
147 #[graphql(complexity = "{\
148 query_costs().storage_iterator\
149 + (query_costs().storage_read + first.unwrap_or_default() as usize) * child_complexity \
150 + (query_costs().storage_read + last.unwrap_or_default() as usize) * child_complexity\
151 }")]
152 async fn contract_balances(
153 &self,
154 ctx: &Context<'_>,
155 filter: ContractBalanceFilterInput,
156 first: Option<i32>,
157 after: Option<String>,
158 last: Option<i32>,
159 before: Option<String>,
160 ) -> async_graphql::Result<
161 Connection<AssetId, ContractBalance, EmptyFields, EmptyFields>,
162 > {
163 let query = ctx.read_view()?;
164
165 crate::schema::query_pagination(after, before, first, last, |start, direction| {
166 let balances = query
167 .contract_balances(
168 filter.contract.into(),
169 (*start).map(Into::into),
170 direction,
171 )
172 .map(|balance| {
173 let balance = balance?;
174 let asset_id = balance.asset_id;
175
176 Ok((asset_id.into(), balance.into()))
177 });
178
179 Ok(balances)
180 })
181 .await
182 }
183}
184
185impl From<graphql_api::ContractBalance> for ContractBalance {
186 fn from(balance: graphql_api::ContractBalance) -> Self {
187 ContractBalance(balance)
188 }
189}