1use std::collections::HashMap;
2use std::hash::{Hash, Hasher};
3
4use crate::diesel::schema::chaindexing_events;
5use diesel::{Insertable, Queryable};
6use ethers::abi::{LogParam, Token};
7use ethers::types::{Address, Log, I256, U256, U64};
8use ethers::utils::format_ether;
9
10use crate::{ChainId, ContractEvent};
11use uuid::Uuid;
12
13use serde::Deserialize;
14
15#[derive(Debug, Deserialize, Clone, Eq, Queryable, Insertable)]
18#[diesel(table_name = chaindexing_events)]
19pub struct Event {
20 pub id: Uuid,
21 pub(crate) chain_id: i64,
22 pub contract_address: String,
23 pub contract_name: String,
24 pub abi: String,
25 parameters: serde_json::Value,
26 topics: serde_json::Value,
27 pub block_hash: String,
28 pub(crate) block_number: i64,
29 block_timestamp: i64,
30 pub transaction_hash: String,
31 pub(crate) transaction_index: i32,
32 pub(crate) log_index: i32,
33 removed: bool,
34}
35
36#[derive(Debug, Deserialize, Clone, Eq, PartialEq)]
38pub struct PartialEvent {
39 pub id: Uuid,
40 pub chain_id: i64,
41 pub contract_address: String,
42 pub contract_name: String,
43 pub block_hash: String,
44 pub block_number: i64,
45 pub block_timestamp: i64,
46 pub transaction_hash: String,
47 pub transaction_index: i64,
48 pub log_index: i64,
49}
50
51impl PartialEq for Event {
52 fn eq(&self, other: &Self) -> bool {
53 self.chain_id == other.chain_id
54 && self.contract_address == other.contract_address
55 && self.abi == other.abi
56 && self.block_hash == other.block_hash
57 }
58}
59
60impl Hash for Event {
61 fn hash<H: Hasher>(&self, state: &mut H) {
62 self.chain_id.hash(state);
63 self.contract_address.hash(state);
64 self.abi.hash(state);
65 self.block_hash.hash(state);
66 }
67}
68
69impl Event {
70 pub fn new(
71 log: &Log,
72 event: &ContractEvent,
73 chain_id: &ChainId,
74 contract_name: &str,
75 block_timestamp: i64,
76 ) -> Self {
77 let log_params = event.value.parse_log(log.clone().into()).unwrap().params;
78 let parameters = Self::log_params_to_parameters(&log_params);
79
80 Self {
81 id: uuid::Uuid::new_v4(),
82 chain_id: *chain_id as i64,
83 contract_address: utils::address_to_string(&log.address).to_lowercase(),
84 contract_name: contract_name.to_owned(),
85 abi: event.abi.clone(),
86 parameters: serde_json::to_value(parameters).unwrap(),
87 topics: serde_json::to_value(&log.topics).unwrap(),
88 block_hash: hashes::h256_to_string(&log.block_hash.unwrap()).to_lowercase(),
89 block_number: log.block_number.unwrap().as_u64() as i64,
90 block_timestamp,
91 transaction_hash: hashes::h256_to_string(&log.transaction_hash.unwrap()).to_lowercase(),
92 transaction_index: log.transaction_index.unwrap().as_u32() as i32,
93 log_index: log.log_index.unwrap().as_u32() as i32,
94 removed: log.removed.unwrap(),
95 }
96 }
97
98 pub(crate) fn get_abi(&self) -> &str {
99 self.abi.as_str()
100 }
101
102 pub fn get_block_number(&self) -> u64 {
104 self.block_number as u64
105 }
106 pub fn get_block_timestamp(&self) -> u64 {
108 self.block_timestamp as u64
109 }
110 pub fn get_transaction_index(&self) -> u32 {
112 self.transaction_index as u32
113 }
114 pub fn get_log_index(&self) -> u32 {
116 self.log_index as u32
117 }
118
119 pub fn get_params(&self) -> EventParam {
121 EventParam::new(&self.parameters)
122 }
123
124 pub fn get_chain_id(&self) -> ChainId {
126 U64::from(self.chain_id).try_into().unwrap()
127 }
128
129 fn log_params_to_parameters(log_params: &[LogParam]) -> HashMap<String, Token> {
130 log_params.iter().fold(HashMap::new(), |mut parameters, log_param| {
131 parameters.insert(log_param.name.to_string(), log_param.value.clone());
132
133 parameters
134 })
135 }
136}
137
138pub struct EventParam {
142 value: HashMap<String, Token>,
143}
144
145impl EventParam {
146 pub(crate) fn new(parameters: &serde_json::Value) -> EventParam {
147 EventParam {
148 value: serde_json::from_value(parameters.clone()).unwrap(),
149 }
150 }
151
152 pub fn get_string_unsafely(&self, key: &str) -> String {
157 self.value.get(key).unwrap().to_string()
158 }
159
160 pub fn get_bytes(&self, key: &str) -> Vec<u8> {
162 let token = self.get_token(key);
163
164 token.clone().into_fixed_bytes().or(token.into_bytes()).unwrap()
165 }
166
167 pub fn get_i8_array(&self, key: &str) -> Vec<i8> {
168 self.get_array_and_transform(key, |token| token_to_int(token).as_i8())
169 }
170 pub fn get_i32_array(&self, key: &str) -> Vec<i32> {
171 self.get_array_and_transform(key, |token| token_to_int(token).as_i32())
172 }
173 pub fn get_i64_array(&self, key: &str) -> Vec<i64> {
174 self.get_array_and_transform(key, |token| token_to_int(token).as_i64())
175 }
176 pub fn get_i128_array(&self, key: &str) -> Vec<i128> {
177 self.get_array_and_transform(key, |token| token_to_int(token).as_i128())
178 }
179
180 pub fn get_u8_array(&self, key: &str) -> Vec<u8> {
181 self.get_array_and_transform(key, |token| token_to_uint(token).as_usize() as u8)
182 }
183 pub fn get_u32_array(&self, key: &str) -> Vec<u32> {
184 self.get_array_and_transform(key, |token| token_to_uint(token).as_u32())
185 }
186 pub fn get_u64_array(&self, key: &str) -> Vec<u64> {
187 self.get_array_and_transform(key, |token| token_to_uint(token).as_u64())
188 }
189 pub fn get_u128_array(&self, key: &str) -> Vec<u128> {
190 self.get_array_and_transform(key, |token| token_to_uint(token).as_u128())
191 }
192 pub fn get_uint_array(&self, key: &str) -> Vec<U256> {
193 self.get_array_and_transform(key, token_to_uint)
194 }
195 pub fn get_int_array(&self, key: &str) -> Vec<I256> {
196 self.get_array_and_transform(key, |token| I256::from_raw(token.into_int().unwrap()))
197 }
198
199 pub fn get_address_array(&self, key: &str) -> Vec<Address> {
200 self.get_array_and_transform(key, token_to_address)
201 }
202 pub fn get_address_string_array(&self, key: &str) -> Vec<String> {
203 self.get_array_and_transform(key, |token| token_to_address_string(token).to_lowercase())
204 }
205
206 fn get_array_and_transform<TokenTransformer, Output>(
207 &self,
208 key: &str,
209 token_transformer: TokenTransformer,
210 ) -> Vec<Output>
211 where
212 TokenTransformer: Fn(Token) -> Output,
213 {
214 self.get_array(key).into_iter().map(token_transformer).collect()
215 }
216 fn get_array(&self, key: &str) -> Vec<Token> {
217 let token = self.get_token(key);
218
219 token.clone().into_fixed_array().or(token.into_array()).unwrap()
220 }
221
222 pub fn get_int_gwei(&self, key: &str) -> f64 {
223 self.get_int_ether(key) * GWEI
224 }
225 pub fn get_int_ether(&self, key: &str) -> f64 {
226 format_ether(self.get_int(key)).parse().unwrap()
227 }
228
229 pub fn get_uint_gwei(&self, key: &str) -> f64 {
230 self.get_uint_ether(key) * GWEI
231 }
232 pub fn get_uint_ether(&self, key: &str) -> f64 {
233 format_ether(self.get_uint(key)).parse().unwrap()
234 }
235
236 pub fn get_i8(&self, key: &str) -> i8 {
237 self.get_int(key).as_i8()
238 }
239 pub fn get_i32(&self, key: &str) -> i32 {
240 self.get_int(key).as_i32()
241 }
242 pub fn get_i64(&self, key: &str) -> i64 {
243 self.get_int(key).as_i64()
244 }
245 pub fn get_i128(&self, key: &str) -> i128 {
246 self.get_int(key).as_i128()
247 }
248
249 pub fn get_u8(&self, key: &str) -> u8 {
250 self.get_usize(key) as u8
251 }
252 pub fn get_usize(&self, key: &str) -> usize {
253 self.get_uint(key).as_usize()
254 }
255 pub fn get_u32(&self, key: &str) -> u32 {
256 self.get_uint(key).as_u32()
257 }
258 pub fn get_u64(&self, key: &str) -> u64 {
259 self.get_uint(key).as_u64()
260 }
261 pub fn get_u128(&self, key: &str) -> u128 {
262 self.get_uint(key).as_u128()
263 }
264 pub fn get_uint(&self, key: &str) -> U256 {
266 token_to_uint(self.get_token(key))
267 }
268 pub fn get_int(&self, key: &str) -> I256 {
269 token_to_int(self.get_token(key))
270 }
271 pub fn get_address_string(&self, key: &str) -> String {
272 token_to_address_string(self.get_token(key))
273 }
274 pub fn get_address(&self, key: &str) -> Address {
275 token_to_address(self.get_token(key))
276 }
277
278 fn get_token(&self, key: &str) -> Token {
279 self.value.get(key).unwrap().clone()
280 }
281}
282
283fn token_to_address_string(token: Token) -> String {
284 utils::address_to_string(&token_to_address(token)).to_lowercase()
285}
286
287fn token_to_address(token: Token) -> Address {
288 token.into_address().unwrap()
289}
290
291fn token_to_uint(token: Token) -> U256 {
292 token.into_uint().unwrap()
293}
294fn token_to_int(token: Token) -> I256 {
295 I256::from_raw(token.into_int().unwrap())
296}
297
298const GWEI: f64 = 1_000_000_000.0;
299
300mod hashes {
301 use ethers::types::{H160, H256};
302
303 pub fn h160_to_string(h160: &H160) -> String {
304 serde_json::to_value(h160).unwrap().as_str().unwrap().to_string()
305 }
306
307 pub fn h256_to_string(h256: &H256) -> String {
308 serde_json::to_value(h256).unwrap().as_str().unwrap().to_string()
309 }
310}
311
312mod utils {
313 use ethers::types::H160;
314
315 use super::hashes;
316
317 pub fn address_to_string(address: &H160) -> String {
318 hashes::h160_to_string(address)
319 }
320}
321
322#[cfg(test)]
323mod event_param_tests {
324 use ethers::types::I256;
325 use serde_json::json;
326
327 use super::*;
328
329 #[test]
330 fn returns_uint_values() {
331 let event_param =
332 EventParam::new(&json!({"sqrtPriceX96":{"Uint":"0x1ca2dce57b617d43d62181e8"}}));
333 assert_eq!(
334 event_param.get_uint("sqrtPriceX96"),
335 U256::from_dec_str("8862469411596380921745474024").unwrap()
336 );
337 }
338
339 #[test]
340 fn returns_int_values() {
341 let event_param = EventParam::new(
342 &json!({"amount0":{"Int":"0xfffffffffffffffffffffffffffffffffffffffffffffffe92da20f7358d10e9"}}),
343 );
344 assert_eq!(
345 event_param.get_int("amount0"),
346 I256::from_dec_str("-26311681626831253271").unwrap()
347 );
348 }
349}