Skip to content

Commit

Permalink
Version 0.1.8
Browse files Browse the repository at this point in the history
  • Loading branch information
traderben committed May 16, 2023
1 parent 67177e4 commit 5f4940d
Show file tree
Hide file tree
Showing 16 changed files with 165 additions and 64 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ vim examples/config.json
python examples/basic_order.py
```

## Getting started with development
## Getting started with contributing to this repo

1. Download `Poetry`: https://python-poetry.org/. Note that in the install script you might have to set `symlinks=True` in `venv.EnvBuilder`.

Expand Down
4 changes: 2 additions & 2 deletions assets/images/coverage.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
14 changes: 7 additions & 7 deletions examples/basic_adding.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,24 @@
import time

import eth_account
import utils
from eth_account.signers.local import LocalAccount

import utils
from hyperliquid.exchange import Exchange
from hyperliquid.info import Info
from hyperliquid.utils import constants
from hyperliquid.utils.signing import get_timestamp_ms
from hyperliquid.utils.types import (
SIDES,
Dict,
L2BookMsg,
L2BookSubscription,
UserEventsMsg,
Literal,
Optional,
Side,
SIDES,
Dict,
TypedDict,
Optional,
Literal,
Union,
UserEventsMsg,
)

# How far from the best bid and offer this strategy ideally places orders. Currently set to .3%
Expand Down Expand Up @@ -88,7 +88,7 @@ def on_book_update(self, book_msg: L2BookMsg) -> None:
# If a resting order exists, maybe cancel it
provide_state = self.provide_state[side]
if provide_state["type"] == "resting":
distance = abs((ideal_price - provide_state["px"]))
distance = abs(ideal_price - provide_state["px"])
if distance > ALLOWABLE_DEVIATION * ideal_distance:
oid = provide_state["oid"]
print(
Expand Down
40 changes: 40 additions & 0 deletions examples/basic_leverage_adjustment.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import json

import eth_account
import utils
from eth_account.signers.local import LocalAccount

from hyperliquid.exchange import Exchange
from hyperliquid.info import Info
from hyperliquid.utils import constants


def main():
config = utils.get_config()
account: LocalAccount = eth_account.Account.from_key(config["secret_key"])
print("Running with account address:", account.address)
info = Info(constants.TESTNET_API_URL, skip_ws=True)
exchange = Exchange(account, constants.TESTNET_API_URL)

# Get the user state and print out leverage information for ETH
user_state = info.user_state(account.address)
print("Current leverage for ETH:")
print(json.dumps(user_state["assetPositions"][exchange.coin_to_asset["ETH"]]["position"]["leverage"], indent=2))

# Set the ETH leverage to 21x (cross margin)
print(exchange.update_leverage(21, "ETH"))

# Set the ETH leverage to 22x (isolated margin)
print(exchange.update_leverage(21, "ETH", False))

# Add 1 dollar of extra margin to the ETH position
print(exchange.update_isolated_margin(1, "ETH"))

# Get the user state and print out the final leverage information after our changes
user_state = info.user_state(account.address)
print("Current leverage for ETH:")
print(json.dumps(user_state["assetPositions"][exchange.coin_to_asset["ETH"]]["position"]["leverage"], indent=2))


if __name__ == "__main__":
main()
7 changes: 4 additions & 3 deletions examples/basic_order.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
from eth_account.signers.local import LocalAccount
import eth_account
import json

import eth_account
import utils
from eth_account.signers.local import LocalAccount

from hyperliquid.info import Info
from hyperliquid.exchange import Exchange
from hyperliquid.info import Info
from hyperliquid.utils import constants


Expand Down
7 changes: 4 additions & 3 deletions examples/basic_vault.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
from eth_account.signers.local import LocalAccount
import eth_account
import json

import eth_account
import utils
from eth_account.signers.local import LocalAccount

from hyperliquid.info import Info
from hyperliquid.exchange import Exchange
from hyperliquid.info import Info
from hyperliquid.utils import constants


Expand Down
4 changes: 2 additions & 2 deletions examples/cancel_open_orders.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
from eth_account.signers.local import LocalAccount
import eth_account
import utils
from eth_account.signers.local import LocalAccount

from hyperliquid.info import Info
from hyperliquid.exchange import Exchange
from hyperliquid.info import Info
from hyperliquid.utils import constants


Expand Down
11 changes: 6 additions & 5 deletions examples/rounding.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,14 @@
For example, if szDecimals = 3 then 1.001 is a valid size but 1.0001 is not.
You can find the szDecimals for an asset by making a meta request to the info endpoint
"""
from eth_account.signers.local import LocalAccount
import eth_account
import json

import eth_account
import utils
from eth_account.signers.local import LocalAccount

from hyperliquid.info import Info
from hyperliquid.exchange import Exchange
from hyperliquid.info import Info
from hyperliquid.utils import constants


Expand All @@ -29,8 +30,8 @@ def main():

# create a szDecimals map
sz_decimals = {}
for info in meta["universe"]:
sz_decimals[info["name"]] = info["szDecimals"]
for asset_info in meta["universe"]:
sz_decimals[asset_info["name"]] = asset_info["szDecimals"]

# For demonstration purposes we'll start with a price and size that have too many digits
sz = 12.345678
Expand Down
2 changes: 1 addition & 1 deletion examples/utils.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import os
import json
import os


def get_config():
Expand Down
104 changes: 76 additions & 28 deletions hyperliquid/exchange.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,17 @@
from hyperliquid.api import API
from hyperliquid.info import Info
from hyperliquid.utils.signing import (
OrderSpec,
order_spec_preprocessing,
order_grouping_to_number,
sign_l1_action,
ZERO_ADDRESS,
OrderSpec,
OrderType,
order_spec_to_order_wire,
float_to_usd_int,
get_timestamp_ms,
order_grouping_to_number,
order_spec_preprocessing,
order_spec_to_order_wire,
sign_l1_action,
)
from hyperliquid.utils.types import Meta, Any, Literal, Optional
from hyperliquid.utils.types import Any, Literal, Meta, Optional


class Exchange(API):
Expand All @@ -35,6 +36,16 @@ def __init__(
self.meta = meta
self.coin_to_asset = {asset_info["name"]: asset for (asset, asset_info) in enumerate(self.meta["universe"])}

def _post_action(self, action, signature, nonce):
payload = {
"action": action,
"nonce": nonce,
"signature": signature,
"vaultAddress": self.vault_address,
}
logging.debug(payload)
return self.post("/exchange", payload)

def order(
self, coin: str, is_buy: bool, sz: float, limit_px: float, order_type: OrderType, reduce_only: bool = False
) -> Any:
Expand All @@ -58,18 +69,16 @@ def order(
ZERO_ADDRESS if self.vault_address is None else self.vault_address,
timestamp,
)
payload = {
"action": {

return self._post_action(
{
"type": "order",
"grouping": grouping,
"orders": [order_spec_to_order_wire(order_spec)],
},
"nonce": timestamp,
"signature": signature,
"vaultAddress": self.vault_address,
}
logging.debug(payload)
return self.post("/exchange", payload)
signature,
timestamp,
)

def cancel(self, coin: str, oid: int) -> Any:
timestamp = get_timestamp_ms()
Expand All @@ -81,20 +90,59 @@ def cancel(self, coin: str, oid: int) -> Any:
ZERO_ADDRESS if self.vault_address is None else self.vault_address,
timestamp,
)
return self.post(
"/exchange",
return self._post_action(
{
"type": "cancel",
"cancels": [
{
"asset": asset,
"oid": oid,
}
],
},
signature,
timestamp,
)

def update_leverage(self, leverage: int, coin: str, is_cross: bool = True) -> Any:
timestamp = get_timestamp_ms()
asset = self.coin_to_asset[coin]
signature = sign_l1_action(
self.wallet,
["uint32", "bool", "uint32"],
[asset, is_cross, leverage],
ZERO_ADDRESS if self.vault_address is None else self.vault_address,
timestamp,
)
return self._post_action(
{
"action": {
"type": "cancel",
"cancels": [
{
"asset": asset,
"oid": oid,
}
],
},
"nonce": timestamp,
"signature": signature,
"vaultAddress": self.vault_address,
"type": "updateLeverage",
"asset": asset,
"isCross": is_cross,
"leverage": leverage,
},
signature,
timestamp,
)

def update_isolated_margin(self, amount: float, coin: str) -> Any:
timestamp = get_timestamp_ms()
asset = self.coin_to_asset[coin]
amount = float_to_usd_int(amount)
signature = sign_l1_action(
self.wallet,
["uint32", "bool", "int64"],
[asset, True, amount],
ZERO_ADDRESS if self.vault_address is None else self.vault_address,
timestamp,
)
return self._post_action(
{
"type": "updateIsolatedMargin",
"asset": asset,
"isBuy": True,
"ntli": amount,
},
signature,
timestamp,
)
2 changes: 1 addition & 1 deletion hyperliquid/info.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from hyperliquid.api import API
from hyperliquid.utils.types import Meta, Subscription, Any, cast, Callable
from hyperliquid.utils.types import Any, Callable, Meta, Subscription, cast
from hyperliquid.websocket_manager import WebsocketManager


Expand Down
15 changes: 12 additions & 3 deletions hyperliquid/utils/signing.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import time

from eth_abi import encode
from eth_account.messages import encode_structured_data
from eth_utils import keccak, to_hex

from hyperliquid.utils.types import TypedDict, Literal, Union, Any, Tuple
from hyperliquid.utils.types import Any, Literal, Tuple, TypedDict, Union

ZERO_ADDRESS = "0x0000000000000000000000000000000000000000"

Expand Down Expand Up @@ -137,9 +138,17 @@ def float_to_wire(x: float) -> str:


def float_to_int_for_hashing(x: float) -> int:
with_decimals = x * 10**8
return float_to_int(x, 8)


def float_to_usd_int(x: float) -> int:
return float_to_int(x, 6)


def float_to_int(x: float, power: int) -> int:
with_decimals = x * 10**power
if abs(round(with_decimals) - with_decimals) >= 1e-4:
raise ValueError("float_to_int_for_hashing causes rounding", x)
raise ValueError("float_to_int causes rounding", x)
return round(with_decimals)


Expand Down
4 changes: 2 additions & 2 deletions hyperliquid/utils/types.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import sys

if sys.version_info >= (3, 8):
from typing import TypedDict, Literal
from typing import Literal, TypedDict
else:
from typing_extensions import TypedDict, Literal

from typing import List, Union, Dict, Tuple, Any, Optional, cast, Callable, NamedTuple
from typing import Any, Callable, Dict, List, NamedTuple, Optional, Tuple, Union, cast

Any = Any
Option = Optional
Expand Down
7 changes: 4 additions & 3 deletions hyperliquid/websocket_manager.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import logging
from collections import defaultdict
import json
import logging
import threading
from collections import defaultdict

import websocket

from hyperliquid.utils.types import Subscription, WsMsg, Callable, Any, NamedTuple, Optional, List, Tuple, Dict
from hyperliquid.utils.types import Any, Callable, Dict, List, NamedTuple, Optional, Subscription, Tuple, WsMsg

ActiveSubscription = NamedTuple("ActiveSubscription", [("callback", Callable[[Any], None]), ("subscription_id", int)])

Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ build-backend = "poetry.core.masonry.api"

[tool.poetry]
name = "hyperliquid-python-sdk"
version = "0.1.7"
version = "0.1.8"
description = "SDK for Hyperliquid API trading with Python."
readme = "README.md"
authors = ["Hyperliquid <[email protected]>"]
Expand Down
Loading

0 comments on commit 5f4940d

Please sign in to comment.