use alloy_primitives::{Bytes, U256};
use crate::protocol::FinalityThreshold;
#[derive(Debug, Default, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub enum TransferMode {
#[default]
Standard,
Fast {
max_fee: U256,
},
StandardWithHook {
hook_data: Bytes,
},
FastWithHook {
max_fee: U256,
hook_data: Bytes,
},
}
impl TransferMode {
#[inline]
#[must_use]
pub const fn finality_threshold(&self) -> FinalityThreshold {
match self {
Self::Standard | Self::StandardWithHook { .. } => FinalityThreshold::Standard,
Self::Fast { .. } | Self::FastWithHook { .. } => FinalityThreshold::Fast,
}
}
#[inline]
#[must_use]
pub const fn is_fast(&self) -> bool {
match self {
Self::Fast { .. } | Self::FastWithHook { .. } => true,
Self::Standard | Self::StandardWithHook { .. } => false,
}
}
#[inline]
#[must_use]
pub const fn has_hook(&self) -> bool {
match self {
Self::StandardWithHook { .. } | Self::FastWithHook { .. } => true,
Self::Standard | Self::Fast { .. } => false,
}
}
#[inline]
#[must_use]
pub fn max_fee(&self) -> U256 {
match self {
Self::Fast { max_fee } | Self::FastWithHook { max_fee, .. } => *max_fee,
Self::Standard | Self::StandardWithHook { .. } => U256::ZERO,
}
}
#[inline]
#[must_use]
pub const fn hook_data(&self) -> Option<&Bytes> {
match self {
Self::StandardWithHook { hook_data } | Self::FastWithHook { hook_data, .. } => {
Some(hook_data)
}
Self::Standard | Self::Fast { .. } => None,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn standard_defaults() {
let mode = TransferMode::default();
assert_eq!(mode, TransferMode::Standard);
assert_eq!(mode.finality_threshold(), FinalityThreshold::Standard);
assert!(!mode.is_fast());
assert!(!mode.has_hook());
assert_eq!(mode.max_fee(), U256::ZERO);
assert!(mode.hook_data().is_none());
}
#[test]
fn fast_carries_fee() {
let mode = TransferMode::Fast {
max_fee: U256::from(1234),
};
assert_eq!(mode.finality_threshold(), FinalityThreshold::Fast);
assert!(mode.is_fast());
assert!(!mode.has_hook());
assert_eq!(mode.max_fee(), U256::from(1234));
assert!(mode.hook_data().is_none());
}
#[test]
fn standard_with_hook_keeps_standard_finality() {
let hook = Bytes::from(vec![1, 2, 3]);
let mode = TransferMode::StandardWithHook {
hook_data: hook.clone(),
};
assert_eq!(mode.finality_threshold(), FinalityThreshold::Standard);
assert!(!mode.is_fast());
assert!(mode.has_hook());
assert_eq!(mode.max_fee(), U256::ZERO);
assert_eq!(mode.hook_data(), Some(&hook));
}
#[test]
fn fast_with_hook_combines_both() {
let hook = Bytes::from(vec![0xde, 0xad, 0xbe, 0xef]);
let mode = TransferMode::FastWithHook {
max_fee: U256::from(500),
hook_data: hook.clone(),
};
assert_eq!(mode.finality_threshold(), FinalityThreshold::Fast);
assert!(mode.is_fast());
assert!(mode.has_hook());
assert_eq!(mode.max_fee(), U256::from(500));
assert_eq!(mode.hook_data(), Some(&hook));
}
}