use std::fmt::Debug;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use crate::{
abi::to_abi,
eip::eip2718::AccessList,
errors::{Error, Result},
primitives::{Address, Bytes, Hex, H256, U256},
prelude::{keccak256, HexError},
};
#[derive(Debug, Serialize, Deserialize)]
#[serde(untagged)]
pub enum TransactionOrHash {
Null,
Hash(H256),
Transaction(Transaction),
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum TransactionType {
#[serde(rename = "0x00")]
Legacy,
#[serde(rename = "0x01")]
Eip2930,
#[serde(rename = "0x02")]
Eip1559,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Transaction {
#[serde(skip_serializing_if = "Option::is_none")]
pub r#type: Option<TransactionType>,
#[serde(skip_serializing_if = "Option::is_none")]
pub nonce: Option<U256>,
pub to: Address,
#[serde(skip_serializing_if = "Option::is_none")]
pub gas: Option<U256>,
#[serde(rename = "transactionIndex")]
#[serde(skip_serializing_if = "Option::is_none")]
transaction_index: Option<U256>,
#[serde(rename = "blockHash")]
#[serde(skip_serializing_if = "Option::is_none")]
pub block_hash: Option<H256>,
#[serde(rename = "blockNumber")]
#[serde(skip_serializing_if = "Option::is_none")]
pub block_number: Option<U256>,
#[serde(rename = "gasPrice")]
#[serde(skip_serializing_if = "Option::is_none")]
pub gas_price: Option<U256>,
#[serde(skip_serializing_if = "Option::is_none")]
pub hash: Option<H256>,
#[serde(skip_serializing_if = "Option::is_none")]
pub value: Option<U256>,
pub input: Hex<Vec<u8>>,
#[serde(rename = "maxPriorityFeePerGas")]
#[serde(skip_serializing_if = "Option::is_none")]
pub max_priority_fee_per_gas: Option<U256>,
#[serde(rename = "maxFeePerGas")]
#[serde(skip_serializing_if = "Option::is_none")]
pub max_fee_per_gas: Option<U256>,
#[serde(skip_serializing_if = "Option::is_none")]
pub access_list: Option<AccessList>,
#[serde(rename = "chainId")]
#[serde(skip_serializing_if = "Option::is_none")]
pub chain_id: Option<U256>,
#[serde(skip_serializing_if = "Option::is_none")]
pub v: Option<U256>,
#[serde(skip_serializing_if = "Option::is_none")]
pub r: Option<U256>,
#[serde(skip_serializing_if = "Option::is_none")]
pub s: Option<U256>,
}
#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Block {
pub hash: Option<H256>,
#[serde(rename = "parentHash")]
pub parent_hash: H256,
#[serde(rename = "sha3Uncles")]
pub sha3_uncles: Option<H256>,
pub miner: Address,
#[serde(rename = "stateRoot")]
pub state_root: H256,
#[serde(rename = "transactionsRoot")]
pub transactions_root: H256,
#[serde(rename = "receiptsRoot")]
pub receipts_root: H256,
#[serde(rename = "logsBloom")]
#[serde(skip_serializing_if = "Option::is_none")]
pub logs_bloom: Option<Hex<Vec<u8>>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub difficulty: Option<Hex<Vec<u8>>>,
pub number: Option<U256>,
#[serde(rename = "gasLimit")]
pub gas_limit: U256,
#[serde(rename = "gasUsed")]
pub gas_used: U256,
pub timestamp: U256,
#[serde(rename = "extraData")]
pub extra_data: Hex<Vec<u8>>,
#[serde(rename = "mixHash")]
pub mix_hash: Option<H256>,
pub nonce: Option<U256>,
#[serde(rename = "totalDeffficult")]
#[serde(skip_serializing_if = "Option::is_none")]
pub total_deffficult: Option<Hex<Vec<u8>>>,
#[serde(rename = "baseFeePerGas")]
#[serde(skip_serializing_if = "Option::is_none")]
pub base_fee_per_gas: Option<U256>,
pub size: U256,
pub transactions: Vec<TransactionOrHash>,
pub uncles: Vec<H256>,
}
#[derive(Serialize, Deserialize, PartialEq, Debug)]
#[serde(untagged)]
pub enum BlockNumberOrTag {
U256(U256),
Tag(BlockTag),
}
impl From<U256> for BlockNumberOrTag {
fn from(v: U256) -> Self {
BlockNumberOrTag::U256(v)
}
}
impl TryFrom<&str> for BlockNumberOrTag {
type Error = Error;
fn try_from(v: &str) -> std::result::Result<Self, Self::Error> {
if v.starts_with("0x") {
Ok(BlockNumberOrTag::U256(
U256::from_str_radix(&v[2..], 16).map_err(|err| Error::Other(err.to_string()))?,
))
} else {
Ok(BlockNumberOrTag::U256(
U256::from_str_radix(v, 10).map_err(|err| Error::Other(err.to_string()))?,
))
}
}
}
impl TryFrom<String> for BlockNumberOrTag {
type Error = Error;
fn try_from(value: String) -> std::result::Result<Self, Self::Error> {
value.as_str().try_into()
}
}
impl TryFrom<BlockTag> for BlockNumberOrTag {
type Error = Error;
fn try_from(value: BlockTag) -> std::result::Result<Self, Self::Error> {
Ok(BlockNumberOrTag::Tag(value))
}
}
impl Default for BlockNumberOrTag {
fn default() -> Self {
BlockNumberOrTag::Tag(BlockTag::Latest)
}
}
#[derive(Serialize, Deserialize, PartialEq, Debug)]
#[serde(rename_all = "lowercase")]
pub enum BlockTag {
Earliest,
Finalized,
Safe,
Latest,
Pending,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct TopicFilter(
pub Topic,
#[serde(skip_serializing_if = "Option::is_none")] pub Option<Topic>,
#[serde(skip_serializing_if = "Option::is_none")] pub Option<Topic>,
#[serde(skip_serializing_if = "Option::is_none")] pub Option<Topic>,
);
impl From<Topic> for TopicFilter {
fn from(value: Topic) -> Self {
TopicFilter(value, None, None, None)
}
}
impl From<(Topic, Topic)> for TopicFilter {
fn from(value: (Topic, Topic)) -> Self {
TopicFilter(value.0, Some(value.1), None, None)
}
}
impl From<(Topic, Topic, Topic)> for TopicFilter {
fn from(value: (Topic, Topic, Topic)) -> Self {
TopicFilter(value.0, Some(value.1), Some(value.2), None)
}
}
impl From<(Topic, Topic, Topic, Topic)> for TopicFilter {
fn from(value: (Topic, Topic, Topic, Topic)) -> Self {
TopicFilter(value.0, Some(value.1), Some(value.2), Some(value.3))
}
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
#[serde(untagged)]
pub enum Topic {
OneOf(Vec<H256>),
This(H256),
}
impl<const N: usize> From<[H256; N]> for Topic {
fn from(value: [H256; N]) -> Self {
Self::OneOf(value.to_vec())
}
}
impl Topic {
pub fn signature(value: &str) -> Self {
Self::This(keccak256(value))
}
pub fn from_simple_value<T>(value: T) -> Self
where
T: Serialize,
{
Self::This(Self::from_simple_value_priv(value))
}
pub fn from_simple_values<T>(value: &[T]) -> Self
where
T: Serialize,
{
Self::OneOf(
value
.iter()
.map(Self::from_simple_value_priv)
.collect::<Vec<_>>(),
)
}
fn from_simple_value_priv<T>(value: T) -> H256
where
T: Serialize,
{
let abi = to_abi(value).expect("Encode simple value");
let mut buf = [0u8; 32];
buf.copy_from_slice(abi.as_ref());
H256::from(buf)
}
}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Hash)]
#[serde(untagged)]
pub enum AddressFilter {
Address(Address),
Addresses(Vec<Address>),
}
impl TryFrom<&str> for AddressFilter {
type Error = HexError;
fn try_from(value: &str) -> std::result::Result<Self, Self::Error> {
let address: Address = value.parse()?;
Ok(Self::Address(address))
}
}
impl<const N: usize> TryFrom<[&str; N]> for AddressFilter {
type Error = HexError;
fn try_from(value: [&str; N]) -> std::result::Result<Self, Self::Error> {
let mut addresses = vec![];
for address in value {
addresses.push(address.parse()?);
}
Ok(Self::Addresses(addresses))
}
}
impl TryFrom<String> for AddressFilter {
type Error = HexError;
fn try_from(value: String) -> std::result::Result<Self, Self::Error> {
let address: Address = value.parse()?;
Ok(Self::Address(address))
}
}
impl<const N: usize> TryFrom<[String; N]> for AddressFilter {
type Error = HexError;
fn try_from(value: [String; N]) -> std::result::Result<Self, Self::Error> {
let mut addresses = vec![];
for address in value {
addresses.push(address.parse()?);
}
Ok(Self::Addresses(addresses))
}
}
impl TryFrom<&[&str]> for AddressFilter {
type Error = HexError;
fn try_from(value: &[&str]) -> std::result::Result<Self, Self::Error> {
let mut addresses = vec![];
for address in value {
addresses.push(address.parse()?);
}
Ok(Self::Addresses(addresses))
}
}
impl TryFrom<&[String]> for AddressFilter {
type Error = HexError;
fn try_from(value: &[String]) -> std::result::Result<Self, Self::Error> {
let mut addresses = vec![];
for address in value {
addresses.push(address.parse()?);
}
Ok(Self::Addresses(addresses))
}
}
#[derive(Default, Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Hash)]
#[serde(rename_all = "camelCase")]
pub struct Filter {
pub from_block: Option<U256>,
pub to_block: Option<U256>,
pub address: Option<AddressFilter>,
pub topics: Option<TopicFilter>,
}
impl Filter {
pub fn new() -> FilterBuilder {
FilterBuilder::default()
}
}
#[derive(Debug)]
pub struct FilterBuilder {
filter: Result<Filter>,
}
impl Default for FilterBuilder {
fn default() -> Self {
Self {
filter: Ok(Filter::default()),
}
}
}
impl FilterBuilder {
fn and_then<F>(self, func: F) -> Self
where
F: FnOnce(Filter) -> Result<Filter>,
{
Self {
filter: self.filter.and_then(func),
}
}
pub fn with_from_block<N>(self, block_num: N) -> Self
where
N: TryInto<U256>,
N::Error: Debug,
{
self.and_then(|mut value| {
value.from_block = Some(
block_num
.try_into()
.map_err(|err| Error::FilterBuilder(format!("{:?}", err)))?,
);
Ok(value)
})
}
pub fn with_to_block<N>(self, block_num: N) -> Self
where
N: TryInto<U256>,
N::Error: Debug,
{
self.and_then(|mut value| {
value.to_block = Some(
block_num
.try_into()
.map_err(|err| Error::FilterBuilder(format!("{:?}", err)))?,
);
Ok(value)
})
}
pub fn with_block<N>(self, block_num: N) -> Self
where
N: TryInto<U256>,
N::Error: Debug,
{
self.and_then(|mut value| {
let block_num = block_num
.try_into()
.map_err(|err| Error::FilterBuilder(format!("{:?}", err)))?;
value.from_block = Some(block_num);
value.to_block = Some(block_num);
Ok(value)
})
}
pub fn with_address<A>(self, filter: A) -> Self
where
A: TryInto<AddressFilter>,
A::Error: Debug,
{
self.and_then(|mut value| {
let filter = filter
.try_into()
.map_err(|err| Error::FilterBuilder(format!("{:?}", err)))?;
value.address = Some(filter);
Ok(value)
})
}
pub fn with_topics<T>(self, filter: T) -> Self
where
T: TryInto<TopicFilter>,
T::Error: Debug,
{
self.and_then(|mut value| {
let filter = filter
.try_into()
.map_err(|err| Error::FilterBuilder(format!("{:?}", err)))?;
value.topics = Some(filter);
Ok(value)
})
}
pub fn create(self) -> Result<Filter> {
self.filter
}
}
#[derive(Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct FeeHistory {
pub oldest_block: U256,
pub base_fee_per_gas: Vec<U256>,
pub reward: Vec<Vec<U256>>,
}
#[derive(Serialize, Deserialize, Debug)]
#[serde(rename_all = "camelCase")]
pub struct Log {
pub removed: bool,
pub log_index: U256,
pub transaction_index: U256,
pub transaction_hash: U256,
pub block_hash: H256,
pub block_number: U256,
pub address: Address,
pub data: Bytes,
pub topics: Vec<H256>,
}
#[derive(Serialize, Deserialize, Debug)]
#[serde(untagged)]
pub enum FilterEvents {
BlocksOrTransactions(Vec<H256>),
Logs(Vec<Log>),
}
#[derive(Debug, Serialize, Deserialize, PartialEq)]
#[serde(untagged)]
pub enum SyncingStatus {
Syncing(Syncing),
#[serde(deserialize_with = "from_bool", serialize_with = "as_bool")]
False,
}
impl Default for SyncingStatus {
fn default() -> Self {
SyncingStatus::False
}
}
fn from_bool<'de, D>(d: D) -> std::result::Result<(), D::Error>
where
D: Deserializer<'de>,
{
bool::deserialize(d).and_then(|flag| {
if !flag {
Ok(())
} else {
Err("Parse syncing status err, should always return false if not syncing")
.map_err(serde::de::Error::custom)
}
})
}
fn as_bool<S>(serializer: S) -> std::result::Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_bool(false)
}
#[derive(Debug, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct Syncing {
starting_block: U256,
current_block: U256,
highest_block: U256,
}
#[derive(Serialize, Deserialize, Debug)]
#[serde(rename_all = "camelCase")]
pub struct TransactionReceipt {
pub from: Address,
pub to: Option<Address>,
pub contract_address: Option<Address>,
pub gas_used: U256,
pub cumulative_gas_used: U256,
pub effective_gas_price: U256,
transaction_index: U256,
pub block_hash: H256,
pub block_number: U256,
pub status: Option<Status>,
pub logs: Vec<Log>,
pub logs_bloom: Bytes,
pub root: Option<H256>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum Status {
#[serde(rename = "0x1")]
Success,
#[serde(rename = "0x0")]
Failure,
}