pub struct TwapOrder {
pub data: TwapData,
pub salt: B256,
}Expand description
A TWAP order ready to be submitted to ComposableCow.
Fields§
§data: TwapDataThe underlying TWAP configuration.
salt: B25632-byte salt uniquely identifying this order instance.
Implementations§
Source§impl TwapOrder
impl TwapOrder
Sourcepub fn new(data: TwapData) -> Self
pub fn new(data: TwapData) -> Self
Create a new TWAP order.
The salt is derived deterministically from the order parameters.
Use TwapOrder::with_salt to supply an explicit salt.
§Example
use alloy_primitives::{Address, U256};
use cow_composable::{TwapData, TwapOrder};
let data = TwapData::sell(Address::ZERO, Address::ZERO, U256::from(1000u64), 4, 3600);
let order = TwapOrder::new(data);
assert_eq!(order.data.num_parts, 4);
assert_eq!(order.data.part_duration, 3600);Sourcepub fn to_params(&self) -> Result<ConditionalOrderParams, CowError>
pub fn to_params(&self) -> Result<ConditionalOrderParams, CowError>
Returns the on-chain ConditionalOrderParams for this order.
§Errors
Returns CowError::AppData if ABI encoding fails.
Sourcepub fn id(&self) -> Result<B256, CowError>
pub fn id(&self) -> Result<B256, CowError>
Unique order ID: keccak256(abi.encode(ConditionalOrderParams)).
§Errors
Returns CowError::AppData if encoding fails.
Sourcepub fn is_valid(&self) -> bool
pub fn is_valid(&self) -> bool
Validate the order parameters.
Mirrors the TypeScript SDK Twap.isValid() logic:
- Tokens must differ and must not be the zero address
sell_amountandbuy_amountmust be non-zeronum_partsmust be ≥ 2part_durationmust be > 0 and ≤MAX_FREQUENCYsell_amountmust be divisible bynum_parts- If
DurationOfPart::LimitDuration:durationmust be ≤part_duration
Sourcepub fn per_part_amounts(&self) -> Result<(U256, U256), CowError>
pub fn per_part_amounts(&self) -> Result<(U256, U256), CowError>
Return the per-part sell and buy amounts (part_sell, min_part_buy).
These are the amounts used in each individual order slice:
sell_amount / num_parts and buy_amount / num_parts.
§Errors
Returns CowError::AppData if num_parts is zero.
§Example
use alloy_primitives::{Address, U256};
use cow_composable::{TwapData, TwapOrder};
let data = TwapData::sell(Address::ZERO, Address::ZERO, U256::from(1000u64), 4, 3600)
.with_buy_amount(U256::from(800u64));
let order = TwapOrder::new(data);
let (sell, buy) = order.per_part_amounts().unwrap();
assert_eq!(sell, U256::from(250u64));
assert_eq!(buy, U256::from(200u64));Sourcepub fn to_struct(&self) -> Result<TwapStruct, CowError>
pub fn to_struct(&self) -> Result<TwapStruct, CowError>
Convert this order’s user-facing data into the on-chain TwapStruct representation.
The struct uses per-part amounts and the raw span/t0 fields.
§Errors
Returns CowError::AppData if num_parts is zero.
Sourcepub fn poll_validate(&self, block_timestamp: u64) -> PollResult
pub fn poll_validate(&self, block_timestamp: u64) -> PollResult
Check tradability of this TWAP order at the given block timestamp.
Returns PollResult::Success if the order is within its execution
window, PollResult::TryAtEpoch if the order has not started yet,
or PollResult::DontTryAgain if the order has fully expired.
For TwapStartTime::AtMiningTime orders, always returns
PollResult::Success because the start time is not known until mined.
Source§impl TwapOrder
impl TwapOrder
Sourcepub const fn total_sell_amount(&self) -> U256
pub const fn total_sell_amount(&self) -> U256
Returns the total sell amount across all parts.
use alloy_primitives::{Address, U256};
use cow_composable::{TwapData, TwapOrder};
let data = TwapData::sell(Address::ZERO, Address::ZERO, U256::from(1_000u64), 4, 3_600);
let order = TwapOrder::new(data);
assert_eq!(order.total_sell_amount(), U256::from(1_000u64));Sourcepub const fn total_buy_amount(&self) -> U256
pub const fn total_buy_amount(&self) -> U256
Returns the total minimum buy amount across all parts.
use alloy_primitives::{Address, U256};
use cow_composable::{TwapData, TwapOrder};
let data = TwapData::sell(Address::ZERO, Address::ZERO, U256::ZERO, 4, 3_600)
.with_buy_amount(U256::from(800u64));
let order = TwapOrder::new(data);
assert_eq!(order.total_buy_amount(), U256::from(800u64));Sourcepub const fn is_sell(&self) -> bool
pub const fn is_sell(&self) -> bool
Returns true if this is a sell-direction TWAP order.
§Returns
true when the order kind is OrderKind::Sell, false otherwise.
Sourcepub const fn is_buy(&self) -> bool
pub const fn is_buy(&self) -> bool
Returns true if this is a buy-direction TWAP order.
§Returns
true when the order kind is OrderKind::Buy, false otherwise.
Sourcepub const fn is_expired_at(&self, block_timestamp: u64) -> bool
pub const fn is_expired_at(&self, block_timestamp: u64) -> bool
Returns true if the order has fully expired at the given Unix timestamp.
Delegates to TwapData::is_expired. Returns false when the start
time is TwapStartTime::AtMiningTime (end time is unknown until mined).
use alloy_primitives::{Address, U256};
use cow_composable::{TwapData, TwapOrder, TwapStartTime};
let data = TwapData::sell(Address::ZERO, Address::ZERO, U256::ZERO, 4, 3_600)
.with_start_time(TwapStartTime::At(1_000_000));
// ends at 1_000_000 + 4 × 3600 = 1_014_400
let order = TwapOrder::new(data);
assert!(!order.is_expired_at(1_014_399));
assert!(order.is_expired_at(1_014_400));Sourcepub const fn start_timestamp(&self) -> Option<u32>
pub const fn start_timestamp(&self) -> Option<u32>
Return the fixed start timestamp, or None when the order starts at mining time.
Mirrors TwapData::start_time::timestamp().
Trait Implementations§
Auto Trait Implementations§
impl Freeze for TwapOrder
impl RefUnwindSafe for TwapOrder
impl Send for TwapOrder
impl Sync for TwapOrder
impl Unpin for TwapOrder
impl UnsafeUnpin for TwapOrder
impl UnwindSafe for TwapOrder
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§impl<T> PolicyExt for Twhere
T: ?Sized,
impl<T> PolicyExt for Twhere
T: ?Sized,
Source§impl<T> ToStringFallible for Twhere
T: Display,
impl<T> ToStringFallible for Twhere
T: Display,
Source§fn try_to_string(&self) -> Result<String, TryReserveError>
fn try_to_string(&self) -> Result<String, TryReserveError>
ToString::to_string, but without panic on OOM.