Skip to content

Commit

Permalink
Version 0.1.15
Browse files Browse the repository at this point in the history
  • Loading branch information
Adam committed Nov 21, 2023
1 parent cb63a3c commit 25c42a1
Show file tree
Hide file tree
Showing 8 changed files with 132 additions and 15 deletions.
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.
24 changes: 23 additions & 1 deletion examples/basic_agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ def main():

# Place an order that should rest by setting the price very low
agent_account: LocalAccount = eth_account.Account.from_key(agent_key)
print("Running with agent address:", account.address)
print("Running with agent address:", agent_account.address)
exchange = Exchange(agent_account, constants.TESTNET_API_URL)
order_result = exchange.order("ETH", True, 0.2, 1000, {"limit": {"tif": "Gtc"}})
print(order_result)
Expand All @@ -35,6 +35,28 @@ def main():
cancel_result = exchange.cancel("ETH", status["resting"]["oid"])
print(cancel_result)

# Create an extra named agent
exchange = Exchange(account, constants.TESTNET_API_URL)
approve_result, extra_agent_key = exchange.approve_agent("persist")
if approve_result["status"] != "ok":
print("approving extra agent failed", approve_result)
return

extra_agent_account: LocalAccount = eth_account.Account.from_key(extra_agent_key)
print("Running with extra agent address:", extra_agent_account.address)

print("Placing order with original agent")
order_result = exchange.order("ETH", True, 0.2, 1000, {"limit": {"tif": "Gtc"}})
print(order_result)

if order_result["status"] == "ok":
status = order_result["response"]["data"]["statuses"][0]
if "resting" in status:
print("Canceling order with extra agent")
exchange = Exchange(extra_agent_account, constants.TESTNET_API_URL)
cancel_result = exchange.cancel("ETH", status["resting"]["oid"])
print(cancel_result)


if __name__ == "__main__":
main()
25 changes: 16 additions & 9 deletions hyperliquid/exchange.py
Original file line number Diff line number Diff line change
Expand Up @@ -239,33 +239,40 @@ def usd_tranfer(self, amount: float, destination: str) -> Any:
signature = sign_usd_transfer_action(self.wallet, payload, is_mainnet)
return self._post_action(
{
"chain": "Arbitrum" if is_mainnet else "ArbitrumGoerli",
"chain": "Arbitrum" if is_mainnet else "ArbitrumTestnet",
"payload": payload,
"type": "usdTransfer",
},
signature,
timestamp,
)

