fuel_core/schema/
gas_price.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
use super::scalars::{
    U32,
    U64,
};
use crate::{
    graphql_api::{
        api_service::GasPriceProvider,
        query_costs,
    },
    schema::ReadViewProvider,
};
use async_graphql::{
    Context,
    Object,
};
use fuel_core_types::{
    blockchain::block::Block,
    fuel_tx::{
        field::MintGasPrice,
        Transaction,
    },
};

pub struct LatestGasPrice {
    pub gas_price: U64,
    pub block_height: U32,
}

#[Object]
impl LatestGasPrice {
    async fn gas_price(&self) -> U64 {
        self.gas_price
    }

    async fn block_height(&self) -> U32 {
        self.block_height
    }
}

#[derive(Default)]
pub struct LatestGasPriceQuery {}

#[Object]
impl LatestGasPriceQuery {
    #[graphql(complexity = "query_costs().block_header")]
    async fn latest_gas_price(
        &self,
        ctx: &Context<'_>,
    ) -> async_graphql::Result<LatestGasPrice> {
        let query = ctx.read_view()?;

        let latest_block: Block<_> = query.latest_block()?;
        let block_height: u32 = (*latest_block.header().height()).into();
        let mut gas_price: U64 = 0.into();
        if let Some(tx_id) = latest_block.transactions().last() {
            if let Transaction::Mint(mint_tx) = query.transaction(tx_id)? {
                gas_price = (*mint_tx.gas_price()).into();
            }
        }
        Ok(LatestGasPrice {
            gas_price,
            block_height: block_height.into(),
        })
    }
}

pub struct EstimateGasPrice {
    pub gas_price: U64,
}

#[Object]
impl EstimateGasPrice {
    async fn gas_price(&self) -> U64 {
        self.gas_price
    }
}

#[derive(Default)]
pub struct EstimateGasPriceQuery {}

#[Object]
impl EstimateGasPriceQuery {
    #[graphql(complexity = "2 * query_costs().storage_read")]
    async fn estimate_gas_price(
        &self,
        ctx: &Context<'_>,
        #[graphql(
            desc = "Number of blocks into the future to estimate the gas price for"
        )]
        block_horizon: Option<U32>,
    ) -> async_graphql::Result<EstimateGasPrice> {
        let query = ctx.read_view()?;

        let latest_block_height: u32 = query.latest_block_height()?.into();
        let target_block = block_horizon
            .and_then(|h| h.0.checked_add(latest_block_height))
            .ok_or(async_graphql::Error::new(format!(
                "Invalid block horizon. Overflows latest block :{latest_block_height:?}"
            )))?;

        let gas_price_provider = ctx.data_unchecked::<GasPriceProvider>();
        let gas_price = gas_price_provider
            .worst_case_gas_price(target_block.into())
            .await
            .ok_or(async_graphql::Error::new(format!(
                "Failed to estimate gas price for block, algorithm not yet set: {target_block:?}"
            )))?;

        Ok(EstimateGasPrice {
            gas_price: gas_price.into(),
        })
    }
}