@@ -2,6 +2,7 @@ use std::marker::PhantomData;
22use std:: time:: { SystemTime , UNIX_EPOCH } ;
33
44use alloy:: primitives:: { B256 , U256 } ;
5+ use alloy:: signers:: Signer ;
56use chrono:: { DateTime , Utc } ;
67use rand:: RngExt as _;
78use rust_decimal:: prelude:: ToPrimitive as _;
@@ -11,6 +12,7 @@ use crate::auth::Kind as AuthKind;
1112use crate :: auth:: state:: Authenticated ;
1213use crate :: clob:: Client ;
1314use crate :: clob:: types:: request:: OrderBookSummaryRequest ;
15+ use crate :: clob:: types:: response:: PostOrderResponse ;
1416use crate :: clob:: types:: {
1517 Amount , AmountInner , Order , OrderPayload , OrderType , Side , SignableOrder , SignatureType ,
1618} ;
@@ -51,6 +53,7 @@ pub struct OrderBuilder<OrderKind, K: AuthKind> {
5153 pub ( crate ) metadata : Option < B256 > ,
5254 pub ( crate ) builder_code : Option < B256 > ,
5355 pub ( crate ) defer_exec : Option < bool > ,
56+ pub ( crate ) user_usdc_balance : Option < Decimal > ,
5457 pub ( crate ) _kind : PhantomData < OrderKind > ,
5558}
5659
@@ -269,6 +272,18 @@ impl<K: AuthKind> OrderBuilder<Limit, K> {
269272 defer_exec : self . defer_exec ,
270273 } )
271274 }
275+
276+ /// Convenience: builds, signs, and posts this limit order in a single call.
277+ ///
278+ /// # Errors
279+ ///
280+ /// Returns an error if any of the build, sign, or post steps fails.
281+ pub async fn build_sign_and_post < S : Signer > ( self , signer : & S ) -> Result < PostOrderResponse > {
282+ let client = self . client . clone ( ) ;
283+ let order = self . build ( ) . await ?;
284+ let signed = client. sign ( signer, order) . await ?;
285+ client. post_order ( signed) . await
286+ }
272287}
273288
274289impl < K : AuthKind > OrderBuilder < Market , K > {
@@ -286,6 +301,15 @@ impl<K: AuthKind> OrderBuilder<Market, K> {
286301 self
287302 }
288303
304+ /// Sets the user's USDC balance. When set on a BUY market order, `build()` shrinks
305+ /// the USDC amount to cover platform + builder taker fees so the order stays within
306+ /// the user's balance.
307+ #[ must_use]
308+ pub fn user_usdc_balance ( mut self , balance : Decimal ) -> Self {
309+ self . user_usdc_balance = Some ( balance) ;
310+ self
311+ }
312+
289313 // Attempts to calculate the market price from the top of the book for the particular token.
290314 // - Uses an orderbook depth search to find the cutoff price:
291315 // - BUY + USDC: walk asks until notional >= USDC
@@ -408,6 +432,34 @@ impl<K: AuthKind> OrderBuilder<Market, K> {
408432 ) ) ) ;
409433 }
410434
435+ let amount = match ( side, amount. 0 , self . user_usdc_balance ) {
436+ ( Side :: Buy , AmountInner :: Usdc ( raw) , Some ( balance) )
437+ if matches ! ( order_type, OrderType :: FOK | OrderType :: FAK ) =>
438+ {
439+ let fee = self . client . fee_rate_bps ( token_id) . await ?;
440+ let fee_rate = Decimal :: from ( fee. base_fee ) / Decimal :: from ( 10_000_u32 ) ;
441+ let fee_exponent = Decimal :: from ( fee. exponent . unwrap_or ( 0 ) ) ;
442+ let builder_taker_fee = match self . builder_code {
443+ Some ( code) if code != B256 :: ZERO => {
444+ let rate = self . client . builder_fee_rate ( code) . await ?;
445+ Decimal :: from ( rate. builder_taker_fee_rate_bps ) / Decimal :: from ( 10_000_u32 )
446+ }
447+ _ => Decimal :: ZERO ,
448+ } ;
449+
450+ let adjusted = super :: utilities:: adjust_market_buy_amount (
451+ raw,
452+ balance,
453+ price,
454+ fee_rate,
455+ fee_exponent,
456+ builder_taker_fee,
457+ ) ;
458+ Amount :: usdc ( adjusted) ?
459+ }
460+ _ => amount,
461+ } ;
462+
411463 let raw_amount = amount. as_inner ( ) ;
412464
413465 let ( taker_amount, maker_amount) = match ( side, amount. 0 ) {
@@ -465,6 +517,18 @@ impl<K: AuthKind> OrderBuilder<Market, K> {
465517 defer_exec : self . defer_exec ,
466518 } )
467519 }
520+
521+ /// Convenience: builds, signs, and posts this market order in a single call.
522+ ///
523+ /// # Errors
524+ ///
525+ /// Returns an error if any of the build, sign, or post steps fails.
526+ pub async fn build_sign_and_post < S : Signer > ( self , signer : & S ) -> Result < PostOrderResponse > {
527+ let client = self . client . clone ( ) ;
528+ let order = self . build ( ) . await ?;
529+ let signed = client. sign ( signer, order) . await ?;
530+ client. post_order ( signed) . await
531+ }
468532}
469533
470534/// Removes trailing zeros, truncates to [`USDC_DECIMALS`] decimal places, and quanitizes as an
0 commit comments