Skip to content

Commit

Permalink
Version 0.1.11
Browse files Browse the repository at this point in the history
  • Loading branch information
traderben committed Sep 11, 2023
1 parent 6ddfbfb commit 063bf44
Show file tree
Hide file tree
Showing 7 changed files with 67 additions and 27 deletions.
3 changes: 1 addition & 2 deletions api/info/userstate.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,9 @@ paths:
totalMarginUsed: "0.0"
totalNtlPos: "0.0"
totalRawUsd: "0.0"
withdrawable: "0.0"
crossMarginSummary:
accountValue: "0.0"
totalMarginUsed: "0.0"
totalNtlPos: "0.0"
totalRawUsd: "0.0"
withdrawable: "0.0"
withdrawable: "0.0"
4 changes: 4 additions & 0 deletions hyperliquid/exchange.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ def bulk_orders(self, order_requests: List[OrderRequest]) -> Any:
[[order_spec_preprocessing(order_spec) for order_spec in order_specs], order_grouping_to_number(grouping)],
ZERO_ADDRESS if self.vault_address is None else self.vault_address,
timestamp,
self.base_url == MAINNET_API_URL,
)

return self._post_action(
Expand All @@ -118,6 +119,7 @@ def bulk_cancel(self, cancel_requests: List[CancelRequest]) -> Any:
[[(self.coin_to_asset[cancel["coin"]], cancel["oid"]) for cancel in cancel_requests]],
ZERO_ADDRESS if self.vault_address is None else self.vault_address,
timestamp,
self.base_url == MAINNET_API_URL,
)
return self._post_action(
{
Expand All @@ -143,6 +145,7 @@ def update_leverage(self, leverage: int, coin: str, is_cross: bool = True) -> An
[asset, is_cross, leverage],
ZERO_ADDRESS if self.vault_address is None else self.vault_address,
timestamp,
self.base_url == MAINNET_API_URL,
)
return self._post_action(
{
Expand All @@ -165,6 +168,7 @@ def update_isolated_margin(self, amount: float, coin: str) -> Any:
[asset, True, amount],
ZERO_ADDRESS if self.vault_address is None else self.vault_address,
timestamp,
self.base_url == MAINNET_API_URL,
)
return self._post_action(
{
Expand Down
4 changes: 2 additions & 2 deletions hyperliquid/info.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,15 +42,15 @@ def user_state(self, address: str) -> Any:
}
],
crossMarginSummary: MarginSummary,
marginSummary: MarginSummary
marginSummary: MarginSummary,
withdrawable: float string,
}
where MarginSummary is {
accountValue: float string,
totalMarginUsed: float string,
totalNtlPos: float string,
totalRawUsd: float string,
withdrawable: float string,
}
"""
return self.post("/info", {"type": "clearinghouseState", "user": address})
Expand Down
8 changes: 4 additions & 4 deletions hyperliquid/utils/signing.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,13 +107,13 @@ def order_spec_to_order_wire(order_spec: OrderSpec) -> OrderWire:
}


def construct_phantom_agent(signature_types, signature_data):
def construct_phantom_agent(signature_types, signature_data, is_mainnet):
connection_id = encode(signature_types, signature_data)

return {"source": "a", "connectionId": keccak(connection_id)}
return {"source": "a" if is_mainnet else "b", "connectionId": keccak(connection_id)}


def sign_l1_action(wallet, signature_types, signature_data, active_pool, nonce):
def sign_l1_action(wallet, signature_types, signature_data, active_pool, nonce, is_mainnet):
signature_types.append("address")
signature_types.append("uint64")
if active_pool is None:
Expand All @@ -122,7 +122,7 @@ def sign_l1_action(wallet, signature_types, signature_data, active_pool, nonce):
signature_data.append(active_pool)
signature_data.append(nonce)

phantom_agent = construct_phantom_agent(signature_types, signature_data)
phantom_agent = construct_phantom_agent(signature_types, signature_data, is_mainnet)

data = {
"domain": {
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.10"
version = "0.1.11"
description = "SDK for Hyperliquid API trading with Python."
readme = "README.md"
authors = ["Hyperliquid <[email protected]>"]
Expand Down
2 changes: 1 addition & 1 deletion tests/cassettes/info_test/test_get_user_state.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ interactions:
uri: https://api.hyperliquid.xyz/info
response:
body:
string: '{"assetPositions":[{"position":{"coin":"BTC","entryPx":"26951.0","leverage":{"type":"cross","value":20},"liquidationPx":"173198.69592357","marginUsed":"10.582271","maxTradeSzs":["0.76534","0.74964"],"positionValue":"211.64542","returnOnEquity":"-0.00756643","szi":"-0.00785","unrealizedPnl":"-0.08007"},"type":"oneWay"},{"position":{"coin":"ETH","entryPx":"1705.82","leverage":{"type":"cross","value":20},"liquidationPx":null,"marginUsed":"11.383755","maxTradeSzs":["11.8423","12.1091"],"positionValue":"227.675114","returnOnEquity":"0.01042942","szi":"0.1334","unrealizedPnl":"0.118726"},"type":"oneWay"},{"position":{"coin":"ATOM","entryPx":"10.787","leverage":{"type":"cross","value":20},"liquidationPx":"2561.83187333","marginUsed":"0.243","maxTradeSzs":["1872.32","1871.42"],"positionValue":"4.86","returnOnEquity":"-0.02407407","szi":"-0.45","unrealizedPnl":"-0.00585"},"type":"oneWay"},{"position":{"coin":"MATIC","entryPx":"1.03483","leverage":{"type":"cross","value":20},"liquidationPx":null,"marginUsed":"3.96788","maxTradeSzs":["19509.1","19662.3"],"positionValue":"79.3576","returnOnEquity":"0.02258687","szi":"76.6","unrealizedPnl":"0.089622"},"type":"oneWay"},{"position":{"coin":"DYDX","entryPx":"2.36808","leverage":{"type":"cross","value":20},"liquidationPx":"11.841653","marginUsed":"14.3622","maxTradeSzs":["8770.4","8528.0"],"positionValue":"287.244","returnOnEquity":"-0.01620253","szi":"-121.2","unrealizedPnl":"-0.232704"},"type":"oneWay"},{"position":{"coin":"SOL","entryPx":"19.6789","leverage":{"type":"cross","value":20},"liquidationPx":null,"marginUsed":"7.275455","maxTradeSzs":["1026.48","1041.26"],"positionValue":"145.5091","returnOnEquity":"0.01127476","szi":"7.39","unrealizedPnl":"0.082029"},"type":"oneWay"},{"position":{"coin":"AVAX","entryPx":"16.3839","leverage":{"type":"cross","value":20},"liquidationPx":null,"marginUsed":"23.206","maxTradeSzs":["1232.4","1289.0"],"positionValue":"464.12","returnOnEquity":"0.01963415","szi":"28.3","unrealizedPnl":"0.45563"},"type":"oneWay"},{"position":{"coin":"BNB","entryPx":"306.509","leverage":{"type":"cross","value":20},"liquidationPx":null,"marginUsed":"29.40102","maxTradeSzs":["65.856","69.688"],"positionValue":"588.0204","returnOnEquity":"0.02548061","szi":"1.916","unrealizedPnl":"0.749156"},"type":"oneWay"},{"position":{"coin":"APE","entryPx":"3.86082","leverage":{"type":"cross","value":20},"liquidationPx":"12.57589638","marginUsed":"25.47694","maxTradeSzs":["5491.5","5227.9"],"positionValue":"509.5388","returnOnEquity":"-0.02679772","szi":"-131.8","unrealizedPnl":"-0.682724"},"type":"oneWay"},{"position":{"coin":"OP","entryPx":"2.04459","leverage":{"type":"cross","value":20},"liquidationPx":"17.0707113","marginUsed":"7.8119","maxTradeSzs":["10036.1","9883.3"],"positionValue":"156.238","returnOnEquity":"-0.00400978","szi":"-76.4","unrealizedPnl":"-0.031324"},"type":"oneWay"},{"position":{"coin":"LTC","entryPx":"88.0926","leverage":{"type":"cross","value":20},"liquidationPx":null,"marginUsed":"23.48931","maxTradeSzs":["229.31","239.97"],"positionValue":"469.7862","returnOnEquity":"0.01075562","szi":"5.33","unrealizedPnl":"0.252642"},"type":"oneWay"},{"position":{"coin":"ARB","entryPx":"1.17991","leverage":{"type":"cross","value":20},"liquidationPx":null,"marginUsed":"14.541035","maxTradeSzs":["17131.2","17624.2"],"positionValue":"290.8207","returnOnEquity":"-0.00186472","szi":"246.5","unrealizedPnl":"-0.027115"},"type":"oneWay"}],"crossMarginSummary":{"accountValue":"1182.312496","totalMarginUsed":"171.740766","totalNtlPos":"3434.815334","totalRawUsd":"86.549602","withdrawable":"1010.57173"},"marginSummary":{"accountValue":"1182.312496","totalMarginUsed":"171.740766","totalNtlPos":"3434.815334","totalRawUsd":"86.549602","withdrawable":"1010.57173"}}'
string: '{"assetPositions":[{"position":{"coin":"BTC","entryPx":"26951.0","leverage":{"type":"cross","value":20},"liquidationPx":"173198.69592357","marginUsed":"10.582271","maxTradeSzs":["0.76534","0.74964"],"positionValue":"211.64542","returnOnEquity":"-0.00756643","szi":"-0.00785","unrealizedPnl":"-0.08007"},"type":"oneWay"},{"position":{"coin":"ETH","entryPx":"1705.82","leverage":{"type":"cross","value":20},"liquidationPx":null,"marginUsed":"11.383755","maxTradeSzs":["11.8423","12.1091"],"positionValue":"227.675114","returnOnEquity":"0.01042942","szi":"0.1334","unrealizedPnl":"0.118726"},"type":"oneWay"},{"position":{"coin":"ATOM","entryPx":"10.787","leverage":{"type":"cross","value":20},"liquidationPx":"2561.83187333","marginUsed":"0.243","maxTradeSzs":["1872.32","1871.42"],"positionValue":"4.86","returnOnEquity":"-0.02407407","szi":"-0.45","unrealizedPnl":"-0.00585"},"type":"oneWay"},{"position":{"coin":"MATIC","entryPx":"1.03483","leverage":{"type":"cross","value":20},"liquidationPx":null,"marginUsed":"3.96788","maxTradeSzs":["19509.1","19662.3"],"positionValue":"79.3576","returnOnEquity":"0.02258687","szi":"76.6","unrealizedPnl":"0.089622"},"type":"oneWay"},{"position":{"coin":"DYDX","entryPx":"2.36808","leverage":{"type":"cross","value":20},"liquidationPx":"11.841653","marginUsed":"14.3622","maxTradeSzs":["8770.4","8528.0"],"positionValue":"287.244","returnOnEquity":"-0.01620253","szi":"-121.2","unrealizedPnl":"-0.232704"},"type":"oneWay"},{"position":{"coin":"SOL","entryPx":"19.6789","leverage":{"type":"cross","value":20},"liquidationPx":null,"marginUsed":"7.275455","maxTradeSzs":["1026.48","1041.26"],"positionValue":"145.5091","returnOnEquity":"0.01127476","szi":"7.39","unrealizedPnl":"0.082029"},"type":"oneWay"},{"position":{"coin":"AVAX","entryPx":"16.3839","leverage":{"type":"cross","value":20},"liquidationPx":null,"marginUsed":"23.206","maxTradeSzs":["1232.4","1289.0"],"positionValue":"464.12","returnOnEquity":"0.01963415","szi":"28.3","unrealizedPnl":"0.45563"},"type":"oneWay"},{"position":{"coin":"BNB","entryPx":"306.509","leverage":{"type":"cross","value":20},"liquidationPx":null,"marginUsed":"29.40102","maxTradeSzs":["65.856","69.688"],"positionValue":"588.0204","returnOnEquity":"0.02548061","szi":"1.916","unrealizedPnl":"0.749156"},"type":"oneWay"},{"position":{"coin":"APE","entryPx":"3.86082","leverage":{"type":"cross","value":20},"liquidationPx":"12.57589638","marginUsed":"25.47694","maxTradeSzs":["5491.5","5227.9"],"positionValue":"509.5388","returnOnEquity":"-0.02679772","szi":"-131.8","unrealizedPnl":"-0.682724"},"type":"oneWay"},{"position":{"coin":"OP","entryPx":"2.04459","leverage":{"type":"cross","value":20},"liquidationPx":"17.0707113","marginUsed":"7.8119","maxTradeSzs":["10036.1","9883.3"],"positionValue":"156.238","returnOnEquity":"-0.00400978","szi":"-76.4","unrealizedPnl":"-0.031324"},"type":"oneWay"},{"position":{"coin":"LTC","entryPx":"88.0926","leverage":{"type":"cross","value":20},"liquidationPx":null,"marginUsed":"23.48931","maxTradeSzs":["229.31","239.97"],"positionValue":"469.7862","returnOnEquity":"0.01075562","szi":"5.33","unrealizedPnl":"0.252642"},"type":"oneWay"},{"position":{"coin":"ARB","entryPx":"1.17991","leverage":{"type":"cross","value":20},"liquidationPx":null,"marginUsed":"14.541035","maxTradeSzs":["17131.2","17624.2"],"positionValue":"290.8207","returnOnEquity":"-0.00186472","szi":"246.5","unrealizedPnl":"-0.027115"},"type":"oneWay"}],"crossMarginSummary":{"accountValue":"1182.312496","totalMarginUsed":"171.740766","totalNtlPos":"3434.815334","totalRawUsd":"86.549602"},"marginSummary":{"accountValue":"1182.312496","totalMarginUsed":"171.740766","totalNtlPos":"3434.815334","totalRawUsd":"86.549602"},"withdrawable":"1010.57173"}'
headers:
access-control-allow-origin:
- '*'
Expand Down
71 changes: 54 additions & 17 deletions tests/signing_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,16 +33,21 @@ def test_phantom_agent_creation_matches_production():
phantom_agent = construct_phantom_agent(
["(uint32,bool,uint64,uint64,bool,uint8,uint64)[]", "uint8", "address", "uint64"],
[[order_spec_preprocessing(order_spec)], order_grouping_to_number(grouping), ZERO_ADDRESS, timestamp],
True,
)
assert to_hex(phantom_agent["connectionId"]) == "0xd16723c8d7aab4b768e2060b763165f256825690ed246e6788264b27f6c929b9"


def test_l1_action_signing_matches():
wallet = eth_account.Account.from_key("0x0123456789012345678901234567890123456789012345678901234567890123")
signature = sign_l1_action(wallet, ["uint64"], [float_to_int_for_hashing(1000)], None, 0)
assert signature["r"] == "0xfd19b1e1f8ff9c4b8bd95f3522dee21783e02e381ba34624796d4f579a9fff74"
assert signature["s"] == "0x671f4cd60fa998ef5f1a841ca97dc47ad390915c230745cd3c371b0ef07a723b"
assert signature["v"] == 27
signature_mainnet = sign_l1_action(wallet, ["uint64"], [float_to_int_for_hashing(1000)], None, 0, True)
assert signature_mainnet["r"] == "0xfd19b1e1f8ff9c4b8bd95f3522dee21783e02e381ba34624796d4f579a9fff74"
assert signature_mainnet["s"] == "0x671f4cd60fa998ef5f1a841ca97dc47ad390915c230745cd3c371b0ef07a723b"
assert signature_mainnet["v"] == 27
signature_testnet = sign_l1_action(wallet, ["uint64"], [float_to_int_for_hashing(1000)], None, 0, False)
assert signature_testnet["r"] == "0x641b70a067c62d3286b85145a3975d6c7205654223ee29892cdeeb46dea73df2"
assert signature_testnet["s"] == "0x7089f33a1b78c1dbbbd83d95398cc9e2b87739fb70a967ab903b62d39050b5cf"
assert signature_testnet["v"] == 27


def test_l1_action_signing_order_matches():
Expand All @@ -60,26 +65,45 @@ def test_l1_action_signing_order_matches():
timestamp = 0
grouping: Literal["na"] = "na"

signature = sign_l1_action(
signature_mainnet = sign_l1_action(
wallet,
["(uint32,bool,uint64,uint64,bool,uint8,uint64)[]", "uint8"],
[[order_spec_preprocessing(order_spec)], order_grouping_to_number(grouping)],
ZERO_ADDRESS,
timestamp,
True,
)
assert signature["r"] == "0xc7249fd2e6483b2ab8fb0a80ac5201c4d36c8ed52bea5896012de499cdb78f4f"
assert signature["s"] == "0x235a525be1a3b3c5186a241763a47f4e1db463dbba64a3c4abad3696852cd6ff"
assert signature["v"] == 27
assert signature_mainnet["r"] == "0xc7249fd2e6483b2ab8fb0a80ac5201c4d36c8ed52bea5896012de499cdb78f4f"
assert signature_mainnet["s"] == "0x235a525be1a3b3c5186a241763a47f4e1db463dbba64a3c4abad3696852cd6ff"
assert signature_mainnet["v"] == 27

signature_testnet = sign_l1_action(
wallet,
["(uint32,bool,uint64,uint64,bool,uint8,uint64)[]", "uint8"],
[[order_spec_preprocessing(order_spec)], order_grouping_to_number(grouping)],
ZERO_ADDRESS,
timestamp,
False,
)
assert signature_testnet["r"] == "0x28d9e3237c12a7b07c357ce224a683ac5b947f03da209907ea264d10bb3a4311"
assert signature_testnet["s"] == "0x556c333b8572886be4dc637792384f19e1d920ab6356982d5bf6d98205e6978b"
assert signature_testnet["v"] == 27


def test_l1_action_signing_matches_with_vault():
wallet = eth_account.Account.from_key("0x0123456789012345678901234567890123456789012345678901234567890123")
signature = sign_l1_action(
wallet, ["uint64"], [float_to_int_for_hashing(1000)], "0x1719884eb866cb12b2287399b15f7db5e7d775ea", 0
signature_mainnet = sign_l1_action(
wallet, ["uint64"], [float_to_int_for_hashing(1000)], "0x1719884eb866cb12b2287399b15f7db5e7d775ea", 0, True
)
assert signature["r"] == "0x9358ee731732877d9a6d1a761fb6db43f93cb7c69ca74ecb382bd0773ac9b093"
assert signature["s"] == "0x2879b3d8384b80664346c4286c34f947fc970c3a84c2f3995555f68493adf60b"
assert signature["v"] == 27
assert signature_mainnet["r"] == "0x9358ee731732877d9a6d1a761fb6db43f93cb7c69ca74ecb382bd0773ac9b093"
assert signature_mainnet["s"] == "0x2879b3d8384b80664346c4286c34f947fc970c3a84c2f3995555f68493adf60b"
assert signature_mainnet["v"] == 27
signature_testnet = sign_l1_action(
wallet, ["uint64"], [float_to_int_for_hashing(1000)], "0x1719884eb866cb12b2287399b15f7db5e7d775ea", 0, False
)
assert signature_testnet["r"] == "0x42fc8e25437f795c701e73d4a21e4ee668f0f89c7ee9581adba915341dae82a3"
assert signature_testnet["s"] == "0x27c6a515b1e0f755a0c357e961b16f8acdf89a2ffdd4a50ca1df2c85e70ab0b3"
assert signature_testnet["v"] == 28


def test_l1_action_signing_tpsl_order_matches():
Expand All @@ -97,16 +121,29 @@ def test_l1_action_signing_tpsl_order_matches():
timestamp = 0
grouping: Literal["na"] = "na"

signature = sign_l1_action(
signature_mainnet = sign_l1_action(
wallet,
["(uint32,bool,uint64,uint64,bool,uint8,uint64)[]", "uint8"],
[[order_spec_preprocessing(order_spec)], order_grouping_to_number(grouping)],
ZERO_ADDRESS,
timestamp,
True,
)
assert signature_mainnet["r"] == "0xac0669959d0031e822c0aac9569f256ed66adfc409ab0bc3349f3006b794daf"
assert signature_mainnet["s"] == "0x25e31fba6a324b13f1b1960142b9af31bfc4cc73796ac988aef434d693f865ea"
assert signature_mainnet["v"] == 28

signature_testnet = sign_l1_action(
wallet,
["(uint32,bool,uint64,uint64,bool,uint8,uint64)[]", "uint8"],
[[order_spec_preprocessing(order_spec)], order_grouping_to_number(grouping)],
ZERO_ADDRESS,
timestamp,
False,
)
assert signature["r"] == "0xac0669959d0031e822c0aac9569f256ed66adfc409ab0bc3349f3006b794daf"
assert signature["s"] == "0x25e31fba6a324b13f1b1960142b9af31bfc4cc73796ac988aef434d693f865ea"
assert signature["v"] == 28
assert signature_testnet["r"] == "0x1d353477289b3beb1b776cb80086d4f768f95e850c80abd394e0383c9f7d4be0"
assert signature_testnet["s"] == "0x665fe43c4321bb8c2450817ad54b424758688f5542fc13b16e8e1db22e9c68ea"
assert signature_testnet["v"] == 28


def test_float_to_int_for_hashing():
Expand Down

0 comments on commit 063bf44

Please sign in to comment.