-
Notifications
You must be signed in to change notification settings - Fork 358
/
Copy patheip_base_fee.rs
141 lines (109 loc) · 3.64 KB
/
eip_base_fee.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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
use core::fmt;
use std::ops::Div;
use std::str::FromStr;
use serde::Deserialize;
use subtle_encoding::base64;
use tendermint_rpc::Url;
use tracing::debug;
use ibc_proto::cosmos::base::v1beta1::DecProto;
use crate::error::Error;
pub async fn query_eip_base_fee(rpc_address: &Url) -> Result<f64, Error> {
debug!("Querying Omosis EIP-1559 base fee from {rpc_address}");
let url =
format!("{rpc_address}/abci_query?path=\"/osmosis.txfees.v1beta1.Query/GetEipBaseFee\"");
let response = reqwest::get(&url).await.map_err(Error::http_request)?;
if !response.status().is_success() {
return Err(Error::http_response(response.status()));
}
#[derive(Deserialize)]
struct EipBaseFeeHTTPResult {
result: EipBaseFeeResult,
}
#[derive(Deserialize)]
struct EipBaseFeeResult {
response: EipBaseFeeResponse,
}
#[derive(Deserialize)]
struct EipBaseFeeResponse {
value: String,
}
let result: EipBaseFeeHTTPResult = response.json().await.map_err(Error::http_response_body)?;
let encoded = result.result.response.value;
let decoded = base64::decode(encoded).map_err(Error::base64_decode)?;
let dec_proto: DecProto = prost::Message::decode(decoded.as_ref())
.map_err(|e| Error::protobuf_decode("cosmos.base.v1beta1.DecProto".to_string(), e))?;
let base_fee_uint128 = Uint128::from_str(&dec_proto.dec).map_err(Error::parse_int)?;
let dec = Decimal::new(base_fee_uint128);
let base_fee = f64::from_str(dec.to_string().as_str()).map_err(Error::parse_float)?;
debug!("Omosis EIP-1559 base fee is {}", base_fee);
Ok(base_fee)
}
/// Extracted from `cosmwasm-std`
///
/// <https://docs.rs/cosmwasm-std/latest/src/cosmwasm_std/math/uint128.rs.html>
#[derive(Clone, Copy)]
struct Uint128(u128);
impl Uint128 {
pub const fn new(value: u128) -> Self {
Self(value)
}
pub fn is_zero(&self) -> bool {
self.0 == 0
}
pub fn checked_rem(&self, rhs: Self) -> Option<Self> {
self.0.checked_rem(rhs.0).map(Self)
}
}
impl FromStr for Uint128 {
type Err = std::num::ParseIntError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
s.parse::<u128>().map(Self)
}
}
impl Div<Uint128> for Uint128 {
type Output = Self;
fn div(self, rhs: Self) -> Self::Output {
Self(
self.0
.checked_div(rhs.0)
.expect("attempt to divide by zero"),
)
}
}
impl fmt::Display for Uint128 {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(f)
}
}
/// Extracted from `cosmwasm-std`
///
/// <https://docs.rs/cosmwasm-std/latest/src/cosmwasm_std/math/decimal.rs.html>
#[derive(Clone, Copy)]
struct Decimal(Uint128);
impl Decimal {
const DECIMAL_FRACTIONAL: Uint128 = Uint128::new(1_000_000_000_000_000_000u128); // 1*10**18
pub const DECIMAL_PLACES: u32 = 18;
pub const fn new(value: Uint128) -> Self {
Self(value)
}
}
impl fmt::Display for Decimal {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use core::fmt::Write;
let whole = (self.0) / Self::DECIMAL_FRACTIONAL;
let fractional = (self.0).checked_rem(Self::DECIMAL_FRACTIONAL).unwrap();
if fractional.is_zero() {
write!(f, "{whole}")
} else {
let fractional_string = format!(
"{:0>padding$}",
fractional,
padding = Self::DECIMAL_PLACES as usize
);
f.write_str(&whole.to_string())?;
f.write_char('.')?;
f.write_str(fractional_string.trim_end_matches('0'))?;
Ok(())
}
}
}