From 330754f2285e9d702af3b7c879288e4e127681b7 Mon Sep 17 00:00:00 2001 From: Vid Kersic Date: Thu, 27 Jun 2024 23:33:30 +0200 Subject: [PATCH] feat: extract optimism genesis info --- crates/rpc-types/Cargo.toml | 2 + crates/rpc-types/src/genesis.rs | 221 ++++++++++++++++++++++++++++++++ 2 files changed, 223 insertions(+) diff --git a/crates/rpc-types/Cargo.toml b/crates/rpc-types/Cargo.toml index 99af5bb89..7bdcc5006 100644 --- a/crates/rpc-types/Cargo.toml +++ b/crates/rpc-types/Cargo.toml @@ -17,8 +17,10 @@ op-alloy-consensus = { workspace = true, features = ["serde"] } alloy-primitives = { workspace = true, features = ["rlp", "serde", "std"] } alloy-rpc-types-eth.workspace = true alloy-network.workspace = true +alloy-serde.workspace = true serde = { workspace = true, features = ["derive"] } +serde_json = { workspace = true } # arbitrary arbitrary = { workspace = true, features = ["derive"], optional = true } diff --git a/crates/rpc-types/src/genesis.rs b/crates/rpc-types/src/genesis.rs index b35b08f8a..6e427c2b6 100644 --- a/crates/rpc-types/src/genesis.rs +++ b/crates/rpc-types/src/genesis.rs @@ -1,5 +1,42 @@ //! OP types for genesis data. +use alloy_serde::OtherFields; +use serde::de::Error; + +/// Info for Optimism chain. +#[derive(Default, Debug, Clone, Copy, Eq, PartialEq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct OptimismChainInfo { + /// Genesis info + pub genesis_info: Option, + /// Base fee info + pub base_fee_info: Option, +} + +impl OptimismChainInfo { + /// Extract the Optimism chain info from `OtherFields` object. + pub fn extract_from(others: &OtherFields) -> Option { + let genesis_info = OptimismGenesisInfo::extract_from(others); + let base_fee_info = OptimismBaseFeeInfo::extract_from(others); + + Some(OptimismChainInfo { genesis_info, base_fee_info }) + } +} + +impl TryFrom for OptimismChainInfo { + type Error = serde_json::Error; + + fn try_from(others: OtherFields) -> Result { + let genesis_info = OptimismGenesisInfo::try_from(others.clone())?; + let base_fee_info = OptimismBaseFeeInfo::try_from(others)?; + + Ok(OptimismChainInfo { + genesis_info: Some(genesis_info), + base_fee_info: Some(base_fee_info), + }) + } +} + /// Genesis info for Optimism. #[derive(Default, Debug, Clone, Copy, Eq, PartialEq, serde::Serialize, serde::Deserialize)] #[serde(rename_all = "camelCase")] @@ -16,6 +53,21 @@ pub struct OptimismGenesisInfo { pub fjord_time: Option, } +impl OptimismGenesisInfo { + /// Extract the Optimism genesis info from `OtherFields` object. + pub fn extract_from(others: &OtherFields) -> Option { + others.deserialize_as().ok() + } +} + +impl TryFrom for OptimismGenesisInfo { + type Error = serde_json::Error; + + fn try_from(others: OtherFields) -> Result { + others.deserialize_as() + } +} + /// Additional base fee info for Optimism. #[derive(Default, Debug, Clone, Copy, Eq, PartialEq, serde::Serialize, serde::Deserialize)] #[serde(rename_all = "camelCase")] @@ -27,3 +79,172 @@ pub struct OptimismBaseFeeInfo { /// EIP-1559 denominator after canyon pub eip1559_denominator_canyon: Option, } + +impl OptimismBaseFeeInfo { + /// Extract the Optimism base fee info from `OtherFields` object. + pub fn extract_from(others: &OtherFields) -> Option { + if let Some(Ok(optimism_base_fee_info)) = + others.get_deserialized::("optimism") + { + return Some(optimism_base_fee_info); + } + None + } +} + +impl TryFrom for OptimismBaseFeeInfo { + type Error = serde_json::Error; + + fn try_from(others: OtherFields) -> Result { + if let Some(Ok(optimism_base_fee_info)) = + others.get_deserialized::("optimism") + { + Ok(optimism_base_fee_info) + } else { + Err(serde_json::Error::missing_field("optimism")) + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_extract_optimism_genesis_info() { + let genesis_info = r#" + { + "bedrockBlock": 10, + "regolithTime": 12, + "canyonTime": 0, + "ecotoneTime": 0 + } + "#; + + let others: OtherFields = serde_json::from_str(genesis_info).unwrap(); + let genesis_info = OptimismGenesisInfo::extract_from(&others).unwrap(); + + assert_eq!( + genesis_info, + OptimismGenesisInfo { + bedrock_block: Some(10), + regolith_time: Some(12), + canyon_time: Some(0), + ecotone_time: Some(0), + fjord_time: None, + } + ); + } + + #[test] + fn test_extract_optimism_base_fee_info() { + let base_fee_info = r#" + { + "optimism": { + "eip1559Elasticity": 0, + "eip1559Denominator": 8, + "eip1559DenominatorCanyon": 8 + } + } + "#; + + let others: OtherFields = serde_json::from_str(base_fee_info).unwrap(); + let base_fee_info = OptimismBaseFeeInfo::extract_from(&others).unwrap(); + + assert_eq!( + base_fee_info, + OptimismBaseFeeInfo { + eip1559_elasticity: Some(0), + eip1559_denominator: Some(8), + eip1559_denominator_canyon: Some(8), + } + ); + } + + #[test] + fn test_extract_optimism_chain_info() { + let chain_info = r#" + { + "bedrockBlock": 10, + "regolithTime": 12, + "canyonTime": 0, + "ecotoneTime": 0, + "optimism": { + "eip1559Denominator": 8, + "eip1559DenominatorCanyon": 8 + } + } + "#; + + let others: OtherFields = serde_json::from_str(chain_info).unwrap(); + let chain_info = OptimismChainInfo::extract_from(&others).unwrap(); + + assert_eq!( + chain_info, + OptimismChainInfo { + genesis_info: Some(OptimismGenesisInfo { + bedrock_block: Some(10), + regolith_time: Some(12), + canyon_time: Some(0), + ecotone_time: Some(0), + fjord_time: None, + }), + base_fee_info: Some(OptimismBaseFeeInfo { + eip1559_elasticity: None, + eip1559_denominator: Some(8), + eip1559_denominator_canyon: Some(8), + }), + } + ); + + let chain_info = OptimismChainInfo::try_from(others).unwrap(); + + assert_eq!( + chain_info, + OptimismChainInfo { + genesis_info: Some(OptimismGenesisInfo { + bedrock_block: Some(10), + regolith_time: Some(12), + canyon_time: Some(0), + ecotone_time: Some(0), + fjord_time: None, + }), + base_fee_info: Some(OptimismBaseFeeInfo { + eip1559_elasticity: None, + eip1559_denominator: Some(8), + eip1559_denominator_canyon: Some(8), + }), + } + ); + } + + #[test] + fn test_extract_optimism_chain_info_no_base_fee() { + let chain_info = r#" + { + "bedrockBlock": 10, + "regolithTime": 12, + "canyonTime": 0, + "ecotoneTime": 0, + "fjordTime": 0 + } + "#; + + let others: OtherFields = serde_json::from_str(chain_info).unwrap(); + let chain_info = OptimismChainInfo::extract_from(&others).unwrap(); + + assert_eq!( + chain_info, + OptimismChainInfo { + genesis_info: Some(OptimismGenesisInfo { + bedrock_block: Some(10), + regolith_time: Some(12), + canyon_time: Some(0), + ecotone_time: Some(0), + fjord_time: Some(0), + }), + base_fee_info: None, + } + ); + } +}