1use std::{
2 fmt::{Debug, Display},
3 str::FromStr,
4};
5
6use serde::{Deserialize, Serialize};
7
8use crate::core::{Address, Asset, NetworkFamily};
9
10#[derive(Debug, Clone, Copy)]
11pub struct EvmNetwork {
12 pub name: &'static str,
13 pub chain_id: u64,
14 pub network_id: &'static str,
15}
16
17impl NetworkFamily for EvmNetwork {
18 fn network_name(&self) -> &str {
19 self.name
20 }
21 fn network_id(&self) -> &str {
22 self.network_id
23 }
24}
25
26#[derive(Clone, Copy, PartialEq, Eq, Hash)]
27pub struct EvmAddress(pub alloy_primitives::Address);
28
29impl From<alloy_primitives::Address> for EvmAddress {
30 fn from(addr: alloy_primitives::Address) -> Self {
31 EvmAddress(addr)
32 }
33}
34
35impl FromStr for EvmAddress {
36 type Err = alloy_primitives::AddressError;
37
38 fn from_str(s: &str) -> Result<Self, Self::Err> {
39 let addr = alloy_primitives::Address::from_str(s)?;
40 Ok(EvmAddress(addr))
41 }
42}
43
44impl Display for EvmAddress {
45 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
46 write!(f, "{}", self.0)
47 }
48}
49
50impl Debug for EvmAddress {
51 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
52 write!(f, "EvmAddress({})", self.0)
53 }
54}
55
56impl Serialize for EvmAddress {
57 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
58 where
59 S: serde::Serializer,
60 {
61 serializer.serialize_str(&self.to_string())
62 }
63}
64
65impl<'de> Deserialize<'de> for EvmAddress {
66 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
67 where
68 D: serde::Deserializer<'de>,
69 {
70 let s = String::deserialize(deserializer)?;
71 EvmAddress::from_str(&s).map_err(serde::de::Error::custom)
72 }
73}
74
75impl Address for EvmAddress {
76 type Network = EvmNetwork;
77}
78
79#[derive(Clone, Copy, PartialEq, Eq, Hash)]
80pub struct EvmSignature(pub alloy_primitives::Signature);
81
82impl Display for EvmSignature {
83 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
84 write!(f, "{}", self.0)
85 }
86}
87
88impl Debug for EvmSignature {
89 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
90 write!(f, "EvmSignature({})", self.0)
91 }
92}
93
94impl FromStr for EvmSignature {
95 type Err = alloy_primitives::SignatureError;
96
97 fn from_str(s: &str) -> Result<Self, Self::Err> {
98 let sig = alloy_primitives::Signature::from_str(s)?;
99 Ok(EvmSignature(sig))
100 }
101}
102
103impl Serialize for EvmSignature {
104 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
105 where
106 S: serde::Serializer,
107 {
108 serializer.serialize_str(&self.to_string())
109 }
110}
111
112impl<'de> Deserialize<'de> for EvmSignature {
113 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
114 where
115 D: serde::Deserializer<'de>,
116 {
117 let s = String::deserialize(deserializer)?;
118 EvmSignature::from_str(&s).map_err(serde::de::Error::custom)
119 }
120}
121
122impl From<alloy_primitives::Signature> for EvmSignature {
123 fn from(sig: alloy_primitives::Signature) -> Self {
124 EvmSignature(sig)
125 }
126}
127
128pub type EvmAsset = Asset<EvmAddress>;
129
130pub trait ExplicitEvmNetwork {
131 const NETWORK: EvmNetwork;
132}
133
134#[derive(Debug, Clone, Copy, Serialize)]
135pub struct Eip712Domain {
136 pub name: &'static str,
137 pub version: &'static str,
138}
139
140pub trait ExplicitEvmAsset {
141 type Network: ExplicitEvmNetwork;
142
143 const ASSET: EvmAsset;
144 const EIP712_DOMAIN: Option<Eip712Domain>;
145}
146
147impl<T> From<T> for EvmNetwork
148where
149 T: ExplicitEvmNetwork,
150{
151 fn from(_: T) -> Self {
152 T::NETWORK
153 }
154}
155
156impl<T> From<T> for EvmAsset
157where
158 T: ExplicitEvmAsset,
159{
160 fn from(_: T) -> Self {
161 T::ASSET
162 }
163}
164
165pub mod networks {
166 use super::*;
167
168 macro_rules! define_explicit_evm_network {
169 ($struct_name:ident, $network_const:expr) => {
170 pub struct $struct_name;
171
172 impl ExplicitEvmNetwork for $struct_name {
173 const NETWORK: EvmNetwork = $network_const;
174 }
175 };
176 }
177
178 define_explicit_evm_network!(
179 Ethereum,
180 EvmNetwork {
181 name: "ethereum",
182 chain_id: 1,
183 network_id: "eip155:1",
184 }
185 );
186 define_explicit_evm_network!(
187 EthereumSepolia,
188 EvmNetwork {
189 name: "ethereum-sepolia",
190 chain_id: 11155111,
191 network_id: "eip155:11155111",
192 }
193 );
194 define_explicit_evm_network!(
195 Base,
196 EvmNetwork {
197 name: "base",
198 chain_id: 8453,
199 network_id: "eip155:8453",
200 }
201 );
202 define_explicit_evm_network!(
203 BaseSepolia,
204 EvmNetwork {
205 name: "base-sepolia",
206 chain_id: 84532,
207 network_id: "eip155:84532",
208 }
209 );
210}
211
212pub mod assets {
213 use alloy_primitives::address;
214
215 use super::*;
216
217 macro_rules! define_explicit_evm_asset {
218 (
219 $struct_name:ident,
220 $network_struct:ty,
221 $addr:expr,
222 $decimals:expr,
223 $name:expr,
224 $symbol:expr,
225 $eip712_domain:expr
226 ) => {
227 pub struct $struct_name;
228
229 impl ExplicitEvmAsset for $struct_name {
230 type Network = $network_struct;
231
232 const ASSET: EvmAsset = EvmAsset {
233 address: EvmAddress(address!($addr)),
234 decimals: $decimals,
235 name: $name,
236 symbol: $symbol,
237 };
238
239 const EIP712_DOMAIN: Option<Eip712Domain> = $eip712_domain;
240 }
241 };
242 }
243
244 macro_rules! define_explicit_usdc {
245 ($struct_name:ident, $network_struct:ty, $addr:expr) => {
246 define_explicit_evm_asset!(
247 $struct_name,
248 $network_struct,
249 $addr,
250 6,
251 "USDC",
252 "USDC",
253 Some(Eip712Domain {
254 name: "USDC",
255 version: "2",
256 })
257 );
258 };
259 }
260
261 define_explicit_usdc!(
262 UsdcEthereum,
263 networks::Ethereum,
264 "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"
265 );
266
267 define_explicit_usdc!(
268 UsdcEthereumSepolia,
269 networks::EthereumSepolia,
270 "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238"
271 );
272
273 define_explicit_usdc!(
274 UsdcBase,
275 networks::Base,
276 "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"
277 );
278
279 define_explicit_usdc!(
280 UsdcBaseSepolia,
281 networks::BaseSepolia,
282 "0x036CbD53842c5426634e7929541eC2318f3dCF7e"
283 );
284}