Skip to content

Commit 5f4940d

Browse files
committed
Version 0.1.8
1 parent 67177e4 commit 5f4940d

File tree

16 files changed

+165
-64
lines changed

16 files changed

+165
-64
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ vim examples/config.json
3535
python examples/basic_order.py
3636
```
3737

38-
## Getting started with development
38+
## Getting started with contributing to this repo
3939

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

assets/images/coverage.svg

Lines changed: 2 additions & 2 deletions
Loading

examples/basic_adding.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,24 +5,24 @@
55
import time
66

77
import eth_account
8+
import utils
89
from eth_account.signers.local import LocalAccount
910

10-
import utils
1111
from hyperliquid.exchange import Exchange
1212
from hyperliquid.info import Info
1313
from hyperliquid.utils import constants
1414
from hyperliquid.utils.signing import get_timestamp_ms
1515
from hyperliquid.utils.types import (
16+
SIDES,
17+
Dict,
1618
L2BookMsg,
1719
L2BookSubscription,
18-
UserEventsMsg,
20+
Literal,
21+
Optional,
1922
Side,
20-
SIDES,
21-
Dict,
2223
TypedDict,
23-
Optional,
24-
Literal,
2524
Union,
25+
UserEventsMsg,
2626
)
2727

2828
# How far from the best bid and offer this strategy ideally places orders. Currently set to .3%
@@ -88,7 +88,7 @@ def on_book_update(self, book_msg: L2BookMsg) -> None:
8888
# If a resting order exists, maybe cancel it
8989
provide_state = self.provide_state[side]
9090
if provide_state["type"] == "resting":
91-
distance = abs((ideal_price - provide_state["px"]))
91+
distance = abs(ideal_price - provide_state["px"])
9292
if distance > ALLOWABLE_DEVIATION * ideal_distance:
9393
oid = provide_state["oid"]
9494
print(
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import json
2+
3+
import eth_account
4+
import utils
5+
from eth_account.signers.local import LocalAccount
6+
7+
from hyperliquid.exchange import Exchange
8+
from hyperliquid.info import Info
9+
from hyperliquid.utils import constants
10+
11+
12+
def main():
13+
config = utils.get_config()
14+
account: LocalAccount = eth_account.Account.from_key(config["secret_key"])
15+
print("Running with account address:", account.address)
16+
info = Info(constants.TESTNET_API_URL, skip_ws=True)
17+
exchange = Exchange(account, constants.TESTNET_API_URL)
18+
19+
# Get the user state and print out leverage information for ETH
20+
user_state = info.user_state(account.address)
21+
print("Current leverage for ETH:")
22+
print(json.dumps(user_state["assetPositions"][exchange.coin_to_asset["ETH"]]["position"]["leverage"], indent=2))
23+
24+
# Set the ETH leverage to 21x (cross margin)
25+
print(exchange.update_leverage(21, "ETH"))
26+
27+
# Set the ETH leverage to 22x (isolated margin)
28+
print(exchange.update_leverage(21, "ETH", False))
29+
30+
# Add 1 dollar of extra margin to the ETH position
31+
print(exchange.update_isolated_margin(1, "ETH"))
32+
33+
# Get the user state and print out the final leverage information after our changes
34+
user_state = info.user_state(account.address)
35+
print("Current leverage for ETH:")
36+
print(json.dumps(user_state["assetPositions"][exchange.coin_to_asset["ETH"]]["position"]["leverage"], indent=2))
37+
38+
39+
if __name__ == "__main__":
40+
main()

examples/basic_order.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1-
from eth_account.signers.local import LocalAccount
2-
import eth_account
31
import json
2+
3+
import eth_account
44
import utils
5+
from eth_account.signers.local import LocalAccount
56

6-
from hyperliquid.info import Info
77
from hyperliquid.exchange import Exchange
8+
from hyperliquid.info import Info
89
from hyperliquid.utils import constants
910

1011

examples/basic_vault.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1-
from eth_account.signers.local import LocalAccount
2-
import eth_account
31
import json
2+
3+
import eth_account
44
import utils
5+
from eth_account.signers.local import LocalAccount
56

6-
from hyperliquid.info import Info
77
from hyperliquid.exchange import Exchange
8+
from hyperliquid.info import Info
89
from hyperliquid.utils import constants
910

1011

examples/cancel_open_orders.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
from eth_account.signers.local import LocalAccount
21
import eth_account
32
import utils
3+
from eth_account.signers.local import LocalAccount
44

5-
from hyperliquid.info import Info
65
from hyperliquid.exchange import Exchange
6+
from hyperliquid.info import Info
77
from hyperliquid.utils import constants
88

99

examples/rounding.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,14 @@
77
For example, if szDecimals = 3 then 1.001 is a valid size but 1.0001 is not.
88
You can find the szDecimals for an asset by making a meta request to the info endpoint
99
"""
10-
from eth_account.signers.local import LocalAccount
11-
import eth_account
1210
import json
11+
12+
import eth_account
1313
import utils
14+
from eth_account.signers.local import LocalAccount
1415

15-
from hyperliquid.info import Info
1616
from hyperliquid.exchange import Exchange
17+
from hyperliquid.info import Info
1718
from hyperliquid.utils import constants
1819

1920

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

3031
# create a szDecimals map
3132
sz_decimals = {}
32-
for info in meta["universe"]:
33-
sz_decimals[info["name"]] = info["szDecimals"]
33+
for asset_info in meta["universe"]:
34+
sz_decimals[asset_info["name"]] = asset_info["szDecimals"]
3435

3536
# For demonstration purposes we'll start with a price and size that have too many digits
3637
sz = 12.345678

examples/utils.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import os
21
import json
2+
import os
33

44

55
def get_config():

hyperliquid/exchange.py

Lines changed: 76 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,17 @@
55
from hyperliquid.api import API
66
from hyperliquid.info import Info
77
from hyperliquid.utils.signing import (
8-
OrderSpec,
9-
order_spec_preprocessing,
10-
order_grouping_to_number,
11-
sign_l1_action,
128
ZERO_ADDRESS,
9+
OrderSpec,
1310
OrderType,
14-
order_spec_to_order_wire,
11+
float_to_usd_int,
1512
get_timestamp_ms,
13+
order_grouping_to_number,
14+
order_spec_preprocessing,
15+
order_spec_to_order_wire,
16+
sign_l1_action,
1617
)
17-
from hyperliquid.utils.types import Meta, Any, Literal, Optional
18+
from hyperliquid.utils.types import Any, Literal, Meta, Optional
1819

1920

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

39+
def _post_action(self, action, signature, nonce):
40+
payload = {
41+
"action": action,
42+
"nonce": nonce,
43+
"signature": signature,
44+
"vaultAddress": self.vault_address,
45+
}
46+
logging.debug(payload)
47+
return self.post("/exchange", payload)
48+
3849
def order(
3950
self, coin: str, is_buy: bool, sz: float, limit_px: float, order_type: OrderType, reduce_only: bool = False
4051
) -> Any:
@@ -58,18 +69,16 @@ def order(
5869
ZERO_ADDRESS if self.vault_address is None else self.vault_address,
5970
timestamp,
6071
)
61-
payload = {
62-
"action": {
72+
73+
return self._post_action(
74+
{
6375
"type": "order",
6476
"grouping": grouping,
6577
"orders": [order_spec_to_order_wire(order_spec)],
6678
},
67-
"nonce": timestamp,
68-
"signature": signature,
69-
"vaultAddress": self.vault_address,
70-
}
71-
logging.debug(payload)
72-
return self.post("/exchange", payload)
79+
signature,
80+
timestamp,
81+
)
7382

7483
def cancel(self, coin: str, oid: int) -> Any:
7584
timestamp = get_timestamp_ms()
@@ -81,20 +90,59 @@ def cancel(self, coin: str, oid: int) -> Any:
8190
ZERO_ADDRESS if self.vault_address is None else self.vault_address,
8291
timestamp,
8392
)
84-
return self.post(
85-
"/exchange",
93+
return self._post_action(
94+
{
95+
"type": "cancel",
96+
"cancels": [
97+
{
98+
"asset": asset,
99+
"oid": oid,
100+
}
101+
],
102+
},
103+
signature,
104+
timestamp,
105+
)
106+
107+
def update_leverage(self, leverage: int, coin: str, is_cross: bool = True) -> Any:
108+
timestamp = get_timestamp_ms()
109+
asset = self.coin_to_asset[coin]
110+
signature = sign_l1_action(
111+
self.wallet,
112+
["uint32", "bool", "uint32"],
113+
[asset, is_cross, leverage],
114+
ZERO_ADDRESS if self.vault_address is None else self.vault_address,
115+
timestamp,
116+
)
117+
return self._post_action(
86118
{
87-
"action": {
88-
"type": "cancel",
89-
"cancels": [
90-
{
91-
"asset": asset,
92-
"oid": oid,
93-
}
94-
],
95-
},
96-
"nonce": timestamp,
97-
"signature": signature,
98-
"vaultAddress": self.vault_address,
119+
"type": "updateLeverage",
120+
"asset": asset,
121+
"isCross": is_cross,
122+
"leverage": leverage,
99123
},
124+
signature,
125+
timestamp,
126+
)
127+
128+
def update_isolated_margin(self, amount: float, coin: str) -> Any:
129+
timestamp = get_timestamp_ms()
130+
asset = self.coin_to_asset[coin]
131+
amount = float_to_usd_int(amount)
132+
signature = sign_l1_action(
133+
self.wallet,
134+
["uint32", "bool", "int64"],
135+
[asset, True, amount],
136+
ZERO_ADDRESS if self.vault_address is None else self.vault_address,
137+
timestamp,
138+
)
139+
return self._post_action(
140+
{
141+
"type": "updateIsolatedMargin",
142+
"asset": asset,
143+
"isBuy": True,
144+
"ntli": amount,
145+
},
146+
signature,
147+
timestamp,
100148
)

0 commit comments

Comments
 (0)