def approve_agent(self) -> Tuple[Any, str]:
def approve_agent(self, name: Optional[str] = None) -> Tuple[Any, str]:
agent_key = "0x" + secrets.token_hex(32)
account = eth_account.Account.from_key(agent_key)
if name is not None:
connection_id = keccak(encode(["address", "string"], [account.address, name]))
else:
connection_id = keccak(encode(["address"], [account.address]))
agent = {
"source": "https://hyperliquid.xyz",
"connectionId": keccak(encode(["address"], [account.address])),
"connectionId": connection_id,
}
timestamp = get_timestamp_ms()
is_mainnet = self.base_url == MAINNET_API_URL
signature = sign_agent(self.wallet, agent, is_mainnet)
agent["connectionId"] = to_hex(agent["connectionId"])
action = {
"chain": "Arbitrum" if is_mainnet else "ArbitrumTestnet",
"agent": agent,
"agentAddress": account.address,
"type": "connect",
}
if name is not None:
action["extraAgentName"] = name
return (
self._post_action(
{
"chain": "Arbitrum" if is_mainnet else "ArbitrumGoerli",
"agent": agent,
"agentAddress": account.address,
"type": "connect",
},
action,
signature,
timestamp,
),
Expand Down
33 changes: 33 additions & 0 deletions hyperliquid/info.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,39 @@ def open_orders(self, address: str) -> Any:
"""
return self.post("/info", {"type": "openOrders", "user": address})

def frontend_open_orders(self, address: str) -> Any:
"""Retrieve a user's open orders with additional frontend info.
POST /info
Args:
address (str): Onchain address in 42-character hexadecimal format;
e.g. 0x0000000000000000000000000000000000000000.
Returns: [
{
children:
[
dict of frontend orders
]
coin: str,
isPositoinTpsl: bool,
isTrigger: bool,
limitPx: float string,
oid: int,
orderType: str,
origSz: float string,
reduceOnly: bool,
side: "A" | "B",
sz: float string,
tif: str,
timestamp: int,
triggerCondition: str,
triggerPx: float str
}
]
"""
return self.post("/info", {"type": "frontendOpenOrders", "user": address})

def all_mids(self) -> Any:
"""Retrieve all mids for all actively traded coins.
Expand Down
4 changes: 2 additions & 2 deletions hyperliquid/utils/signing.py
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ def sign_usd_transfer_action(wallet, message, is_mainnet):
"domain": {
"name": "Exchange",
"version": "1",
"chainId": 42161 if is_mainnet else 421613,
"chainId": 42161 if is_mainnet else 421614,
"verifyingContract": "0x0000000000000000000000000000000000000000",
},
"types": {
Expand All @@ -208,7 +208,7 @@ def sign_agent(wallet, agent, is_mainnet):
"domain": {
"name": "Exchange",
"version": "1",
"chainId": 42161 if is_mainnet else 421613,
"chainId": 42161 if is_mainnet else 421614,
"verifyingContract": "0x0000000000000000000000000000000000000000",
},
"types": {
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.14"
version = "0.1.15"
description = "SDK for Hyperliquid API trading with Python."
readme = "README.md"
authors = ["Hyperliquid <[email protected]>"]
Expand Down
48 changes: 48 additions & 0 deletions tests/cassettes/info_test/test_get_frontend_open_orders.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
interactions:
- request:
body: '{"type": "frontendOpenOrders", "user": "0xCB331197E84f135AB9Ed6FB51Cd9757c0bd29d0D"}'
headers:
Accept:
- '*/*'
Accept-Encoding:
- gzip, deflate
Connection:
- keep-alive
Content-Length:
- '84'
Content-Type:
- application/json
User-Agent:
- python-requests/2.31.0
method: POST
uri: https://api.hyperliquid.xyz/info
response:
body:
string: '[{"children":[],"coin":"INJ","isPositionTpsl":false,"isTrigger":true,"limitPx":"9.2037","oid":3184595907,"orderType":"Take
Profit Market","origSz":"12.5","reduceOnly":true,"side":"A","sz":"12.5","tif":null,"timestamp":1700126022555,"triggerCondition":"Price
above 10.004","triggerPx":"10.004"},{"children":[],"coin":"INJ","isPositionTpsl":false,"isTrigger":true,"limitPx":"9.1954","oid":3184595906,"orderType":"Stop
Market","origSz":"12.5","reduceOnly":true,"side":"A","sz":"12.5","tif":null,"timestamp":1700126022555,"triggerCondition":"Price
below 9.995","triggerPx":"9.995"},{"children":[{"children":[],"coin":"INJ","isPositionTpsl":false,"isTrigger":true,"limitPx":"9.1954","oid":3184595906,"orderType":"Stop
Market","origSz":"12.5","reduceOnly":true,"side":"A","sz":"12.5","tif":null,"timestamp":1700126022555,"triggerCondition":"Price
below 9.995","triggerPx":"9.995"},{"children":[],"coin":"INJ","isPositionTpsl":false,"isTrigger":true,"limitPx":"9.2037","oid":3184595907,"orderType":"Take
Profit Market","origSz":"12.5","reduceOnly":true,"side":"A","sz":"12.5","tif":null,"timestamp":1700126022555,"triggerCondition":"Price
above 10.004","triggerPx":"10.004"}],"coin":"INJ","isPositionTpsl":false,"isTrigger":false,"limitPx":"10.0","oid":3184595905,"orderType":"Limit","origSz":"12.5","reduceOnly":false,"side":"B","sz":"12.5","tif":"Gtc","timestamp":1700126022555,"triggerCondition":"N/A","triggerPx":"0.0"}]'
headers:
access-control-allow-origin:
- '*'
access-control-expose-headers:
- '*'
content-length:
- '1417'
content-type:
- application/json
date:
- Thu, 16 Nov 2023 09:16:00 GMT
vary:
- origin
- access-control-request-method
- access-control-request-headers
status:
code: 200
message: OK
version: 1
7 changes: 7 additions & 0 deletions tests/info_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,13 @@ def test_get_open_orders():
assert len(response) == 196


@pytest.mark.vcr()
def test_get_frontend_open_orders():
info = Info(skip_ws=True)
response = info.frontend_open_orders("0xCB331197E84f135AB9Ed6FB51Cd9757c0bd29d0D")
assert len(response) == 3


@pytest.mark.vcr()
def test_get_all_mids():
info = Info(skip_ws=True)
Expand Down

0 comments on commit 25c42a1

Please sign in to comment.