openzeppelin_relayer/domain/transaction/stellar/
utils.rsuse crate::models::OperationSpec;
use crate::models::RelayerError;
pub fn needs_simulation(operations: &[OperationSpec]) -> bool {
operations
.iter()
.any(|op| !matches!(op, OperationSpec::Payment { .. }))
}
pub fn next_sequence_u64(seq_num: i64) -> Result<u64, RelayerError> {
let next_i64 = seq_num
.checked_add(1)
.ok_or_else(|| RelayerError::ProviderError("sequence overflow".into()))?;
u64::try_from(next_i64)
.map_err(|_| RelayerError::ProviderError("sequence overflows u64".into()))
}
pub fn i64_from_u64(value: u64) -> Result<i64, RelayerError> {
i64::try_from(value).map_err(|_| RelayerError::ProviderError("u64→i64 overflow".into()))
}
#[cfg(test)]
mod tests {
use super::*;
use crate::models::AssetSpec;
const TEST_PK: &str = "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWHF";
fn payment_op(destination: &str) -> OperationSpec {
OperationSpec::Payment {
destination: destination.to_string(),
amount: 100,
asset: AssetSpec::Native,
}
}
#[test]
fn returns_false_for_only_payment_ops() {
let ops = vec![payment_op(TEST_PK)];
assert!(!needs_simulation(&ops));
}
mod next_sequence_u64_tests {
use super::*;
#[test]
fn test_increment() {
assert_eq!(next_sequence_u64(0).unwrap(), 1);
assert_eq!(next_sequence_u64(12345).unwrap(), 12346);
}
#[test]
fn test_error_path_overflow_i64_max() {
let result = next_sequence_u64(i64::MAX);
assert!(result.is_err());
match result.unwrap_err() {
RelayerError::ProviderError(msg) => assert_eq!(msg, "sequence overflow"),
_ => panic!("Unexpected error type"),
}
}
}
mod i64_from_u64_tests {
use super::*;
#[test]
fn test_happy_path_conversion() {
assert_eq!(i64_from_u64(0).unwrap(), 0);
assert_eq!(i64_from_u64(12345).unwrap(), 12345);
assert_eq!(i64_from_u64(i64::MAX as u64).unwrap(), i64::MAX);
}
#[test]
fn test_error_path_overflow_u64_max() {
let result = i64_from_u64(u64::MAX);
assert!(result.is_err());
match result.unwrap_err() {
RelayerError::ProviderError(msg) => assert_eq!(msg, "u64→i64 overflow"),
_ => panic!("Unexpected error type"),
}
}
#[test]
fn test_edge_case_just_above_i64_max() {
let value = (i64::MAX as u64) + 1;
let result = i64_from_u64(value);
assert!(result.is_err());
match result.unwrap_err() {
RelayerError::ProviderError(msg) => assert_eq!(msg, "u64→i64 overflow"),
_ => panic!("Unexpected error type"),
}
}
}
}