openzeppelin_relayer/jobs/handlers/
transaction_submission_handler.rs1use actix_web::web::ThinData;
9use apalis::prelude::{Attempt, Data, *};
10use eyre::Result;
11use log::info;
12
13use crate::{
14 constants::WORKER_DEFAULT_MAXIMUM_RETRIES,
15 domain::{get_relayer_transaction, get_transaction_by_id, Transaction},
16 jobs::{handle_result, Job, TransactionCommand, TransactionSend},
17 models::DefaultAppState,
18};
19
20pub async fn transaction_submission_handler(
21 job: Job<TransactionSend>,
22 state: Data<ThinData<DefaultAppState>>,
23 attempt: Attempt,
24) -> Result<(), Error> {
25 info!("handling transaction submission: {:?}", job.data);
26
27 let result = handle_request(job.data, state).await;
28
29 handle_result(
30 result,
31 attempt,
32 "Transaction Sender",
33 WORKER_DEFAULT_MAXIMUM_RETRIES,
34 )
35}
36
37async fn handle_request(
38 status_request: TransactionSend,
39 state: Data<ThinData<DefaultAppState>>,
40) -> Result<()> {
41 let relayer_transaction =
42 get_relayer_transaction(status_request.relayer_id.clone(), &state).await?;
43
44 let transaction = get_transaction_by_id(status_request.transaction_id, &state).await?;
45
46 match status_request.command {
47 TransactionCommand::Submit => {
48 relayer_transaction.submit_transaction(transaction).await?;
49 }
50 TransactionCommand::Cancel { reason } => {
51 info!("Cancelling transaction: {:?}", reason);
52 relayer_transaction.submit_transaction(transaction).await?;
53 }
54 TransactionCommand::Resubmit => {
55 info!("Resubmitting transaction with updated parameters");
56 relayer_transaction
57 .resubmit_transaction(transaction)
58 .await?;
59 }
60 TransactionCommand::Resend => {
61 info!("Resending transaction");
62 relayer_transaction.submit_transaction(transaction).await?;
63 }
64 };
65
66 info!("Transaction handled successfully");
67
68 Ok(())
69}
70
71#[cfg(test)]
72mod tests {
73 use super::*;
74 use std::collections::HashMap;
75
76 #[tokio::test]
77 async fn test_submission_handler_job_validation() {
78 let submit_job = TransactionSend::submit("tx123", "relayer-1");
80 let job = Job::new(crate::jobs::JobType::TransactionSend, submit_job);
81
82 match job.data.command {
84 TransactionCommand::Submit => {}
85 _ => panic!("Expected Submit command"),
86 }
87 assert_eq!(job.data.transaction_id, "tx123");
88 assert_eq!(job.data.relayer_id, "relayer-1");
89 assert!(job.data.metadata.is_none());
90
91 let cancel_job = TransactionSend::cancel("tx123", "relayer-1", "user requested");
93 let job = Job::new(crate::jobs::JobType::TransactionSend, cancel_job);
94
95 match job.data.command {
97 TransactionCommand::Cancel { reason } => {
98 assert_eq!(reason, "user requested");
99 }
100 _ => panic!("Expected Cancel command"),
101 }
102 }
103
104 #[tokio::test]
105 async fn test_submission_job_with_metadata() {
106 let mut metadata = HashMap::new();
108 metadata.insert("gas_price".to_string(), "20000000000".to_string());
109
110 let submit_job =
111 TransactionSend::submit("tx123", "relayer-1").with_metadata(metadata.clone());
112
113 assert!(submit_job.metadata.is_some());
115 let job_metadata = submit_job.metadata.unwrap();
116 assert_eq!(job_metadata.get("gas_price").unwrap(), "20000000000");
117 }
118
119 }