1use crate::{
2 fuel_core_graphql_api::{
3 api_service::ChainInfoProvider,
4 query_costs,
5 },
6 graphql_api::Config,
7 schema::{
8 ReadViewProvider,
9 block::Block,
10 scalars::{
11 Address,
12 AssetId,
13 U16,
14 U32,
15 U64,
16 },
17 },
18};
19use async_graphql::{
20 Context,
21 Enum,
22 Object,
23 Union,
24};
25use fuel_core_types::{
26 fuel_tx,
27 fuel_tx::GasCostsValues,
28};
29use std::{
30 ops::Deref,
31 sync::Arc,
32};
33
34pub struct ChainInfo;
35pub struct ConsensusParameters(pub Arc<fuel_tx::ConsensusParameters>);
36pub struct TxParameters(fuel_tx::TxParameters);
37pub struct PredicateParameters(fuel_tx::PredicateParameters);
38pub struct ScriptParameters(fuel_tx::ScriptParameters);
39pub struct ContractParameters(fuel_tx::ContractParameters);
40pub struct FeeParameters(fuel_tx::FeeParameters);
41
42pub struct GasCosts(fuel_tx::GasCosts);
43
44#[derive(Clone, Copy, Debug, Enum, Eq, PartialEq)]
45pub enum GasCostsVersion {
46 V1,
47}
48
49#[derive(Clone, Copy, Debug, Enum, Eq, PartialEq)]
50pub enum FeeParametersVersion {
51 V1,
52}
53
54#[derive(Clone, Copy, Debug, Enum, Eq, PartialEq)]
55pub enum ContractParametersVersion {
56 V1,
57}
58
59#[derive(Clone, Copy, Debug, Enum, Eq, PartialEq)]
60pub enum ScriptParametersVersion {
61 V1,
62 V2,
63}
64
65#[derive(Clone, Copy, Debug, Enum, Eq, PartialEq)]
66pub enum PredicateParametersVersion {
67 V1,
68}
69
70#[derive(Clone, Copy, Debug, Enum, Eq, PartialEq)]
71pub enum TxParametersVersion {
72 V1,
73}
74
75#[derive(Clone, Copy, Debug, Enum, Eq, PartialEq)]
76pub enum ConsensusParametersVersion {
77 V1,
78}
79
80#[derive(Union)]
81pub enum DependentCost {
82 LightOperation(LightOperation),
83 HeavyOperation(HeavyOperation),
84}
85
86pub struct LightOperation {
87 base: u64,
88 units_per_gas: u64,
89}
90
91pub struct HeavyOperation {
92 base: u64,
93 gas_per_unit: u64,
94}
95
96impl From<fuel_tx::DependentCost> for DependentCost {
97 fn from(value: fuel_tx::DependentCost) -> Self {
98 match value {
99 fuel_tx::DependentCost::LightOperation {
100 base,
101 units_per_gas,
102 } => DependentCost::LightOperation(LightOperation {
103 base,
104 units_per_gas,
105 }),
106 fuel_tx::DependentCost::HeavyOperation { base, gas_per_unit } => {
107 DependentCost::HeavyOperation(HeavyOperation { base, gas_per_unit })
108 }
109 }
110 }
111}
112
113#[Object]
114impl ConsensusParameters {
115 async fn version(&self) -> ConsensusParametersVersion {
116 match self.0.as_ref() {
117 fuel_tx::ConsensusParameters::V1(_) | fuel_tx::ConsensusParameters::V2(_) => {
118 ConsensusParametersVersion::V1
119 }
120 }
121 }
122
123 async fn tx_params(&self) -> TxParameters {
124 TxParameters(self.0.tx_params().to_owned())
125 }
126
127 async fn predicate_params(&self) -> PredicateParameters {
128 PredicateParameters(self.0.predicate_params().to_owned())
129 }
130
131 async fn script_params(&self) -> ScriptParameters {
132 ScriptParameters(self.0.script_params().to_owned())
133 }
134
135 async fn contract_params(&self) -> ContractParameters {
136 ContractParameters(self.0.contract_params().to_owned())
137 }
138
139 async fn fee_params(&self) -> FeeParameters {
140 FeeParameters(self.0.fee_params().to_owned())
141 }
142
143 async fn base_asset_id(&self) -> AssetId {
144 AssetId(*self.0.base_asset_id())
145 }
146
147 async fn block_gas_limit(&self) -> U64 {
148 self.0.block_gas_limit().into()
149 }
150
151 async fn block_transaction_size_limit(&self) -> U64 {
152 self.0.block_transaction_size_limit().into()
153 }
154
155 async fn chain_id(&self) -> U64 {
156 (*self.0.chain_id()).into()
157 }
158
159 async fn gas_costs(&self) -> async_graphql::Result<GasCosts> {
160 Ok(GasCosts(self.0.gas_costs().clone()))
161 }
162
163 async fn privileged_address(&self) -> async_graphql::Result<Address> {
164 Ok(Address(*self.0.privileged_address()))
165 }
166}
167
168#[Object]
169impl TxParameters {
170 async fn version(&self) -> TxParametersVersion {
171 match self.0 {
172 fuel_tx::TxParameters::V1(_) => TxParametersVersion::V1,
173 }
174 }
175
176 async fn max_inputs(&self) -> U16 {
177 self.0.max_inputs().into()
178 }
179
180 async fn max_outputs(&self) -> U16 {
181 self.0.max_outputs().into()
182 }
183
184 async fn max_witnesses(&self) -> U32 {
185 self.0.max_witnesses().into()
186 }
187
188 async fn max_gas_per_tx(&self) -> U64 {
189 self.0.max_gas_per_tx().into()
190 }
191
192 async fn max_size(&self) -> U64 {
193 self.0.max_size().into()
194 }
195
196 async fn max_bytecode_subsections(&self) -> U16 {
197 self.0.max_bytecode_subsections().into()
198 }
199}
200
201#[Object]
202impl PredicateParameters {
203 async fn version(&self) -> PredicateParametersVersion {
204 match self.0 {
205 fuel_tx::PredicateParameters::V1(_) => PredicateParametersVersion::V1,
206 }
207 }
208
209 async fn max_predicate_length(&self) -> U64 {
210 self.0.max_predicate_length().into()
211 }
212
213 async fn max_predicate_data_length(&self) -> U64 {
214 self.0.max_predicate_data_length().into()
215 }
216
217 async fn max_gas_per_predicate(&self) -> U64 {
218 self.0.max_gas_per_predicate().into()
219 }
220
221 async fn max_message_data_length(&self) -> U64 {
222 self.0.max_message_data_length().into()
223 }
224}
225
226#[Object]
227impl ScriptParameters {
228 async fn version(&self) -> ScriptParametersVersion {
229 match self.0 {
230 fuel_tx::ScriptParameters::V1(_) => ScriptParametersVersion::V1,
231 fuel_tx::ScriptParameters::V2(_) => ScriptParametersVersion::V2,
232 }
233 }
234
235 async fn max_script_length(&self) -> U64 {
236 self.0.max_script_length().into()
237 }
238
239 async fn max_script_data_length(&self) -> U64 {
240 self.0.max_script_data_length().into()
241 }
242
243 async fn max_storage_slot_length(&self) -> U64 {
244 self.0.max_storage_slot_length().into()
245 }
246}
247
248#[Object]
249impl ContractParameters {
250 async fn version(&self) -> ContractParametersVersion {
251 match self.0 {
252 fuel_tx::ContractParameters::V1(_) => ContractParametersVersion::V1,
253 }
254 }
255
256 async fn contract_max_size(&self) -> U64 {
257 self.0.contract_max_size().into()
258 }
259
260 async fn max_storage_slots(&self) -> U64 {
261 self.0.max_storage_slots().into()
262 }
263}
264
265#[Object]
266impl FeeParameters {
267 async fn version(&self) -> FeeParametersVersion {
268 match self.0 {
269 fuel_tx::FeeParameters::V1(_) => FeeParametersVersion::V1,
270 }
271 }
272
273 async fn gas_price_factor(&self) -> U64 {
274 self.0.gas_price_factor().into()
275 }
276
277 async fn gas_per_byte(&self) -> U64 {
278 self.0.gas_per_byte().into()
279 }
280}
281
282#[Object]
283impl GasCosts {
284 async fn version(&self) -> GasCostsVersion {
285 match self.0.deref() {
286 GasCostsValues::V1(_)
287 | GasCostsValues::V2(_)
288 | GasCostsValues::V3(_)
289 | GasCostsValues::V4(_)
290 | GasCostsValues::V5(_)
291 | GasCostsValues::V6(_)
292 | GasCostsValues::V7(_) => GasCostsVersion::V1,
293 }
294 }
295
296 async fn add(&self) -> U64 {
297 self.0.add().into()
298 }
299
300 async fn addi(&self) -> U64 {
301 self.0.addi().into()
302 }
303
304 async fn aloc(&self) -> U64 {
305 self.0.aloc().base().into()
306 }
307
308 async fn and(&self) -> U64 {
309 self.0.and().into()
310 }
311
312 async fn andi(&self) -> U64 {
313 self.0.andi().into()
314 }
315
316 async fn bal(&self) -> U64 {
317 self.0.bal().into()
318 }
319
320 async fn bhei(&self) -> U64 {
321 self.0.bhei().into()
322 }
323
324 async fn bhsh(&self) -> U64 {
325 self.0.bhsh().into()
326 }
327
328 async fn burn(&self) -> U64 {
329 self.0.burn().into()
330 }
331
332 async fn cb(&self) -> U64 {
333 self.0.cb().into()
334 }
335
336 async fn cfei(&self) -> U64 {
337 self.0.cfei().base().into()
338 }
339
340 async fn cfsi(&self) -> U64 {
341 self.0.cfsi().into()
342 }
343
344 async fn div(&self) -> U64 {
345 self.0.div().into()
346 }
347
348 async fn divi(&self) -> U64 {
349 self.0.divi().into()
350 }
351
352 async fn ecr1(&self) -> U64 {
353 self.0.ecr1().into()
354 }
355
356 async fn eck1(&self) -> U64 {
357 self.0.eck1().into()
358 }
359
360 async fn ed19(&self) -> U64 {
361 self.0.ed19().base().into()
362 }
363
364 async fn eq(&self) -> U64 {
365 self.0.eq_().into()
366 }
367
368 async fn exp(&self) -> U64 {
369 self.0.exp().into()
370 }
371
372 async fn expi(&self) -> U64 {
373 self.0.expi().into()
374 }
375
376 async fn flag(&self) -> U64 {
377 self.0.flag().into()
378 }
379
380 async fn gm(&self) -> U64 {
381 self.0.gm().into()
382 }
383
384 async fn gt(&self) -> U64 {
385 self.0.gt().into()
386 }
387
388 async fn gtf(&self) -> U64 {
389 self.0.gtf().into()
390 }
391
392 async fn ji(&self) -> U64 {
393 self.0.ji().into()
394 }
395
396 async fn jmp(&self) -> U64 {
397 self.0.jmp().into()
398 }
399
400 async fn jne(&self) -> U64 {
401 self.0.jne().into()
402 }
403
404 async fn jnei(&self) -> U64 {
405 self.0.jnei().into()
406 }
407
408 async fn jnzi(&self) -> U64 {
409 self.0.jnzi().into()
410 }
411
412 async fn jmpf(&self) -> U64 {
413 self.0.jmpf().into()
414 }
415
416 async fn jmpb(&self) -> U64 {
417 self.0.jmpb().into()
418 }
419
420 async fn jnzf(&self) -> U64 {
421 self.0.jnzf().into()
422 }
423
424 async fn jnzb(&self) -> U64 {
425 self.0.jnzb().into()
426 }
427
428 async fn jnef(&self) -> U64 {
429 self.0.jnef().into()
430 }
431
432 async fn jneb(&self) -> U64 {
433 self.0.jneb().into()
434 }
435
436 async fn lb(&self) -> U64 {
437 self.0.lb().into()
438 }
439
440 async fn log(&self) -> U64 {
441 self.0.log().into()
442 }
443
444 async fn lt(&self) -> U64 {
445 self.0.lt().into()
446 }
447
448 async fn lw(&self) -> U64 {
449 self.0.lw().into()
450 }
451
452 async fn mint(&self) -> U64 {
453 self.0.mint().into()
454 }
455
456 async fn mlog(&self) -> U64 {
457 self.0.mlog().into()
458 }
459
460 async fn mod_op(&self) -> U64 {
461 self.0.mod_op().into()
462 }
463
464 async fn modi(&self) -> U64 {
465 self.0.modi().into()
466 }
467
468 async fn move_op(&self) -> U64 {
469 self.0.move_op().into()
470 }
471
472 async fn movi(&self) -> U64 {
473 self.0.movi().into()
474 }
475
476 async fn mroo(&self) -> U64 {
477 self.0.mroo().into()
478 }
479
480 async fn mul(&self) -> U64 {
481 self.0.mul().into()
482 }
483
484 async fn muli(&self) -> U64 {
485 self.0.muli().into()
486 }
487
488 async fn mldv(&self) -> U64 {
489 self.0.mldv().into()
490 }
491
492 async fn niop(&self) -> Option<U64> {
493 self.0.niop().ok().map(Into::into)
494 }
495
496 async fn noop(&self) -> U64 {
497 self.0.noop().into()
498 }
499
500 async fn not(&self) -> U64 {
501 self.0.not().into()
502 }
503
504 async fn or(&self) -> U64 {
505 self.0.or().into()
506 }
507
508 async fn ori(&self) -> U64 {
509 self.0.ori().into()
510 }
511
512 async fn poph(&self) -> U64 {
513 self.0.poph().into()
514 }
515
516 async fn popl(&self) -> U64 {
517 self.0.popl().into()
518 }
519
520 async fn pshh(&self) -> U64 {
521 self.0.pshh().into()
522 }
523
524 async fn pshl(&self) -> U64 {
525 self.0.pshl().into()
526 }
527
528 async fn ret(&self) -> U64 {
529 self.0.ret().into()
530 }
531
532 async fn rvrt(&self) -> U64 {
533 self.0.rvrt().into()
534 }
535
536 async fn sb(&self) -> U64 {
537 self.0.sb().into()
538 }
539
540 async fn sll(&self) -> U64 {
541 self.0.sll().into()
542 }
543
544 async fn slli(&self) -> U64 {
545 self.0.slli().into()
546 }
547
548 async fn srl(&self) -> U64 {
549 self.0.srl().into()
550 }
551
552 async fn srli(&self) -> U64 {
553 self.0.srli().into()
554 }
555
556 async fn srw(&self) -> Option<U64> {
557 self.0.srw().ok().map(Into::into)
558 }
559
560 async fn sub(&self) -> U64 {
561 self.0.sub().into()
562 }
563
564 async fn subi(&self) -> U64 {
565 self.0.subi().into()
566 }
567
568 async fn sw(&self) -> U64 {
569 self.0.sw().into()
570 }
571
572 async fn sww(&self) -> Option<U64> {
573 self.0.sww().ok().map(Into::into)
574 }
575
576 async fn time(&self) -> U64 {
577 self.0.time().into()
578 }
579
580 async fn tr(&self) -> U64 {
581 self.0.tr().into()
582 }
583
584 async fn tro(&self) -> U64 {
585 self.0.tro().into()
586 }
587
588 async fn wdcm(&self) -> U64 {
589 self.0.wdcm().into()
590 }
591
592 async fn wqcm(&self) -> U64 {
593 self.0.wqcm().into()
594 }
595
596 async fn wdop(&self) -> U64 {
597 self.0.wdop().into()
598 }
599
600 async fn wqop(&self) -> U64 {
601 self.0.wqop().into()
602 }
603
604 async fn wdml(&self) -> U64 {
605 self.0.wdml().into()
606 }
607
608 async fn wqml(&self) -> U64 {
609 self.0.wqml().into()
610 }
611
612 async fn wddv(&self) -> U64 {
613 self.0.wddv().into()
614 }
615
616 async fn wqdv(&self) -> U64 {
617 self.0.wqdv().into()
618 }
619
620 async fn wdmd(&self) -> U64 {
621 self.0.wdmd().into()
622 }
623
624 async fn wqmd(&self) -> U64 {
625 self.0.wqmd().into()
626 }
627
628 async fn wdam(&self) -> U64 {
629 self.0.wdam().into()
630 }
631
632 async fn wqam(&self) -> U64 {
633 self.0.wqam().into()
634 }
635
636 async fn wdmm(&self) -> U64 {
637 self.0.wdmm().into()
638 }
639
640 async fn wqmm(&self) -> U64 {
641 self.0.wqmm().into()
642 }
643
644 async fn xor(&self) -> U64 {
645 self.0.xor().into()
646 }
647
648 async fn xori(&self) -> U64 {
649 self.0.xori().into()
650 }
651
652 async fn ecop(&self) -> Option<U64> {
653 self.0.ecop().ok().map(Into::into)
654 }
655
656 async fn aloc_dependent_cost(&self) -> DependentCost {
657 self.0.aloc().into()
658 }
659
660 async fn bldd(&self) -> Option<DependentCost> {
661 self.0.bldd().ok().map(Into::into)
662 }
663
664 async fn bsiz(&self) -> Option<DependentCost> {
665 self.0.bsiz().ok().map(Into::into)
666 }
667
668 async fn cfe(&self) -> DependentCost {
669 self.0.cfe().into()
670 }
671
672 async fn cfei_dependent_cost(&self) -> DependentCost {
673 self.0.cfei().into()
674 }
675
676 async fn call(&self) -> DependentCost {
677 self.0.call().into()
678 }
679
680 async fn ccp(&self) -> DependentCost {
681 self.0.ccp().into()
682 }
683
684 async fn croo(&self) -> DependentCost {
685 self.0.croo().into()
686 }
687
688 async fn csiz(&self) -> DependentCost {
689 self.0.csiz().into()
690 }
691
692 async fn ed19_dependent_cost(&self) -> DependentCost {
693 self.0.ed19().into()
694 }
695
696 async fn k256(&self) -> DependentCost {
697 self.0.k256().into()
698 }
699
700 async fn ldc(&self) -> DependentCost {
701 self.0.ldc().into()
702 }
703
704 async fn logd(&self) -> DependentCost {
705 self.0.logd().into()
706 }
707
708 async fn mcl(&self) -> DependentCost {
709 self.0.mcl().into()
710 }
711
712 async fn mcli(&self) -> DependentCost {
713 self.0.mcli().into()
714 }
715
716 async fn mcp(&self) -> DependentCost {
717 self.0.mcp().into()
718 }
719
720 async fn mcpi(&self) -> DependentCost {
721 self.0.mcpi().into()
722 }
723
724 async fn meq(&self) -> DependentCost {
725 self.0.meq().into()
726 }
727
728 async fn retd(&self) -> DependentCost {
729 self.0.retd().into()
730 }
731
732 async fn s256(&self) -> DependentCost {
733 self.0.s256().into()
734 }
735
736 async fn scwq(&self) -> Option<DependentCost> {
737 self.0.scwq().ok().map(Into::into)
738 }
739
740 async fn smo(&self) -> DependentCost {
741 self.0.smo().into()
742 }
743
744 async fn srwq(&self) -> Option<DependentCost> {
745 self.0.srwq().ok().map(Into::into)
746 }
747
748 async fn swwq(&self) -> Option<DependentCost> {
749 self.0.swwq().ok().map(Into::into)
750 }
751
752 async fn epar(&self) -> Option<DependentCost> {
753 self.0.epar().ok().map(Into::into)
754 }
755
756 async fn storage_read_cold(&self) -> Option<DependentCost> {
759 self.0.storage_read_cold().ok().map(Into::into)
760 }
761
762 async fn storage_read_hot(&self) -> Option<DependentCost> {
763 self.0.storage_read_hot().ok().map(Into::into)
764 }
765
766 async fn storage_write(&self) -> Option<DependentCost> {
767 self.0.storage_write().ok().map(Into::into)
768 }
769
770 async fn storage_clear(&self) -> Option<DependentCost> {
771 self.0.storage_clear().ok().map(Into::into)
772 }
773
774 async fn contract_root(&self) -> DependentCost {
777 self.0.contract_root().into()
778 }
779
780 async fn state_root(&self) -> DependentCost {
781 self.0.state_root().into()
782 }
783
784 async fn vm_initialization(&self) -> DependentCost {
785 self.0.vm_initialization().into()
786 }
787
788 async fn new_storage_per_byte(&self) -> U64 {
789 self.0.new_storage_per_byte().into()
790 }
791}
792
793#[Object]
794impl LightOperation {
795 async fn base(&self) -> U64 {
796 self.base.into()
797 }
798
799 async fn units_per_gas(&self) -> U64 {
800 self.units_per_gas.into()
801 }
802}
803
804#[Object]
805impl HeavyOperation {
806 async fn base(&self) -> U64 {
807 self.base.into()
808 }
809
810 async fn gas_per_unit(&self) -> U64 {
811 self.gas_per_unit.into()
812 }
813}
814
815#[Object]
816impl ChainInfo {
817 #[graphql(complexity = "query_costs().storage_read")]
818 async fn name(&self, ctx: &Context<'_>) -> async_graphql::Result<String> {
819 let config: &Config = ctx.data_unchecked();
820 Ok(config.chain_name.clone())
821 }
822
823 #[graphql(complexity = "query_costs().storage_read + child_complexity")]
824 async fn latest_block(&self, ctx: &Context<'_>) -> async_graphql::Result<Block> {
825 let query = ctx.read_view()?;
826
827 let latest_block = query.latest_block()?.into();
828 Ok(latest_block)
829 }
830
831 #[graphql(complexity = "query_costs().storage_read")]
832 async fn da_height(&self, ctx: &Context<'_>) -> U64 {
833 let Ok(query) = ctx.read_view() else {
834 return 0.into();
835 };
836
837 query.da_height().unwrap_or_default().0.into()
838 }
839
840 #[graphql(complexity = "query_costs().storage_read + child_complexity")]
841 async fn consensus_parameters(
842 &self,
843 ctx: &Context<'_>,
844 ) -> async_graphql::Result<ConsensusParameters> {
845 let params = ctx
846 .data_unchecked::<ChainInfoProvider>()
847 .current_consensus_params();
848
849 Ok(ConsensusParameters(params))
850 }
851
852 #[graphql(complexity = "query_costs().storage_read + child_complexity")]
853 async fn gas_costs(&self, ctx: &Context<'_>) -> async_graphql::Result<GasCosts> {
854 let params = ctx
855 .data_unchecked::<ChainInfoProvider>()
856 .current_consensus_params();
857
858 Ok(GasCosts(params.gas_costs().clone()))
859 }
860}
861
862#[derive(Default)]
863pub struct ChainQuery;
864
865#[Object]
866impl ChainQuery {
867 async fn chain(&self) -> ChainInfo {
868 ChainInfo
869 }
870}