pub struct HyperliquidSpotClient { /* private fields */ }Expand description
Hyperliquid spot trading execution client.
Wraps the official hyperliquid_rust_sdk to implement the ExecutionClient trait
for spot trading on Hyperliquid DEX.
Implementations§
Source§impl HyperliquidSpotClient
impl HyperliquidSpotClient
Sourcepub async fn connect(
config: HyperliquidConfig,
) -> Result<Self, ConnectivityError>
pub async fn connect( config: HyperliquidConfig, ) -> Result<Self, ConnectivityError>
Create a new spot client asynchronously.
Use this when calling from an async context (e.g., tokio tests).
For sync contexts, use ExecutionClient::new().
§Errors
ConnectivityError::Socket when the SDK clients cannot be created, or Hyperliquid’s
spotMeta cannot be read (see Spot coins).
Sourcepub fn wallet_address(&self) -> String
pub fn wallet_address(&self) -> String
Returns the wallet address as a hex string (for logging/debugging).
Sourcepub async fn order_precision(
&self,
instrument: &InstrumentNameExchange,
) -> Option<OrderPrecision>
pub async fn order_precision( &self, instrument: &InstrumentNameExchange, ) -> Option<OrderPrecision>
The precision rules for orders on the spot pair instrument (BASE-QUOTE-SPOT), from
its base token’s szDecimals.
open_order refuses an order that breaks them with
OrderError::InvalidPrecision and sends nothing. Round with these rules first. See
OrderPrecision.
None when instrument is not of that form, or Hyperliquid lists no such pair. A pair
missing from the pairs this client holds is looked for in spotMeta again first, at most
once every 10 seconds, so a pair listed since the client connected is found.
None too when instrument spells the pair’s tokens differently from Hyperliquid, even
only in ASCII case (KPEPE-USDC-SPOT for kPEPE/USDC). Every order report names the
pair as Hyperliquid spells it, so open_order refuses an
order under any other spelling, naming the one to use.
Trait Implementations§
Source§impl Clone for HyperliquidSpotClient
impl Clone for HyperliquidSpotClient
Source§impl Debug for HyperliquidSpotClient
impl Debug for HyperliquidSpotClient
Source§impl ExecutionClient for HyperliquidSpotClient
impl ExecutionClient for HyperliquidSpotClient
Source§fn new(config: Self::Config) -> Self
fn new(config: Self::Config) -> Self
Creates a new Hyperliquid spot client synchronously.
§Panics
- If no Tokio runtime is available on the current thread
- If called from within an async context (e.g., inside
async fn,spawn, orblock_on) - If SDK initialization fails (network error, invalid credentials), or Hyperliquid’s
spotMetacannot be read
§Recommended Usage
Use HyperliquidSpotClient::connect instead — it’s async-safe and returns Result.
This method exists only for trait compliance; prefer connect() in all new code.
Source§async fn account_stream(
&self,
_assets: &[AssetNameExchange],
_instruments: &[InstrumentNameExchange],
) -> Result<Self::AccountStream, UnindexedClientError>
async fn account_stream( &self, _assets: &[AssetNameExchange], _instruments: &[InstrumentNameExchange], ) -> Result<Self::AccountStream, UnindexedClientError>
Returns a live stream of account events (fills, order updates) for spot orders.
§Instrument filtering
The instruments parameter is ignored — Hyperliquid’s WebSocket API does not
support per-instrument subscriptions for user events. All fills and order updates
are delivered, but we filter client-side to only emit spot events (see
Spot coins).
§Task lifecycle
Spawns three background tasks (fills, orders, and the reconnect’s order check) that are automatically cancelled when the returned stream is dropped.
§Orders that ended while disconnected
After each reconnect the stream reports how each order the client holds as live ended,
where it did, exactly as HyperliquidClient’s does; see its
account_stream. The listing leaves out an order on a spot coin missing from spotMeta,
which cannot be on an instrument the client holds an order on, but a lookup that finds an
order on one, even after spotMeta is read again (see Spot coins),
fails, and is retried.
Source§async fn fetch_trades(
&self,
start: DateTime<Utc>,
end: DateTime<Utc>,
instruments: &[InstrumentNameExchange],
) -> Result<TradesRead<AssetNameExchange, InstrumentNameExchange>, UnindexedClientError>
async fn fetch_trades( &self, start: DateTime<Utc>, end: DateTime<Utc>, instruments: &[InstrumentNameExchange], ) -> Result<TradesRead<AssetNameExchange, InstrumentNameExchange>, UnindexedClientError>
Reads the span with userFillsByTime, to its end within the call, so the read is always
complete (resume: None). Hyperliquid keeps only each wallet’s 10,000 most recent fills,
so a span reaching further back is read only as far as those go, and
held_since says where that is.
const EXCHANGE: ExchangeId = ExchangeId::HyperliquidSpot
Source§const SUPPORTED_KINDS: &'static [InstrumentKindDiscriminant]
const SUPPORTED_KINDS: &'static [InstrumentKindDiscriminant]
InstrumentKindDiscriminants this client can trade. Read moretype Config = HyperliquidConfig
type AccountStream = Pin<Box<dyn Stream<Item = AccountEvent<ExchangeId, AssetNameExchange, InstrumentNameExchange>> + Send>>
Source§async fn account_snapshot(
&self,
_assets: &[AssetNameExchange],
instruments: &[InstrumentNameExchange],
) -> Result<UnindexedAccountSnapshot, UnindexedClientError>
async fn account_snapshot( &self, _assets: &[AssetNameExchange], instruments: &[InstrumentNameExchange], ) -> Result<UnindexedAccountSnapshot, UnindexedClientError>
instruments, from the
venue. Read moreSource§async fn cancel_order(
&self,
request: OrderRequestCancel<ExchangeId, &InstrumentNameExchange>,
) -> UnindexedOrderResponseCancel
async fn cancel_order( &self, request: OrderRequestCancel<ExchangeId, &InstrumentNameExchange>, ) -> UnindexedOrderResponseCancel
Source§async fn open_order(
&self,
request: OrderRequestOpen<ExchangeId, &InstrumentNameExchange>,
) -> Order<ExchangeId, InstrumentNameExchange, UnindexedOrderState>
async fn open_order( &self, request: OrderRequestOpen<ExchangeId, &InstrumentNameExchange>, ) -> Order<ExchangeId, InstrumentNameExchange, UnindexedOrderState>
Source§async fn fetch_balances(
&self,
_assets: &[AssetNameExchange],
) -> Result<Vec<AssetBalance<AssetNameExchange>>, UnindexedClientError>
async fn fetch_balances( &self, _assets: &[AssetNameExchange], ) -> Result<Vec<AssetBalance<AssetNameExchange>>, UnindexedClientError>
Source§async fn fetch_open_orders(
&self,
instruments: &[InstrumentNameExchange],
) -> Result<Vec<Order<ExchangeId, InstrumentNameExchange, Open>>, UnindexedClientError>
async fn fetch_open_orders( &self, instruments: &[InstrumentNameExchange], ) -> Result<Vec<Order<ExchangeId, InstrumentNameExchange, Open>>, UnindexedClientError>
Source§fn validate_config(
config: &Self::Config,
instruments: &[ClientInstrument<'_>],
) -> Result<(), String>
fn validate_config( config: &Self::Config, instruments: &[ClientInstrument<'_>], ) -> Result<(), String>
fn cancel_orders<'a>( &self, requests: impl IntoIterator<Item = OrderRequestCancel<ExchangeId, &'a InstrumentNameExchange>>, ) -> impl Stream<Item = UnindexedOrderResponseCancel> + Send
fn open_orders<'a>( &self, requests: impl IntoIterator<Item = OrderRequestOpen<ExchangeId, &'a InstrumentNameExchange>>, ) -> impl Stream<Item = Order<ExchangeId, InstrumentNameExchange, UnindexedOrderState>> + Send
Source§impl OrderStatusClient for HyperliquidSpotClient
Looks each order up with orderStatus (weight 2), as
HyperliquidClient does; see its implementation for how each
status is reported. An order on a spot coin missing from spotMeta even after it is read again
(see Spot coins) fails the call, since it cannot be told apart from an order
on the key’s instrument.
impl OrderStatusClient for HyperliquidSpotClient
Looks each order up with orderStatus (weight 2), as
HyperliquidClient does; see its implementation for how each
status is reported. An order on a spot coin missing from spotMeta even after it is read again
(see Spot coins) fails the call, since it cannot be told apart from an order
on the key’s instrument.
The account stream runs the same lookup itself after a reconnect; see
account_stream.
Source§async fn fetch_order_status(
&self,
key: &UnindexedOrderKey,
) -> Result<VenueOrderStatus, UnindexedClientError>
async fn fetch_order_status( &self, key: &UnindexedOrderKey, ) -> Result<VenueOrderStatus, UnindexedClientError>
One orderStatus (weight 2), which reports a live order as well as an ended one, read
as fetch_ended_orders reads it.
§Errors
When the lookup fails, the order is on a spot coin missing from spotMeta, or
Hyperliquid’s record of the order does not convert.
Source§async fn fetch_ended_orders(
&self,
orders: &[UnindexedOrderKey],
) -> Result<Vec<UnindexedInactiveOrder>, UnindexedClientError>
async fn fetch_ended_orders( &self, orders: &[UnindexedOrderKey], ) -> Result<Vec<UnindexedInactiveOrder>, UnindexedClientError>
orders ended, for those that have. Read moreAuto Trait Implementations§
impl !RefUnwindSafe for HyperliquidSpotClient
impl !UnwindSafe for HyperliquidSpotClient
impl Freeze for HyperliquidSpotClient
impl Send for HyperliquidSpotClient
impl Sync for HyperliquidSpotClient
impl Unpin for HyperliquidSpotClient
impl UnsafeUnpin for HyperliquidSpotClient
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> FmtForward for T
impl<T> FmtForward for T
Source§fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
self to use its Binary implementation when Debug-formatted.Source§fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
self to use its Display implementation when
Debug-formatted.Source§fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
self to use its LowerExp implementation when
Debug-formatted.Source§fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
self to use its LowerHex implementation when
Debug-formatted.Source§fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
self to use its Octal implementation when Debug-formatted.Source§fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
self to use its Pointer implementation when
Debug-formatted.Source§fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
self to use its UpperExp implementation when
Debug-formatted.Source§fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
self to use its UpperHex implementation when
Debug-formatted.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> 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 moreimpl<T> JsonSchemaMaybe for T
Source§impl<T> Pipe for Twhere
T: ?Sized,
impl<T> Pipe for Twhere
T: ?Sized,
Source§fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
Source§fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
self and passes that borrow into the pipe function. Read moreSource§fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
self and passes that borrow into the pipe function. Read moreSource§fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
Source§fn pipe_borrow_mut<'a, B, R>(
&'a mut self,
func: impl FnOnce(&'a mut B) -> R,
) -> R
fn pipe_borrow_mut<'a, B, R>( &'a mut self, func: impl FnOnce(&'a mut B) -> R, ) -> R
Source§fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
self, then passes self.as_ref() into the pipe function.Source§fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
self, then passes self.as_mut() into the pipe
function.Source§fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
self, then passes self.deref() into the pipe function.Source§impl<T> Pointable for T
impl<T> Pointable for T
Source§impl<T> PolicyExt for Twhere
T: ?Sized,
impl<T> PolicyExt for Twhere
T: ?Sized,
Source§impl<T> Tap for T
impl<T> Tap for T
Source§fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
Borrow<B> of a value. Read moreSource§fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
BorrowMut<B> of a value. Read moreSource§fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
AsRef<R> view of a value. Read moreSource§fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
AsMut<R> view of a value. Read moreSource§fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
Deref::Target of a value. Read moreSource§fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
Deref::Target of a value. Read moreSource§fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
.tap() only in debug builds, and is erased in release builds.Source§fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
.tap_mut() only in debug builds, and is erased in release
builds.Source§fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
.tap_borrow() only in debug builds, and is erased in release
builds.Source§fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
.tap_borrow_mut() only in debug builds, and is erased in release
builds.Source§fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
.tap_ref() only in debug builds, and is erased in release
builds.Source§fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
.tap_ref_mut() only in debug builds, and is erased in release
builds.Source§fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
.tap_deref() only in debug builds, and is erased in release
builds.