hyperliquid-sdk 0.7.2__tar.gz → 0.7.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {hyperliquid_sdk-0.7.2 → hyperliquid_sdk-0.7.3}/PKG-INFO +134 -1
- {hyperliquid_sdk-0.7.2 → hyperliquid_sdk-0.7.3}/README.md +133 -0
- {hyperliquid_sdk-0.7.2 → hyperliquid_sdk-0.7.3}/hyperliquid_sdk/__init__.py +1 -1
- {hyperliquid_sdk-0.7.2 → hyperliquid_sdk-0.7.3}/pyproject.toml +1 -1
- {hyperliquid_sdk-0.7.2 → hyperliquid_sdk-0.7.3}/.gitignore +0 -0
- {hyperliquid_sdk-0.7.2 → hyperliquid_sdk-0.7.3}/LICENSE +0 -0
- {hyperliquid_sdk-0.7.2 → hyperliquid_sdk-0.7.3}/hyperliquid_sdk/client.py +0 -0
- {hyperliquid_sdk-0.7.2 → hyperliquid_sdk-0.7.3}/hyperliquid_sdk/errors.py +0 -0
- {hyperliquid_sdk-0.7.2 → hyperliquid_sdk-0.7.3}/hyperliquid_sdk/evm.py +0 -0
- {hyperliquid_sdk-0.7.2 → hyperliquid_sdk-0.7.3}/hyperliquid_sdk/evm_stream.py +0 -0
- {hyperliquid_sdk-0.7.2 → hyperliquid_sdk-0.7.3}/hyperliquid_sdk/grpc_stream.py +0 -0
- {hyperliquid_sdk-0.7.2 → hyperliquid_sdk-0.7.3}/hyperliquid_sdk/hypercore.py +0 -0
- {hyperliquid_sdk-0.7.2 → hyperliquid_sdk-0.7.3}/hyperliquid_sdk/info.py +0 -0
- {hyperliquid_sdk-0.7.2 → hyperliquid_sdk-0.7.3}/hyperliquid_sdk/order.py +0 -0
- {hyperliquid_sdk-0.7.2 → hyperliquid_sdk-0.7.3}/hyperliquid_sdk/proto/__init__.py +0 -0
- {hyperliquid_sdk-0.7.2 → hyperliquid_sdk-0.7.3}/hyperliquid_sdk/proto/orderbook.proto +0 -0
- {hyperliquid_sdk-0.7.2 → hyperliquid_sdk-0.7.3}/hyperliquid_sdk/proto/orderbook_pb2.py +0 -0
- {hyperliquid_sdk-0.7.2 → hyperliquid_sdk-0.7.3}/hyperliquid_sdk/proto/orderbook_pb2_grpc.py +0 -0
- {hyperliquid_sdk-0.7.2 → hyperliquid_sdk-0.7.3}/hyperliquid_sdk/proto/streaming.proto +0 -0
- {hyperliquid_sdk-0.7.2 → hyperliquid_sdk-0.7.3}/hyperliquid_sdk/proto/streaming_pb2.py +0 -0
- {hyperliquid_sdk-0.7.2 → hyperliquid_sdk-0.7.3}/hyperliquid_sdk/proto/streaming_pb2_grpc.py +0 -0
- {hyperliquid_sdk-0.7.2 → hyperliquid_sdk-0.7.3}/hyperliquid_sdk/py.typed +0 -0
- {hyperliquid_sdk-0.7.2 → hyperliquid_sdk-0.7.3}/hyperliquid_sdk/websocket.py +0 -0
- {hyperliquid_sdk-0.7.2 → hyperliquid_sdk-0.7.3}/tests/__init__.py +0 -0
- {hyperliquid_sdk-0.7.2 → hyperliquid_sdk-0.7.3}/tests/conftest.py +0 -0
- {hyperliquid_sdk-0.7.2 → hyperliquid_sdk-0.7.3}/tests/test_hypercore.py +0 -0
- {hyperliquid_sdk-0.7.2 → hyperliquid_sdk-0.7.3}/tests/test_info.py +0 -0
- {hyperliquid_sdk-0.7.2 → hyperliquid_sdk-0.7.3}/tests/test_order.py +0 -0
- {hyperliquid_sdk-0.7.2 → hyperliquid_sdk-0.7.3}/tests/test_sdk.py +0 -0
- {hyperliquid_sdk-0.7.2 → hyperliquid_sdk-0.7.3}/tests/test_websocket.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: hyperliquid-sdk
|
|
3
|
-
Version: 0.7.
|
|
3
|
+
Version: 0.7.3
|
|
4
4
|
Summary: Community SDK for Hyperliquid. One line to place orders, zero ceremony. HyperCore, HyperEVM, WebSocket and gRPC streams. Not affiliated with Hyperliquid Foundation.
|
|
5
5
|
Project-URL: Homepage, https://hyperliquidapi.com
|
|
6
6
|
Project-URL: Documentation, https://www.quicknode.com/docs/hyperliquid/api-overview
|
|
@@ -429,6 +429,139 @@ sdk.schedule_cancel(int(time.time() * 1000) + 60000)
|
|
|
429
429
|
sdk.close_position("BTC") # Close entire position
|
|
430
430
|
```
|
|
431
431
|
|
|
432
|
+
### Querying Open Orders by Trading Pair
|
|
433
|
+
|
|
434
|
+
```python
|
|
435
|
+
# Get all open orders
|
|
436
|
+
result = sdk.open_orders()
|
|
437
|
+
print(f"Total open orders: {len(result['orders'])}")
|
|
438
|
+
|
|
439
|
+
# Order fields: coin, limitPx (price), sz (size), side, oid, timestamp,
|
|
440
|
+
# orderType, tif, cloid, reduceOnly
|
|
441
|
+
for order in result['orders']:
|
|
442
|
+
print(f"{order['coin']} {order['side']} {order['sz']}@{order['limitPx']}")
|
|
443
|
+
|
|
444
|
+
# Filter by trading pair
|
|
445
|
+
btc_orders = [o for o in result['orders'] if o['coin'] == 'BTC']
|
|
446
|
+
for order in btc_orders:
|
|
447
|
+
print(f" {order['side']} {order['sz']} @ {order['limitPx']} | "
|
|
448
|
+
f"type={order['orderType']} tif={order['tif']} oid={order['oid']}")
|
|
449
|
+
|
|
450
|
+
# For enhanced data (triggers, children), use frontend_open_orders()
|
|
451
|
+
enhanced = sdk.info().frontend_open_orders(sdk.address)
|
|
452
|
+
```
|
|
453
|
+
|
|
454
|
+
### Partial Position Close by Percentage
|
|
455
|
+
|
|
456
|
+
`close_position()` closes the entire position. To close a percentage, read the current size and place a reduce-only market order for the desired amount:
|
|
457
|
+
|
|
458
|
+
```python
|
|
459
|
+
def close_percentage(sdk, coin: str, percent: float):
|
|
460
|
+
"""Close a percentage (0-100) of an open position."""
|
|
461
|
+
state = sdk.info().clearinghouse_state(sdk.address)
|
|
462
|
+
position = next(
|
|
463
|
+
(p for p in state['assetPositions'] if p['position']['coin'] == coin), None
|
|
464
|
+
)
|
|
465
|
+
if position is None:
|
|
466
|
+
raise ValueError(f"No open position for {coin}")
|
|
467
|
+
|
|
468
|
+
# szi is signed: positive = long, negative = short
|
|
469
|
+
szi = float(position['position']['szi'])
|
|
470
|
+
# Note: round close_size to asset's size decimals in production
|
|
471
|
+
close_size = abs(szi) * (percent / 100)
|
|
472
|
+
|
|
473
|
+
if szi > 0:
|
|
474
|
+
# Long position: sell to close
|
|
475
|
+
sdk.sell(coin, size=close_size, tif="market", reduce_only=True)
|
|
476
|
+
else:
|
|
477
|
+
# Short position: buy to close
|
|
478
|
+
sdk.buy(coin, size=close_size, tif="market", reduce_only=True)
|
|
479
|
+
|
|
480
|
+
# Close 50% of BTC position
|
|
481
|
+
close_percentage(sdk, "BTC", 50)
|
|
482
|
+
```
|
|
483
|
+
|
|
484
|
+
### Batch Cancel with Partial Failure Handling
|
|
485
|
+
|
|
486
|
+
Cancel all orders for an asset in one call:
|
|
487
|
+
|
|
488
|
+
```python
|
|
489
|
+
# Cancel all orders for a specific asset
|
|
490
|
+
sdk.cancel_all("BTC")
|
|
491
|
+
|
|
492
|
+
# Cancel by client order ID (for CLOID-tracked orders)
|
|
493
|
+
sdk.cancel_by_cloid("0xmycloid...", "BTC")
|
|
494
|
+
```
|
|
495
|
+
|
|
496
|
+
Or cancel selectively with per-order error handling:
|
|
497
|
+
|
|
498
|
+
```python
|
|
499
|
+
from hyperliquid_sdk import HyperliquidError
|
|
500
|
+
|
|
501
|
+
# Get open orders
|
|
502
|
+
result = sdk.open_orders()
|
|
503
|
+
|
|
504
|
+
# Cancel specific orders with per-order error handling
|
|
505
|
+
target_orders = [o for o in result['orders']
|
|
506
|
+
if o['coin'] == 'BTC' and float(o['limitPx']) < 50000]
|
|
507
|
+
failures = []
|
|
508
|
+
for order in target_orders:
|
|
509
|
+
try:
|
|
510
|
+
sdk.cancel(order['oid'], order['coin'])
|
|
511
|
+
except HyperliquidError as e:
|
|
512
|
+
failures.append({'oid': order['oid'], 'error': str(e)})
|
|
513
|
+
|
|
514
|
+
if failures:
|
|
515
|
+
print(f"Failed to cancel {len(failures)} orders: {failures}")
|
|
516
|
+
```
|
|
517
|
+
|
|
518
|
+
### Resilient Order Placement
|
|
519
|
+
|
|
520
|
+
Use client order IDs (CLOIDs) for idempotent orders and categorize errors for retry logic:
|
|
521
|
+
|
|
522
|
+
```python
|
|
523
|
+
import uuid
|
|
524
|
+
import time
|
|
525
|
+
import random
|
|
526
|
+
from hyperliquid_sdk import (
|
|
527
|
+
Order, HyperliquidError, RateLimitError, InvalidNonceError,
|
|
528
|
+
DuplicateOrderError, GeoBlockedError, InsufficientMarginError,
|
|
529
|
+
ValidationError, SignatureError, MaxOrdersError,
|
|
530
|
+
)
|
|
531
|
+
|
|
532
|
+
# Set a CLOID for idempotency — the exchange rejects duplicates
|
|
533
|
+
cloid = "0x" + uuid.uuid4().hex
|
|
534
|
+
order = sdk.order(Order.buy("BTC").size(0.001).price(65000).gtc().cloid(cloid))
|
|
535
|
+
|
|
536
|
+
# Error categories:
|
|
537
|
+
# Transient (retry): RateLimitError, InvalidNonceError
|
|
538
|
+
# Permanent (fail): GeoBlockedError, InsufficientMarginError, ValidationError,
|
|
539
|
+
# SignatureError, MaxOrdersError
|
|
540
|
+
# Already done: DuplicateOrderError (order already placed)
|
|
541
|
+
|
|
542
|
+
TRANSIENT_ERRORS = (RateLimitError, InvalidNonceError)
|
|
543
|
+
|
|
544
|
+
def place_with_retry(sdk, order_builder, max_retries=3):
|
|
545
|
+
"""Place an order with exponential backoff and idempotency."""
|
|
546
|
+
cloid = "0x" + uuid.uuid4().hex
|
|
547
|
+
order_builder = order_builder.cloid(cloid)
|
|
548
|
+
|
|
549
|
+
for attempt in range(max_retries):
|
|
550
|
+
try:
|
|
551
|
+
return sdk.order(order_builder)
|
|
552
|
+
except DuplicateOrderError:
|
|
553
|
+
return None # Order already went through
|
|
554
|
+
except TRANSIENT_ERRORS as e:
|
|
555
|
+
if attempt == max_retries - 1:
|
|
556
|
+
raise
|
|
557
|
+
wait = (2 ** attempt) + random.random()
|
|
558
|
+
time.sleep(wait)
|
|
559
|
+
|
|
560
|
+
# Timeout configuration on SDK constructor
|
|
561
|
+
from hyperliquid_sdk import HyperliquidSDK
|
|
562
|
+
sdk = HyperliquidSDK(endpoint, private_key="0x...", timeout=30)
|
|
563
|
+
```
|
|
564
|
+
|
|
432
565
|
### Leverage & Margin
|
|
433
566
|
|
|
434
567
|
```python
|
|
@@ -388,6 +388,139 @@ sdk.schedule_cancel(int(time.time() * 1000) + 60000)
|
|
|
388
388
|
sdk.close_position("BTC") # Close entire position
|
|
389
389
|
```
|
|
390
390
|
|
|
391
|
+
### Querying Open Orders by Trading Pair
|
|
392
|
+
|
|
393
|
+
```python
|
|
394
|
+
# Get all open orders
|
|
395
|
+
result = sdk.open_orders()
|
|
396
|
+
print(f"Total open orders: {len(result['orders'])}")
|
|
397
|
+
|
|
398
|
+
# Order fields: coin, limitPx (price), sz (size), side, oid, timestamp,
|
|
399
|
+
# orderType, tif, cloid, reduceOnly
|
|
400
|
+
for order in result['orders']:
|
|
401
|
+
print(f"{order['coin']} {order['side']} {order['sz']}@{order['limitPx']}")
|
|
402
|
+
|
|
403
|
+
# Filter by trading pair
|
|
404
|
+
btc_orders = [o for o in result['orders'] if o['coin'] == 'BTC']
|
|
405
|
+
for order in btc_orders:
|
|
406
|
+
print(f" {order['side']} {order['sz']} @ {order['limitPx']} | "
|
|
407
|
+
f"type={order['orderType']} tif={order['tif']} oid={order['oid']}")
|
|
408
|
+
|
|
409
|
+
# For enhanced data (triggers, children), use frontend_open_orders()
|
|
410
|
+
enhanced = sdk.info().frontend_open_orders(sdk.address)
|
|
411
|
+
```
|
|
412
|
+
|
|
413
|
+
### Partial Position Close by Percentage
|
|
414
|
+
|
|
415
|
+
`close_position()` closes the entire position. To close a percentage, read the current size and place a reduce-only market order for the desired amount:
|
|
416
|
+
|
|
417
|
+
```python
|
|
418
|
+
def close_percentage(sdk, coin: str, percent: float):
|
|
419
|
+
"""Close a percentage (0-100) of an open position."""
|
|
420
|
+
state = sdk.info().clearinghouse_state(sdk.address)
|
|
421
|
+
position = next(
|
|
422
|
+
(p for p in state['assetPositions'] if p['position']['coin'] == coin), None
|
|
423
|
+
)
|
|
424
|
+
if position is None:
|
|
425
|
+
raise ValueError(f"No open position for {coin}")
|
|
426
|
+
|
|
427
|
+
# szi is signed: positive = long, negative = short
|
|
428
|
+
szi = float(position['position']['szi'])
|
|
429
|
+
# Note: round close_size to asset's size decimals in production
|
|
430
|
+
close_size = abs(szi) * (percent / 100)
|
|
431
|
+
|
|
432
|
+
if szi > 0:
|
|
433
|
+
# Long position: sell to close
|
|
434
|
+
sdk.sell(coin, size=close_size, tif="market", reduce_only=True)
|
|
435
|
+
else:
|
|
436
|
+
# Short position: buy to close
|
|
437
|
+
sdk.buy(coin, size=close_size, tif="market", reduce_only=True)
|
|
438
|
+
|
|
439
|
+
# Close 50% of BTC position
|
|
440
|
+
close_percentage(sdk, "BTC", 50)
|
|
441
|
+
```
|
|
442
|
+
|
|
443
|
+
### Batch Cancel with Partial Failure Handling
|
|
444
|
+
|
|
445
|
+
Cancel all orders for an asset in one call:
|
|
446
|
+
|
|
447
|
+
```python
|
|
448
|
+
# Cancel all orders for a specific asset
|
|
449
|
+
sdk.cancel_all("BTC")
|
|
450
|
+
|
|
451
|
+
# Cancel by client order ID (for CLOID-tracked orders)
|
|
452
|
+
sdk.cancel_by_cloid("0xmycloid...", "BTC")
|
|
453
|
+
```
|
|
454
|
+
|
|
455
|
+
Or cancel selectively with per-order error handling:
|
|
456
|
+
|
|
457
|
+
```python
|
|
458
|
+
from hyperliquid_sdk import HyperliquidError
|
|
459
|
+
|
|
460
|
+
# Get open orders
|
|
461
|
+
result = sdk.open_orders()
|
|
462
|
+
|
|
463
|
+
# Cancel specific orders with per-order error handling
|
|
464
|
+
target_orders = [o for o in result['orders']
|
|
465
|
+
if o['coin'] == 'BTC' and float(o['limitPx']) < 50000]
|
|
466
|
+
failures = []
|
|
467
|
+
for order in target_orders:
|
|
468
|
+
try:
|
|
469
|
+
sdk.cancel(order['oid'], order['coin'])
|
|
470
|
+
except HyperliquidError as e:
|
|
471
|
+
failures.append({'oid': order['oid'], 'error': str(e)})
|
|
472
|
+
|
|
473
|
+
if failures:
|
|
474
|
+
print(f"Failed to cancel {len(failures)} orders: {failures}")
|
|
475
|
+
```
|
|
476
|
+
|
|
477
|
+
### Resilient Order Placement
|
|
478
|
+
|
|
479
|
+
Use client order IDs (CLOIDs) for idempotent orders and categorize errors for retry logic:
|
|
480
|
+
|
|
481
|
+
```python
|
|
482
|
+
import uuid
|
|
483
|
+
import time
|
|
484
|
+
import random
|
|
485
|
+
from hyperliquid_sdk import (
|
|
486
|
+
Order, HyperliquidError, RateLimitError, InvalidNonceError,
|
|
487
|
+
DuplicateOrderError, GeoBlockedError, InsufficientMarginError,
|
|
488
|
+
ValidationError, SignatureError, MaxOrdersError,
|
|
489
|
+
)
|
|
490
|
+
|
|
491
|
+
# Set a CLOID for idempotency — the exchange rejects duplicates
|
|
492
|
+
cloid = "0x" + uuid.uuid4().hex
|
|
493
|
+
order = sdk.order(Order.buy("BTC").size(0.001).price(65000).gtc().cloid(cloid))
|
|
494
|
+
|
|
495
|
+
# Error categories:
|
|
496
|
+
# Transient (retry): RateLimitError, InvalidNonceError
|
|
497
|
+
# Permanent (fail): GeoBlockedError, InsufficientMarginError, ValidationError,
|
|
498
|
+
# SignatureError, MaxOrdersError
|
|
499
|
+
# Already done: DuplicateOrderError (order already placed)
|
|
500
|
+
|
|
501
|
+
TRANSIENT_ERRORS = (RateLimitError, InvalidNonceError)
|
|
502
|
+
|
|
503
|
+
def place_with_retry(sdk, order_builder, max_retries=3):
|
|
504
|
+
"""Place an order with exponential backoff and idempotency."""
|
|
505
|
+
cloid = "0x" + uuid.uuid4().hex
|
|
506
|
+
order_builder = order_builder.cloid(cloid)
|
|
507
|
+
|
|
508
|
+
for attempt in range(max_retries):
|
|
509
|
+
try:
|
|
510
|
+
return sdk.order(order_builder)
|
|
511
|
+
except DuplicateOrderError:
|
|
512
|
+
return None # Order already went through
|
|
513
|
+
except TRANSIENT_ERRORS as e:
|
|
514
|
+
if attempt == max_retries - 1:
|
|
515
|
+
raise
|
|
516
|
+
wait = (2 ** attempt) + random.random()
|
|
517
|
+
time.sleep(wait)
|
|
518
|
+
|
|
519
|
+
# Timeout configuration on SDK constructor
|
|
520
|
+
from hyperliquid_sdk import HyperliquidSDK
|
|
521
|
+
sdk = HyperliquidSDK(endpoint, private_key="0x...", timeout=30)
|
|
522
|
+
```
|
|
523
|
+
|
|
391
524
|
### Leverage & Margin
|
|
392
525
|
|
|
393
526
|
```python
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "hyperliquid-sdk"
|
|
7
|
-
version = "0.7.
|
|
7
|
+
version = "0.7.3"
|
|
8
8
|
description = "Community SDK for Hyperliquid. One line to place orders, zero ceremony. HyperCore, HyperEVM, WebSocket and gRPC streams. Not affiliated with Hyperliquid Foundation."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "MIT"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|