openzeppelin_relayer/jobs/handlers/
transaction_submission_handler.rsuse actix_web::web::ThinData;
use apalis::prelude::{Attempt, Data, *};
use eyre::Result;
use log::info;
use crate::{
constants::WORKER_DEFAULT_MAXIMUM_RETRIES,
domain::{get_relayer_transaction, get_transaction_by_id, Transaction},
jobs::{handle_result, Job, JobProducer, TransactionCommand, TransactionSend},
models::AppState,
};
pub async fn transaction_submission_handler(
job: Job<TransactionSend>,
state: Data<ThinData<AppState<JobProducer>>>,
attempt: Attempt,
) -> Result<(), Error> {
info!("handling transaction submission: {:?}", job.data);
let result = handle_request(job.data, state).await;
handle_result(
result,
attempt,
"Transaction Sender",
WORKER_DEFAULT_MAXIMUM_RETRIES,
)
}
async fn handle_request(
status_request: TransactionSend,
state: Data<ThinData<AppState<JobProducer>>>,
) -> Result<()> {
let relayer_transaction =
get_relayer_transaction(status_request.relayer_id.clone(), &state).await?;
let transaction = get_transaction_by_id(status_request.transaction_id, &state).await?;
match status_request.command {
TransactionCommand::Submit => {
relayer_transaction.submit_transaction(transaction).await?;
}
TransactionCommand::Cancel { reason } => {
info!("Cancelling transaction: {:?}", reason);
relayer_transaction.submit_transaction(transaction).await?;
}
TransactionCommand::Resubmit => {
info!("Resubmitting transaction with updated parameters");
relayer_transaction
.resubmit_transaction(transaction)
.await?;
}
TransactionCommand::Resend => {
info!("Resending transaction");
relayer_transaction.submit_transaction(transaction).await?;
}
};
info!("Transaction handled successfully");
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
use std::collections::HashMap;
#[tokio::test]
async fn test_submission_handler_job_validation() {
let submit_job = TransactionSend::submit("tx123", "relayer-1");
let job = Job::new(crate::jobs::JobType::TransactionSend, submit_job);
match job.data.command {
TransactionCommand::Submit => {}
_ => panic!("Expected Submit command"),
}
assert_eq!(job.data.transaction_id, "tx123");
assert_eq!(job.data.relayer_id, "relayer-1");
assert!(job.data.metadata.is_none());
let cancel_job = TransactionSend::cancel("tx123", "relayer-1", "user requested");
let job = Job::new(crate::jobs::JobType::TransactionSend, cancel_job);
match job.data.command {
TransactionCommand::Cancel { reason } => {
assert_eq!(reason, "user requested");
}
_ => panic!("Expected Cancel command"),
}
}
#[tokio::test]
async fn test_submission_job_with_metadata() {
let mut metadata = HashMap::new();
metadata.insert("gas_price".to_string(), "20000000000".to_string());
let submit_job =
TransactionSend::submit("tx123", "relayer-1").with_metadata(metadata.clone());
assert!(submit_job.metadata.is_some());
let job_metadata = submit_job.metadata.unwrap();
assert_eq!(job_metadata.get("gas_price").unwrap(), "20000000000");
}
}