Languages: δΈζ
A professional, type-safe, and feature-rich Java SDK for the Hyperliquid L1, designed for high-performance trading and data streaming.
This SDK provides a comprehensive, pure Java solution for interacting with the Hyperliquid decentralized exchange. It empowers developers to build sophisticated trading bots, data analysis tools, and platform integrations with ease and confidence.
- π High Performance: Optimized for low-latency trading with efficient data handling.
- π‘οΈ Type-Safe: Fluent builders and strongly-typed models prevent common errors and enhance code clarity.
- π Secure by Design: Robust EIP-712 signing and clear wallet management patterns.
- πΌ Multi-Wallet Management: Seamlessly manage and switch between multiple trading accounts (Main & API Wallets).
- π Powerful WebSocket: Auto-reconnect, exponential backoff, and type-safe real-time data subscriptions.
- π§© Fluent & Intuitive API: A clean, modern API designed for an excellent developer experience.
- Requirements: JDK
21+, Maven or Gradle. - Maven:
<dependency>
<groupId>io.github.heiye115</groupId>
<artifactId>hyperliquid-java-sdk</artifactId>
<version>0.2.6</version> <!-- Replace with the latest version -->
</dependency>- Gradle (Groovy):
implementation 'io.github.heiye115:hyperliquid-java-sdk:0.2.6' // Replace with the latest versionGet up and running in minutes with this complete, runnable example.
Prerequisites:
- Have a Hyperliquid account. For this example, use the Testnet.
- Obtain your wallet's private key.
- IMPORTANT: Store your private key securely. The recommended way is to use an environment variable.
export HYPERLIQUID_TESTNET_PRIVATE_KEY="0xYourPrivateKey"This example demonstrates how to:
- Build the client.
- Query market data (
l2Book). - Place a limit order (
order). - Handle potential API errors (
HypeError).
public class QuickStart {
private static final Logger LOGGER = LoggerFactory.getLogger(QuickStart.class);
public static void main(String[] args) {
// 1. Recommended: Use API Wallet for better security
// API Wallet: Sub-wallet authorized by main wallet, with limited permissions, main private key not exposed
String primaryWalletAddress = ""; // Primary wallet address
String apiWalletPrivateKey = ""; // API wallet private key
// 2. Build the client for the testnet
HyperliquidClient client = HyperliquidClient.builder()
.testNetUrl() // Use the testnet environment
.addApiWallet(primaryWalletAddress, apiWalletPrivateKey)
.build();
Info info = client.getInfo();
Exchange exchange = client.getExchange(); // Get the exchange instance for the added wallet
// 3. Query market data: Get the L2 book for "ETH"
try {
LOGGER.info("Querying L2 book for ETH...");
L2Book l2Book = info.l2Book("ETH");
// Print the top 3 levels of bids and asks
LOGGER.info("Successfully retrieved L2 book for {}:", l2Book.getCoin());
l2Book.getLevels().get(0).subList(0, 3).forEach(level ->
LOGGER.info(" Ask - Price: {}, Size: {}", level.getPx(), level.getSz())
);
l2Book.getLevels().get(1).subList(0, 3).forEach(level ->
LOGGER.info(" Bid - Price: {}, Size: {}", level.getPx(), level.getSz())
);
} catch (HypeError e) {
LOGGER.error("Failed to query L2 book. Message: {}", e.getMessage());
}
// 4. Execute a trade: Create a limit buy order for ETH
try {
LOGGER.info("Placing a limit buy order for ETH...");
// Create a limit buy order for 0.01 ETH at a price of $1500
OrderRequest orderRequest = OrderRequest.builder()
.perp("ETH") // Perpetual contract for ETH
.buy("0.01") // Buying 0.01 ETH
.limitPrice("1500") // Limit price for the order
.gtc() // Good Till Cancel (GTC) order
.build();
Order order = exchange.order(orderRequest);
LOGGER.info("Order placed successfully. Response: {}", JSONUtil.writeValueAsString(order));
} catch (HypeError | JsonProcessingException e) {
// Example of handling a specific error, e.g., insufficient margin
LOGGER.error("Order placement failed. Message: {}", e.getMessage(), e);
}
}
}The HyperliquidClient.builder() provides a fluent API for configuration.
// Full configuration example
HyperliquidClient client = HyperliquidClient.builder()
// Select network (or provide a custom URL)
.testNetUrl() // or .baseUrl("https://api.hyperliquid.xyz")
// --- Wallet Management ---
// Option 1: Add a single main private key
.addPrivateKey("0xYourMainPrivateKey")
// Option 2: Add multiple API Wallets (recommended for security)
// An API wallet is a sub-wallet authorized by your main wallet.
.addApiWallet("0xYourMainAddress1", "0xYourApiPrivateKey1")
.addApiWallet("0xYourMainAddress2", "0xYourApiPrivateKey2")
// --- Performance ---
// Cache warm-up is enabled by default; disable only when startup latency is critical
// .disableAutoWarmUpCache()
// --- (optional)Network ---
// Set custom HTTP client
.okHttpClient(customClient)
// Set timeout (seconds) for the underlying OkHttpClient (applies to connect/read/write)
.timeout(15)
// Build the immutable client instance
.build();
// Accessing exchange instances for different wallets
Exchange exchange1 = client.getExchange("0xYourMainAddress1");
Exchange exchange2 = client.getExchange("0xYourMainAddress2");The Info API provides access to all public market data and private user data.
Get User State:
UserState userState = info.userState("0xYourAddress");
LOGGER.info("Total margin usage: {}", userState.getMarginSummary().getTotalMarginUsed());Get Open Orders:
List<OpenOrder> openOrders = info.openOrders("0xYourAddress");
LOGGER.info("User has {} open orders.", openOrders.size());Get Market Metadata:
Meta meta = info.meta();
// Find details for a specific asset
meta.getUniverse().stream()
.filter(asset -> "ETH".equals(asset.getName()))
.findFirst()
.ifPresent(ethAsset -> LOGGER.info("Max leverage for ETH: {}", ethAsset.getMaxLeverage()));The Exchange API handles all state-changing actions, which require signing.
Building Orders with OrderRequest.Builder:
The builder provides a type-safe way to construct complex orders.
// Stop-Loss Market Order
OrderRequest slOrder = OrderRequest.builder()
.perp("ETH")
.sell("0.01") // Direction to close a long position
.stopBelow("2900") // Trigger when price drops below 2900
.marketTrigger() // Execute as a market order when triggered
.reduceOnly() // Ensures it only reduces a position
.build();
// Take-Profit Limit Order
OrderRequest tpOrder = OrderRequest.builder()
.perp("ETH")
.sell("0.01")
.stopAbove("3100") // Trigger when price rises above 3100
.limitPrice("3100") // Execute as a limit order
.reduceOnly()
.build();Bulk Orders: Place multiple orders in a single atomic request.
List<OrderRequest> orders = List.of(slOrder, tpOrder);
JsonNode bulkResponse = exchange.bulkOrders(orders);Cancel an Order:
// Assumes 'oid' is the ID of an open order
JsonNode cancelResponse = exchange.cancel("ETH", oid);Update Leverage:
UpdateLeverage leverageResponse = exchange.updateLeverage("ETH", 20, false); // 20x leverage, non-cross-marginSubscribe to real-time data streams. The WebsocketManager handles connection stability automatically.
// Define a subscription for order updates events
OrderUpdatesSubscription orderUpdatesSubscription = OrderUpdatesSubscription.of("0x....");
// Subscribe with a message handler and an error handler
info.subscribe(orderUpdatesSubscription,
// OnMessage callback
(message) -> {
LOGGER.info("Received WebSocket message: {}", message);
// Add your logic to process the message
}
);
// To unsubscribe
// info.unsubscribe(orderUpdatesSubscription);All SDK-specific errors are thrown as HypeError. This includes API errors from the server and client-side validation errors.
try {
// Some exchange operation
} catch (HypeError e) {
LOGGER.error("An error occurred. Code: [{}], Message: [{}]", e.getCode(), e.getMessage());
// You can also access the original JSON error response if available
if (e.getJsonNode() != null) {
LOGGER.error("Raw error response: {}", e.getJsonNode().toString());
}
}Contributions are welcome! Please read our Contributing Guidelines to get started. You can help by reporting issues, suggesting features, or submitting pull requests.
This project is licensed under the Apache 2.0 License. See the LICENSE file for details.
Contact the author via:
- WeChat: heiye5050
- Email: heiye115@gmail.com
- Telegram: @heiye5050