Skip to main content

fuel_core/schema/
chain.rs

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    // Storage micro-ops
757
758    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    // Non-opcode prices
775
776    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}