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
use alloy_primitives::Address;
use clickhouse::Row;
use redefined::Redefined;
use reth_rpc_types::beacon::BlsPublicKey;
use rkyv::{Archive, Deserialize as rDeserialize, Serialize as rSerialize};
use serde::{Deserialize, Serialize};
use serde_with::serde_as;

use crate::{
    db::{
        redefined_types::primitives::{AddressRedefined, BlsPublicKeyRedefined},
        searcher::Fund,
    },
    implement_table_value_codecs_with_zc,
    serde_utils::{addresss, option_addresss, option_fund, vec_address, vec_bls_pub_key},
    FastHashSet,
};

#[derive(Debug, Default, Row, PartialEq, Clone, Eq, Serialize, Deserialize, Redefined)]
#[redefined_attr(derive(Debug, PartialEq, Clone, Serialize, rSerialize, rDeserialize, Archive))]
pub struct BuilderInfo {
    pub name: Option<String>,
    #[redefined(same_fields)]
    #[serde(deserialize_with = "option_fund::deserialize")]
    #[serde(default)]
    pub fund: Option<Fund>,
    #[serde(with = "vec_bls_pub_key")]
    #[serde(default)]
    pub pub_keys: Vec<BlsPublicKey>,
    #[serde(with = "vec_address")]
    #[serde(default)]
    pub searchers_eoas: Vec<Address>,
    #[serde(with = "vec_address")]
    #[serde(default)]
    pub searchers_contracts: Vec<Address>,
    #[serde(with = "option_addresss")]
    #[serde(default)]
    pub ultrasound_relay_collateral_address: Option<Address>,
}

impl BuilderInfo {
    pub fn merge(&mut self, other: BuilderInfo) {
        self.name = other.name.or(self.name.take());
        self.fund = other.fund.or(self.fund.take());

        self.pub_keys = self
            .pub_keys
            .iter()
            .chain(other.pub_keys.iter())
            .cloned()
            .collect::<FastHashSet<_>>()
            .into_iter()
            .collect();

        self.searchers_eoas = self
            .searchers_eoas
            .iter()
            .chain(other.searchers_eoas.iter())
            .cloned()
            .collect::<FastHashSet<_>>()
            .into_iter()
            .collect();

        self.searchers_contracts = self
            .searchers_contracts
            .iter()
            .chain(other.searchers_contracts.iter())
            .cloned()
            .collect::<FastHashSet<_>>()
            .into_iter()
            .collect();

        self.ultrasound_relay_collateral_address = other
            .ultrasound_relay_collateral_address
            .or(self.ultrasound_relay_collateral_address.take());
    }

    pub fn describe(&self) -> String {
        let mut description = String::new();

        if let Some(name) = &self.name {
            description.push_str(name);
        } else {
            // If no name is provided, use a placeholder or generic term
            description.push_str("Unknown Block Builder");
        }

        description
    }
}

implement_table_value_codecs_with_zc!(BuilderInfoRedefined);

#[serde_as]
#[derive(Debug, Default, Row, PartialEq, Clone, Serialize, Deserialize)]
pub struct BuilderInfoWithAddress {
    #[serde(with = "addresss")]
    pub address: Address,
    pub name: Option<String>,
    #[serde(deserialize_with = "option_fund::deserialize")]
    pub fund: Option<Fund>,
    #[serde(with = "vec_bls_pub_key")]
    pub pub_keys: Vec<BlsPublicKey>,
    #[serde(with = "vec_address")]
    pub searchers_eoas: Vec<Address>,
    #[serde(with = "vec_address")]
    pub searchers_contracts: Vec<Address>,
    #[serde(with = "option_addresss")]
    pub ultrasound_relay_collateral_address: Option<Address>,
}

impl BuilderInfoWithAddress {
    pub fn new_with_address(address: Address, info: BuilderInfo) -> Self {
        Self {
            address,
            name: info.name,
            fund: info.fund,
            pub_keys: info.pub_keys,
            searchers_eoas: info.searchers_eoas,
            searchers_contracts: info.searchers_contracts,
            ultrasound_relay_collateral_address: info.ultrasound_relay_collateral_address,
        }
    }
}