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	}
323	Ok(())
324}
325
326fn json_to_hashmap(json: &JsonValue) -> HashMap<String, String> {
328	let mut result = HashMap::new();
329	flatten_json_path(json, "", &mut result);
330	result
331}
332
333fn flatten_json_path(value: &JsonValue, prefix: &str, result: &mut HashMap<String, String>) {
335	match value {
336		JsonValue::Object(obj) => {
337			for (key, val) in obj {
338				let new_prefix = if prefix.is_empty() {
339					key.clone()
340				} else {
341					format!("{}.{}", prefix, key)
342				};
343				flatten_json_path(val, &new_prefix, result);
344			}
345		}
346		JsonValue::Array(arr) => {
347			for (idx, val) in arr.iter().enumerate() {
348				let new_prefix = format!("{}.{}", prefix, idx);
349				flatten_json_path(val, &new_prefix, result);
350			}
351		}
352		JsonValue::String(s) => insert_primitive(prefix, result, s),
353		JsonValue::Number(n) => insert_primitive(prefix, result, n.to_string()),
354		JsonValue::Bool(b) => insert_primitive(prefix, result, b.to_string()),
355		JsonValue::Null => insert_primitive(prefix, result, "null".to_string()),
356	}
357}
358
359fn insert_primitive<T: ToString>(prefix: &str, result: &mut HashMap<String, String>, value: T) {
361	let key = if prefix.is_empty() {
362		"value".to_string()
363	} else {
364		prefix.to_string()
365	};
366	result.insert(key, value.to_string());
367}
368
369#[cfg(test)]
370mod tests {
371	use super::*;
372	use serde_json::json;
373
374	#[test]
375	fn test_json_to_hashmap() {
376		let json = json!({
377			"monitor": {
378				"name": "Test Monitor",
379			},
380			"transaction": {
381				"hash": "0x1234567890abcdef",
382			},
383		});
384
385		let hashmap = json_to_hashmap(&json);
386		assert_eq!(hashmap["monitor.name"], "Test Monitor");
387		assert_eq!(hashmap["transaction.hash"], "0x1234567890abcdef");
388	}
389
390	#[test]
391	fn test_json_to_hashmap_with_functions() {
392		let json = json!({
393			"monitor": {
394				"name": "Test Monitor",
395			},
396			"functions": [
397				{
398					"signature": "function1(uint256)",
399					"args": {
400						"arg1": "100",
401					},
402				},
403			],
404		});
405
406		let hashmap = json_to_hashmap(&json);
407		assert_eq!(hashmap["monitor.name"], "Test Monitor");
408		assert_eq!(hashmap["functions.0.signature"], "function1(uint256)");
409		assert_eq!(hashmap["functions.0.args.arg1"], "100");
410	}
411
412	#[test]
413	fn test_json_to_hashmap_with_events() {
414		let json = json!({
415			"monitor": {
416				"name": "Test Monitor",
417			},
418			"events": [
419				{
420					"signature": "event1(uint256)",
421					"args": {
422						"arg1": "100",
423					},
424				},
425			],
426		});
427
428		let hashmap = json_to_hashmap(&json);
429		assert_eq!(hashmap["monitor.name"], "Test Monitor");
430		assert_eq!(hashmap["events.0.signature"], "event1(uint256)");
431		assert_eq!(hashmap["events.0.args.arg1"], "100");
432	}
433
434	#[test]
436	fn test_flatten_json_path_object() {
437		let json = json!({
438			"monitor": {
439				"name": "Test Monitor",
440			},
441		});
442
443		let mut result = HashMap::new();
444		flatten_json_path(&json, "", &mut result);
445		assert_eq!(result["monitor.name"], "Test Monitor");
446	}
447
448	#[test]
449	fn test_flatten_json_path_array() {
450		let json = json!({
451			"monitor": {
452				"name": "Test Monitor",
453			},
454		});
455
456		let mut result = HashMap::new();
457		flatten_json_path(&json, "", &mut result);
458		assert_eq!(result["monitor.name"], "Test Monitor");
459	}
460
461	#[test]
462	fn test_flatten_json_path_string() {
463		let json = json!("Test String");
464		let mut result = HashMap::new();
465		flatten_json_path(&json, "test_prefix", &mut result);
466		assert_eq!(result["test_prefix"], "Test String");
467
468		let mut result2 = HashMap::new();
469		flatten_json_path(&json, "", &mut result2);
470		assert_eq!(result2["value"], "Test String");
471	}
472
473	#[test]
474	fn test_flatten_json_path_number() {
475		let json = json!(123);
476		let mut result = HashMap::new();
477		flatten_json_path(&json, "test_prefix", &mut result);
478		assert_eq!(result["test_prefix"], "123");
479
480		let mut result2 = HashMap::new();
481		flatten_json_path(&json, "", &mut result2);
482		assert_eq!(result2["value"], "123");
483	}
484
485	#[test]
486	fn test_flatten_json_path_boolean() {
487		let json = json!(true);
488		let mut result = HashMap::new();
489		flatten_json_path(&json, "test_prefix", &mut result);
490		assert_eq!(result["test_prefix"], "true");
491
492		let mut result2 = HashMap::new();
494		flatten_json_path(&json, "", &mut result2);
495		assert_eq!(result2["value"], "true");
496	}
497
498	#[test]
499	fn test_flatten_json_path_null() {
500		let json = json!(null);
501		let mut result = HashMap::new();
502		flatten_json_path(&json, "test_prefix", &mut result);
503		assert_eq!(result["test_prefix"], "null");
504
505		let mut result2 = HashMap::new();
506		flatten_json_path(&json, "", &mut result2);
507		assert_eq!(result2["value"], "null");
508	}
509
510	#[test]
511	fn test_flatten_json_path_nested_object() {
512		let json = json!({
513			"monitor": {
514				"name": "Test Monitor",
515				"nested": {
516					"key": "value",
517				},
518			},
519		});
520
521		let mut result = HashMap::new();
522		flatten_json_path(&json, "", &mut result);
523		assert_eq!(result["monitor.nested.key"], "value");
524	}
525
526	#[test]
527	fn test_flatten_json_path_nested_array() {
528		let json = json!({
529			"monitor": {
530				"name": "Test Monitor",
531				"nested": [
532					{
533						"key": "value1",
534					},
535					{
536						"key": "value2",
537					},
538				],
539			},
540		});
541
542		let mut result = HashMap::new();
543		flatten_json_path(&json, "", &mut result);
544		assert_eq!(result["monitor.nested.0.key"], "value1");
545		assert_eq!(result["monitor.nested.1.key"], "value2");
546	}
547
548	#[test]
549	fn test_flatten_json_path_with_prefix() {
550		let json = json!({
551			"monitor": {
552				"name": "Test Monitor",
553			},
554		});
555
556		let mut result = HashMap::new();
557		flatten_json_path(&json, "prefix", &mut result);
558		assert_eq!(result["prefix.monitor.name"], "Test Monitor");
559	}
560
561	#[test]
562	fn test_json_to_hashmap_with_primitive_values() {
563		let json_string = json!("Test String");
565		let hashmap_string = json_to_hashmap(&json_string);
566		assert_eq!(hashmap_string["value"], "Test String");
567
568		let json_number = json!(123);
570		let hashmap_number = json_to_hashmap(&json_number);
571		assert_eq!(hashmap_number["value"], "123");
572
573		let json_bool = json!(true);
575		let hashmap_bool = json_to_hashmap(&json_bool);
576		assert_eq!(hashmap_bool["value"], "true");
577
578		let json_null = json!(null);
580		let hashmap_null = json_to_hashmap(&json_null);
581		assert_eq!(hashmap_null["value"], "null");
582	}
583
584	#[test]
585	fn test_insert_primitive() {
586		let mut result = HashMap::new();
587		insert_primitive("prefix", &mut result, "Test String");
588		assert_eq!(result["prefix"], "Test String");
589
590		let mut result2 = HashMap::new();
591		insert_primitive("", &mut result2, "Test String");
592		assert_eq!(result2["value"], "Test String");
593
594		let mut result3 = HashMap::new();
595		insert_primitive("prefix", &mut result3, 123);
596		assert_eq!(result3["prefix"], "123");
597
598		let mut result4 = HashMap::new();
599		insert_primitive("", &mut result4, 123);
600		assert_eq!(result4["value"], "123");
601
602		let mut result5 = HashMap::new();
603		insert_primitive("prefix", &mut result5, true);
604		assert_eq!(result5["prefix"], "true");
605
606		let mut result6 = HashMap::new();
607		insert_primitive("", &mut result6, true);
608		assert_eq!(result6["value"], "true");
609
610		let mut result7 = HashMap::new();
611		insert_primitive("prefix", &mut result7, JsonValue::Null);
612		assert_eq!(result7["prefix"], "null");
613
614		let mut result8 = HashMap::new();
615		insert_primitive("", &mut result8, JsonValue::Null);
616		assert_eq!(result8["value"], "null");
617	}
618}