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 MonitorMatch::Midnight(midnight_monitor_match) => {
238 let transaction = midnight_monitor_match.transaction.clone();
239
240 let mut data_json = json!({
242 "monitor": {
243 "name": midnight_monitor_match.monitor.name.clone(),
244 },
245 "transaction": {
246 "hash": transaction.hash().to_string(),
247 },
248 "functions": [],
249 "events": []
250 });
251
252 let functions = data_json["functions"].as_array_mut().unwrap();
254 for func in midnight_monitor_match.matched_on.functions.iter() {
255 let mut function_data = json!({
256 "signature": func.signature.clone(),
257 "args": {}
258 });
259
260 if let Some(args) = &midnight_monitor_match.matched_on_args {
262 if let Some(func_args) = &args.functions {
263 for func_arg in func_args {
264 if func_arg.signature == func.signature {
265 if let Some(arg_entries) = &func_arg.args {
266 let args_obj = function_data["args"].as_object_mut().unwrap();
267 for arg in arg_entries {
268 args_obj.insert(arg.name.clone(), json!(arg.value.clone()));
269 }
270 }
271 }
272 }
273 }
274 }
275
276 functions.push(function_data);
277 }
278
279 let events = data_json["events"].as_array_mut().unwrap();
281 for event in midnight_monitor_match.matched_on.events.iter() {
282 let mut event_data = json!({
283 "signature": event.signature.clone(),
284 "args": {}
285 });
286
287 if let Some(args) = &midnight_monitor_match.matched_on_args {
289 if let Some(event_args) = &args.events {
290 for event_arg in event_args {
291 if event_arg.signature == event.signature {
292 if let Some(arg_entries) = &event_arg.args {
293 let args_obj = event_data["args"].as_object_mut().unwrap();
294 for arg in arg_entries {
295 args_obj.insert(arg.name.clone(), json!(arg.value.clone()));
296 }
297 }
298 }
299 }
300 }
301 }
302
303 events.push(event_data);
304 }
305
306 let _ = trigger_service
309 .execute(
310 &midnight_monitor_match
311 .monitor
312 .triggers
313 .iter()
314 .map(|s| s.to_string())
315 .collect::<Vec<_>>(),
316 json_to_hashmap(&data_json),
317 &matching_monitor,
318 trigger_scripts,
319 )
320 .await;
321 }
322 MonitorMatch::Solana(solana_monitor_match) => {
323 let transaction = solana_monitor_match.transaction.clone();
324
325 let mut data_json = json!({
327 "monitor": {
328 "name": solana_monitor_match.monitor.name.clone(),
329 },
330 "transaction": {
331 "signature": transaction.signature().to_string(),
332 },
333 "functions": [],
334 "events": []
335 });
336
337 let functions = data_json["functions"].as_array_mut().unwrap();
339 for func in solana_monitor_match.matched_on.functions.iter() {
340 let mut function_data = json!({
341 "signature": func.signature.clone(),
342 "args": {}
343 });
344
345 if let Some(args) = &solana_monitor_match.matched_on_args {
347 if let Some(func_args) = &args.functions {
348 for func_arg in func_args {
349 if func_arg.signature == func.signature {
350 if let Some(arg_entries) = &func_arg.args {
351 let args_obj = function_data["args"].as_object_mut().unwrap();
352 for arg in arg_entries {
353 args_obj.insert(arg.name.clone(), json!(arg.value.clone()));
354 }
355 }
356 }
357 }
358 }
359 }
360
361 functions.push(function_data);
362 }
363
364 let events = data_json["events"].as_array_mut().unwrap();
366 for event in solana_monitor_match.matched_on.events.iter() {
367 let mut event_data = json!({
368 "signature": event.signature.clone(),
369 "args": {}
370 });
371
372 if let Some(args) = &solana_monitor_match.matched_on_args {
374 if let Some(event_args) = &args.events {
375 for event_arg in event_args {
376 if event_arg.signature == event.signature {
377 if let Some(arg_entries) = &event_arg.args {
378 let args_obj = event_data["args"].as_object_mut().unwrap();
379 for arg in arg_entries {
380 args_obj.insert(arg.name.clone(), json!(arg.value.clone()));
381 }
382 }
383 }
384 }
385 }
386 }
387
388 events.push(event_data);
389 }
390
391 let _ = trigger_service
394 .execute(
395 &solana_monitor_match
396 .monitor
397 .triggers
398 .iter()
399 .map(|s| s.to_string())
400 .collect::<Vec<_>>(),
401 json_to_hashmap(&data_json),
402 &matching_monitor,
403 trigger_scripts,
404 )
405 .await;
406 }
407 }
408 Ok(())
409}
410
411fn json_to_hashmap(json: &JsonValue) -> HashMap<String, String> {
413 let mut result = HashMap::new();
414 flatten_json_path(json, "", &mut result);
415 result
416}
417
418fn flatten_json_path(value: &JsonValue, prefix: &str, result: &mut HashMap<String, String>) {
420 match value {
421 JsonValue::Object(obj) => {
422 for (key, val) in obj {
423 let new_prefix = if prefix.is_empty() {
424 key.clone()
425 } else {
426 format!("{}.{}", prefix, key)
427 };
428 flatten_json_path(val, &new_prefix, result);
429 }
430 }
431 JsonValue::Array(arr) => {
432 for (idx, val) in arr.iter().enumerate() {
433 let new_prefix = format!("{}.{}", prefix, idx);
434 flatten_json_path(val, &new_prefix, result);
435 }
436 }
437 JsonValue::String(s) => insert_primitive(prefix, result, s),
438 JsonValue::Number(n) => insert_primitive(prefix, result, n.to_string()),
439 JsonValue::Bool(b) => insert_primitive(prefix, result, b.to_string()),
440 JsonValue::Null => insert_primitive(prefix, result, "null".to_string()),
441 }
442}
443
444fn insert_primitive<T: ToString>(prefix: &str, result: &mut HashMap<String, String>, value: T) {
446 let key = if prefix.is_empty() {
447 "value".to_string()
448 } else {
449 prefix.to_string()
450 };
451 result.insert(key, value.to_string());
452}
453
454#[cfg(test)]
455mod tests {
456 use super::*;
457 use serde_json::json;
458
459 #[test]
460 fn test_json_to_hashmap() {
461 let json = json!({
462 "monitor": {
463 "name": "Test Monitor",
464 },
465 "transaction": {
466 "hash": "0x1234567890abcdef",
467 },
468 });
469
470 let hashmap = json_to_hashmap(&json);
471 assert_eq!(hashmap["monitor.name"], "Test Monitor");
472 assert_eq!(hashmap["transaction.hash"], "0x1234567890abcdef");
473 }
474
475 #[test]
476 fn test_json_to_hashmap_with_functions() {
477 let json = json!({
478 "monitor": {
479 "name": "Test Monitor",
480 },
481 "functions": [
482 {
483 "signature": "function1(uint256)",
484 "args": {
485 "arg1": "100",
486 },
487 },
488 ],
489 });
490
491 let hashmap = json_to_hashmap(&json);
492 assert_eq!(hashmap["monitor.name"], "Test Monitor");
493 assert_eq!(hashmap["functions.0.signature"], "function1(uint256)");
494 assert_eq!(hashmap["functions.0.args.arg1"], "100");
495 }
496
497 #[test]
498 fn test_json_to_hashmap_with_events() {
499 let json = json!({
500 "monitor": {
501 "name": "Test Monitor",
502 },
503 "events": [
504 {
505 "signature": "event1(uint256)",
506 "args": {
507 "arg1": "100",
508 },
509 },
510 ],
511 });
512
513 let hashmap = json_to_hashmap(&json);
514 assert_eq!(hashmap["monitor.name"], "Test Monitor");
515 assert_eq!(hashmap["events.0.signature"], "event1(uint256)");
516 assert_eq!(hashmap["events.0.args.arg1"], "100");
517 }
518
519 #[test]
521 fn test_flatten_json_path_object() {
522 let json = json!({
523 "monitor": {
524 "name": "Test Monitor",
525 },
526 });
527
528 let mut result = HashMap::new();
529 flatten_json_path(&json, "", &mut result);
530 assert_eq!(result["monitor.name"], "Test Monitor");
531 }
532
533 #[test]
534 fn test_flatten_json_path_array() {
535 let json = json!({
536 "monitor": {
537 "name": "Test Monitor",
538 },
539 });
540
541 let mut result = HashMap::new();
542 flatten_json_path(&json, "", &mut result);
543 assert_eq!(result["monitor.name"], "Test Monitor");
544 }
545
546 #[test]
547 fn test_flatten_json_path_string() {
548 let json = json!("Test String");
549 let mut result = HashMap::new();
550 flatten_json_path(&json, "test_prefix", &mut result);
551 assert_eq!(result["test_prefix"], "Test String");
552
553 let mut result2 = HashMap::new();
554 flatten_json_path(&json, "", &mut result2);
555 assert_eq!(result2["value"], "Test String");
556 }
557
558 #[test]
559 fn test_flatten_json_path_number() {
560 let json = json!(123);
561 let mut result = HashMap::new();
562 flatten_json_path(&json, "test_prefix", &mut result);
563 assert_eq!(result["test_prefix"], "123");
564
565 let mut result2 = HashMap::new();
566 flatten_json_path(&json, "", &mut result2);
567 assert_eq!(result2["value"], "123");
568 }
569
570 #[test]
571 fn test_flatten_json_path_boolean() {
572 let json = json!(true);
573 let mut result = HashMap::new();
574 flatten_json_path(&json, "test_prefix", &mut result);
575 assert_eq!(result["test_prefix"], "true");
576
577 let mut result2 = HashMap::new();
579 flatten_json_path(&json, "", &mut result2);
580 assert_eq!(result2["value"], "true");
581 }
582
583 #[test]
584 fn test_flatten_json_path_null() {
585 let json = json!(null);
586 let mut result = HashMap::new();
587 flatten_json_path(&json, "test_prefix", &mut result);
588 assert_eq!(result["test_prefix"], "null");
589
590 let mut result2 = HashMap::new();
591 flatten_json_path(&json, "", &mut result2);
592 assert_eq!(result2["value"], "null");
593 }
594
595 #[test]
596 fn test_flatten_json_path_nested_object() {
597 let json = json!({
598 "monitor": {
599 "name": "Test Monitor",
600 "nested": {
601 "key": "value",
602 },
603 },
604 });
605
606 let mut result = HashMap::new();
607 flatten_json_path(&json, "", &mut result);
608 assert_eq!(result["monitor.nested.key"], "value");
609 }
610
611 #[test]
612 fn test_flatten_json_path_nested_array() {
613 let json = json!({
614 "monitor": {
615 "name": "Test Monitor",
616 "nested": [
617 {
618 "key": "value1",
619 },
620 {
621 "key": "value2",
622 },
623 ],
624 },
625 });
626
627 let mut result = HashMap::new();
628 flatten_json_path(&json, "", &mut result);
629 assert_eq!(result["monitor.nested.0.key"], "value1");
630 assert_eq!(result["monitor.nested.1.key"], "value2");
631 }
632
633 #[test]
634 fn test_flatten_json_path_with_prefix() {
635 let json = json!({
636 "monitor": {
637 "name": "Test Monitor",
638 },
639 });
640
641 let mut result = HashMap::new();
642 flatten_json_path(&json, "prefix", &mut result);
643 assert_eq!(result["prefix.monitor.name"], "Test Monitor");
644 }
645
646 #[test]
647 fn test_json_to_hashmap_with_primitive_values() {
648 let json_string = json!("Test String");
650 let hashmap_string = json_to_hashmap(&json_string);
651 assert_eq!(hashmap_string["value"], "Test String");
652
653 let json_number = json!(123);
655 let hashmap_number = json_to_hashmap(&json_number);
656 assert_eq!(hashmap_number["value"], "123");
657
658 let json_bool = json!(true);
660 let hashmap_bool = json_to_hashmap(&json_bool);
661 assert_eq!(hashmap_bool["value"], "true");
662
663 let json_null = json!(null);
665 let hashmap_null = json_to_hashmap(&json_null);
666 assert_eq!(hashmap_null["value"], "null");
667 }
668
669 #[test]
670 fn test_insert_primitive() {
671 let mut result = HashMap::new();
672 insert_primitive("prefix", &mut result, "Test String");
673 assert_eq!(result["prefix"], "Test String");
674
675 let mut result2 = HashMap::new();
676 insert_primitive("", &mut result2, "Test String");
677 assert_eq!(result2["value"], "Test String");
678
679 let mut result3 = HashMap::new();
680 insert_primitive("prefix", &mut result3, 123);
681 assert_eq!(result3["prefix"], "123");
682
683 let mut result4 = HashMap::new();
684 insert_primitive("", &mut result4, 123);
685 assert_eq!(result4["value"], "123");
686
687 let mut result5 = HashMap::new();
688 insert_primitive("prefix", &mut result5, true);
689 assert_eq!(result5["prefix"], "true");
690
691 let mut result6 = HashMap::new();
692 insert_primitive("", &mut result6, true);
693 assert_eq!(result6["value"], "true");
694
695 let mut result7 = HashMap::new();
696 insert_primitive("prefix", &mut result7, JsonValue::Null);
697 assert_eq!(result7["prefix"], "null");
698
699 let mut result8 = HashMap::new();
700 insert_primitive("", &mut result8, JsonValue::Null);
701 assert_eq!(result8["value"], "null");
702 }
703}