1use std::collections::HashMap;
10
11use alloy::primitives::Address;
12use serde_json::{json, Value as JsonValue};
13
14use crate::{
15 models::{MonitorMatch, ScriptLanguage},
16 services::{
17 filter::{
18 evm_helpers::{b256_to_string, h160_to_string},
19 FilterError,
20 },
21 trigger::TriggerExecutionServiceTrait,
22 },
23};
24
25pub async fn handle_match<T: TriggerExecutionServiceTrait>(
53 matching_monitor: MonitorMatch,
54 trigger_service: &T,
55 trigger_scripts: &HashMap<String, (ScriptLanguage, String)>,
56) -> Result<(), FilterError> {
57 match &matching_monitor {
58 MonitorMatch::EVM(evm_monitor_match) => {
59 let transaction = evm_monitor_match.transaction.clone();
60 let sender = transaction.sender().unwrap_or(&Address::ZERO);
62
63 let mut data_json = json!({
65 "monitor": {
66 "name": evm_monitor_match.monitor.name.clone(),
67 },
68 "transaction": {
69 "hash": b256_to_string(*transaction.hash()),
70 "from": h160_to_string(*sender),
71 "value": transaction.value().to_string(),
72 },
73 "functions": [],
74 "events": []
75 });
76
77 if let Some(to) = transaction.to() {
79 data_json["transaction"]["to"] = json!(h160_to_string(*to));
80 }
81
82 let functions = data_json["functions"].as_array_mut().unwrap();
84 for func in evm_monitor_match.matched_on.functions.iter() {
85 let mut function_data = json!({
86 "signature": func.signature.clone(),
87 "args": {}
88 });
89
90 if let Some(args) = &evm_monitor_match.matched_on_args {
92 if let Some(func_args) = &args.functions {
93 for func_arg in func_args {
94 if func_arg.signature == func.signature {
95 if let Some(arg_entries) = &func_arg.args {
96 let args_obj = function_data["args"].as_object_mut().unwrap();
97 for arg in arg_entries {
98 args_obj.insert(arg.name.clone(), json!(arg.value.clone()));
99 }
100 }
101 }
102 }
103 }
104 }
105
106 functions.push(function_data);
107 }
108
109 let events = data_json["events"].as_array_mut().unwrap();
111 for event in evm_monitor_match.matched_on.events.iter() {
112 let mut event_data = json!({
113 "signature": event.signature.clone(),
114 "args": {}
115 });
116
117 if let Some(args) = &evm_monitor_match.matched_on_args {
119 if let Some(event_args) = &args.events {
120 for event_arg in event_args {
121 if event_arg.signature == event.signature {
122 if let Some(arg_entries) = &event_arg.args {
123 let args_obj = event_data["args"].as_object_mut().unwrap();
124 for arg in arg_entries {
125 args_obj.insert(arg.name.clone(), json!(arg.value.clone()));
126 }
127 }
128 }
129 }
130 }
131 }
132
133 events.push(event_data);
134 }
135
136 let _ = trigger_service
139 .execute(
140 &evm_monitor_match
141 .monitor
142 .triggers
143 .iter()
144 .map(|s| s.to_string())
145 .collect::<Vec<_>>(),
146 json_to_hashmap(&data_json),
147 &matching_monitor,
148 trigger_scripts,
149 )
150 .await;
151 }
152 MonitorMatch::Stellar(stellar_monitor_match) => {
153 let transaction = stellar_monitor_match.transaction.clone();
154
155 let mut data_json = json!({
157 "monitor": {
158 "name": stellar_monitor_match.monitor.name.clone(),
159 },
160 "transaction": {
161 "hash": transaction.hash().to_string(),
162 },
163 "functions": [],
164 "events": []
165 });
166
167 let functions = data_json["functions"].as_array_mut().unwrap();
169 for func in stellar_monitor_match.matched_on.functions.iter() {
170 let mut function_data = json!({
171 "signature": func.signature.clone(),
172 "args": {}
173 });
174
175 if let Some(args) = &stellar_monitor_match.matched_on_args {
177 if let Some(func_args) = &args.functions {
178 for func_arg in func_args {
179 if func_arg.signature == func.signature {
180 if let Some(arg_entries) = &func_arg.args {
181 let args_obj = function_data["args"].as_object_mut().unwrap();
182 for arg in arg_entries {
183 args_obj.insert(arg.name.clone(), json!(arg.value.clone()));
184 }
185 }
186 }
187 }
188 }
189 }
190
191 functions.push(function_data);
192 }
193
194 let events = data_json["events"].as_array_mut().unwrap();
196 for event in stellar_monitor_match.matched_on.events.iter() {
197 let mut event_data = json!({
198 "signature": event.signature.clone(),
199 "args": {}
200 });
201
202 if let Some(args) = &stellar_monitor_match.matched_on_args {
204 if let Some(event_args) = &args.events {
205 for event_arg in event_args {
206 if event_arg.signature == event.signature {
207 if let Some(arg_entries) = &event_arg.args {
208 let args_obj = event_data["args"].as_object_mut().unwrap();
209 for arg in arg_entries {
210 args_obj.insert(arg.name.clone(), json!(arg.value.clone()));
211 }
212 }
213 }
214 }
215 }
216 }
217
218 events.push(event_data);
219 }
220
221 let _ = trigger_service
224 .execute(
225 &stellar_monitor_match
226 .monitor
227 .triggers
228 .iter()
229 .map(|s| s.to_string())
230 .collect::<Vec<_>>(),
231 json_to_hashmap(&data_json),
232 &matching_monitor,
233 trigger_scripts,
234 )
235 .await;
236 }
237 }
238 Ok(())
239}
240
241fn json_to_hashmap(json: &JsonValue) -> HashMap<String, String> {
243 let mut result = HashMap::new();
244 flatten_json_path(json, "", &mut result);
245 result
246}
247
248fn flatten_json_path(value: &JsonValue, prefix: &str, result: &mut HashMap<String, String>) {
250 match value {
251 JsonValue::Object(obj) => {
252 for (key, val) in obj {
253 let new_prefix = if prefix.is_empty() {
254 key.clone()
255 } else {
256 format!("{}.{}", prefix, key)
257 };
258 flatten_json_path(val, &new_prefix, result);
259 }
260 }
261 JsonValue::Array(arr) => {
262 for (idx, val) in arr.iter().enumerate() {
263 let new_prefix = format!("{}.{}", prefix, idx);
264 flatten_json_path(val, &new_prefix, result);
265 }
266 }
267 JsonValue::String(s) => insert_primitive(prefix, result, s),
268 JsonValue::Number(n) => insert_primitive(prefix, result, n.to_string()),
269 JsonValue::Bool(b) => insert_primitive(prefix, result, b.to_string()),
270 JsonValue::Null => insert_primitive(prefix, result, "null".to_string()),
271 }
272}
273
274fn insert_primitive<T: ToString>(prefix: &str, result: &mut HashMap<String, String>, value: T) {
276 let key = if prefix.is_empty() {
277 "value".to_string()
278 } else {
279 prefix.to_string()
280 };
281 result.insert(key, value.to_string());
282}
283
284#[cfg(test)]
285mod tests {
286 use super::*;
287 use serde_json::json;
288
289 #[test]
290 fn test_json_to_hashmap() {
291 let json = json!({
292 "monitor": {
293 "name": "Test Monitor",
294 },
295 "transaction": {
296 "hash": "0x1234567890abcdef",
297 },
298 });
299
300 let hashmap = json_to_hashmap(&json);
301 assert_eq!(hashmap["monitor.name"], "Test Monitor");
302 assert_eq!(hashmap["transaction.hash"], "0x1234567890abcdef");
303 }
304
305 #[test]
306 fn test_json_to_hashmap_with_functions() {
307 let json = json!({
308 "monitor": {
309 "name": "Test Monitor",
310 },
311 "functions": [
312 {
313 "signature": "function1(uint256)",
314 "args": {
315 "arg1": "100",
316 },
317 },
318 ],
319 });
320
321 let hashmap = json_to_hashmap(&json);
322 assert_eq!(hashmap["monitor.name"], "Test Monitor");
323 assert_eq!(hashmap["functions.0.signature"], "function1(uint256)");
324 assert_eq!(hashmap["functions.0.args.arg1"], "100");
325 }
326
327 #[test]
328 fn test_json_to_hashmap_with_events() {
329 let json = json!({
330 "monitor": {
331 "name": "Test Monitor",
332 },
333 "events": [
334 {
335 "signature": "event1(uint256)",
336 "args": {
337 "arg1": "100",
338 },
339 },
340 ],
341 });
342
343 let hashmap = json_to_hashmap(&json);
344 assert_eq!(hashmap["monitor.name"], "Test Monitor");
345 assert_eq!(hashmap["events.0.signature"], "event1(uint256)");
346 assert_eq!(hashmap["events.0.args.arg1"], "100");
347 }
348
349 #[test]
351 fn test_flatten_json_path_object() {
352 let json = json!({
353 "monitor": {
354 "name": "Test Monitor",
355 },
356 });
357
358 let mut result = HashMap::new();
359 flatten_json_path(&json, "", &mut result);
360 assert_eq!(result["monitor.name"], "Test Monitor");
361 }
362
363 #[test]
364 fn test_flatten_json_path_array() {
365 let json = json!({
366 "monitor": {
367 "name": "Test Monitor",
368 },
369 });
370
371 let mut result = HashMap::new();
372 flatten_json_path(&json, "", &mut result);
373 assert_eq!(result["monitor.name"], "Test Monitor");
374 }
375
376 #[test]
377 fn test_flatten_json_path_string() {
378 let json = json!("Test String");
379 let mut result = HashMap::new();
380 flatten_json_path(&json, "test_prefix", &mut result);
381 assert_eq!(result["test_prefix"], "Test String");
382
383 let mut result2 = HashMap::new();
384 flatten_json_path(&json, "", &mut result2);
385 assert_eq!(result2["value"], "Test String");
386 }
387
388 #[test]
389 fn test_flatten_json_path_number() {
390 let json = json!(123);
391 let mut result = HashMap::new();
392 flatten_json_path(&json, "test_prefix", &mut result);
393 assert_eq!(result["test_prefix"], "123");
394
395 let mut result2 = HashMap::new();
396 flatten_json_path(&json, "", &mut result2);
397 assert_eq!(result2["value"], "123");
398 }
399
400 #[test]
401 fn test_flatten_json_path_boolean() {
402 let json = json!(true);
403 let mut result = HashMap::new();
404 flatten_json_path(&json, "test_prefix", &mut result);
405 assert_eq!(result["test_prefix"], "true");
406
407 let mut result2 = HashMap::new();
409 flatten_json_path(&json, "", &mut result2);
410 assert_eq!(result2["value"], "true");
411 }
412
413 #[test]
414 fn test_flatten_json_path_null() {
415 let json = json!(null);
416 let mut result = HashMap::new();
417 flatten_json_path(&json, "test_prefix", &mut result);
418 assert_eq!(result["test_prefix"], "null");
419
420 let mut result2 = HashMap::new();
421 flatten_json_path(&json, "", &mut result2);
422 assert_eq!(result2["value"], "null");
423 }
424
425 #[test]
426 fn test_flatten_json_path_nested_object() {
427 let json = json!({
428 "monitor": {
429 "name": "Test Monitor",
430 "nested": {
431 "key": "value",
432 },
433 },
434 });
435
436 let mut result = HashMap::new();
437 flatten_json_path(&json, "", &mut result);
438 assert_eq!(result["monitor.nested.key"], "value");
439 }
440
441 #[test]
442 fn test_flatten_json_path_nested_array() {
443 let json = json!({
444 "monitor": {
445 "name": "Test Monitor",
446 "nested": [
447 {
448 "key": "value1",
449 },
450 {
451 "key": "value2",
452 },
453 ],
454 },
455 });
456
457 let mut result = HashMap::new();
458 flatten_json_path(&json, "", &mut result);
459 assert_eq!(result["monitor.nested.0.key"], "value1");
460 assert_eq!(result["monitor.nested.1.key"], "value2");
461 }
462
463 #[test]
464 fn test_flatten_json_path_with_prefix() {
465 let json = json!({
466 "monitor": {
467 "name": "Test Monitor",
468 },
469 });
470
471 let mut result = HashMap::new();
472 flatten_json_path(&json, "prefix", &mut result);
473 assert_eq!(result["prefix.monitor.name"], "Test Monitor");
474 }
475
476 #[test]
477 fn test_json_to_hashmap_with_primitive_values() {
478 let json_string = json!("Test String");
480 let hashmap_string = json_to_hashmap(&json_string);
481 assert_eq!(hashmap_string["value"], "Test String");
482
483 let json_number = json!(123);
485 let hashmap_number = json_to_hashmap(&json_number);
486 assert_eq!(hashmap_number["value"], "123");
487
488 let json_bool = json!(true);
490 let hashmap_bool = json_to_hashmap(&json_bool);
491 assert_eq!(hashmap_bool["value"], "true");
492
493 let json_null = json!(null);
495 let hashmap_null = json_to_hashmap(&json_null);
496 assert_eq!(hashmap_null["value"], "null");
497 }
498
499 #[test]
500 fn test_insert_primitive() {
501 let mut result = HashMap::new();
502 insert_primitive("prefix", &mut result, "Test String");
503 assert_eq!(result["prefix"], "Test String");
504
505 let mut result2 = HashMap::new();
506 insert_primitive("", &mut result2, "Test String");
507 assert_eq!(result2["value"], "Test String");
508
509 let mut result3 = HashMap::new();
510 insert_primitive("prefix", &mut result3, 123);
511 assert_eq!(result3["prefix"], "123");
512
513 let mut result4 = HashMap::new();
514 insert_primitive("", &mut result4, 123);
515 assert_eq!(result4["value"], "123");
516
517 let mut result5 = HashMap::new();
518 insert_primitive("prefix", &mut result5, true);
519 assert_eq!(result5["prefix"], "true");
520
521 let mut result6 = HashMap::new();
522 insert_primitive("", &mut result6, true);
523 assert_eq!(result6["value"], "true");
524
525 let mut result7 = HashMap::new();
526 insert_primitive("prefix", &mut result7, JsonValue::Null);
527 assert_eq!(result7["prefix"], "null");
528
529 let mut result8 = HashMap::new();
530 insert_primitive("", &mut result8, JsonValue::Null);
531 assert_eq!(result8["value"], "null");
532 }
533}