From 0e1d04f6cb7a6f7d9c732d60c09401449fd2e0fd Mon Sep 17 00:00:00 2001 From: carlos Date: Tue, 19 Dec 2023 14:25:13 +0200 Subject: [PATCH 01/18] add mainnet examples, readme and configs --- v4-client-py/23.3.2 | 0 .../examples/mainnet_examples/README.md | 26 ++++ .../examples/mainnet_examples/__init__.py | 0 .../mainnet_account_endpoints.py | 121 ++++++++++++++++++ .../mainnet_long_term_order_cancel_example.py | 109 ++++++++++++++++ ...innet_long_term_order_composite_example.py | 93 ++++++++++++++ ...mainnet_short_term_order_cancel_example.py | 88 +++++++++++++ ...nnet_short_term_order_composite_example.py | 72 +++++++++++ .../mainnet_examples/mainnet_ws_get_fills.py | 70 ++++++++++ .../v4_client_py/chain/aerial/config.py | 4 +- .../v4_client_py/clients/constants.py | 8 +- .../v4_client_py/clients/modules/post.py | 4 +- 12 files changed, 588 insertions(+), 7 deletions(-) create mode 100644 v4-client-py/23.3.2 create mode 100644 v4-client-py/examples/mainnet_examples/README.md create mode 100644 v4-client-py/examples/mainnet_examples/__init__.py create mode 100644 v4-client-py/examples/mainnet_examples/mainnet_account_endpoints.py create mode 100644 v4-client-py/examples/mainnet_examples/mainnet_long_term_order_cancel_example.py create mode 100644 v4-client-py/examples/mainnet_examples/mainnet_long_term_order_composite_example.py create mode 100644 v4-client-py/examples/mainnet_examples/mainnet_short_term_order_cancel_example.py create mode 100644 v4-client-py/examples/mainnet_examples/mainnet_short_term_order_composite_example.py create mode 100644 v4-client-py/examples/mainnet_examples/mainnet_ws_get_fills.py diff --git a/v4-client-py/23.3.2 b/v4-client-py/23.3.2 new file mode 100644 index 00000000..e69de29b diff --git a/v4-client-py/examples/mainnet_examples/README.md b/v4-client-py/examples/mainnet_examples/README.md new file mode 100644 index 00000000..fe4bb053 --- /dev/null +++ b/v4-client-py/examples/mainnet_examples/README.md @@ -0,0 +1,26 @@ +# User guide to test mainnet examples + +The examples present in this folder are meant to be used in the mainnet, thus, with real money. Use them at your own risk. + +1. Go to your repository location for the Python client +``` +cd ~/.../v4-clients/v4-client-py +``` +2. Create a virtual environment for the DyDx client, activate it and install requirements +``` +python3 -m venv venv +source venv/bin/activate +pip3 install -r requirements.txt +``` +3. Export PYTHONPATH for your current location +``` +export PYTHONPATH='cd ~/.../v4-clients/v4-client-py' +``` +4. Set in v4_client_py/clients/modules/post.py the mainnet network instead of testnet (lines 46 to 48) +``` +# here to be selected testent or mainnet network +#network = NetworkConfig.fetch_dydx_testnet() +network = NetworkConfig.fetchai_mainnet() +``` + +Now you are ready to use the examples in this folder. \ No newline at end of file diff --git a/v4-client-py/examples/mainnet_examples/__init__.py b/v4-client-py/examples/mainnet_examples/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/v4-client-py/examples/mainnet_examples/mainnet_account_endpoints.py b/v4-client-py/examples/mainnet_examples/mainnet_account_endpoints.py new file mode 100644 index 00000000..e482adf9 --- /dev/null +++ b/v4-client-py/examples/mainnet_examples/mainnet_account_endpoints.py @@ -0,0 +1,121 @@ +from v4_client_py.clients import IndexerClient, Subaccount +from v4_client_py.clients.constants import Network +import os +import sys + +# Set the mnemonic as a variable in your shell +MNEMONIC = os.environ.get("MNEMONIC") +if MNEMONIC is None: + print("MNEMONIC not provided.") + sys.exit(1) + +client = IndexerClient( + config=Network.mainnet().indexer_config, +) + +try: + subaccount = Subaccount.from_mnemonic(MNEMONIC) + address = subaccount.address + + # Get subaccounts + try: + subaccounts_response = client.account.get_subaccounts(address) + print(f"{subaccounts_response.data}") + subaccounts = subaccounts_response.data["subaccounts"] + subaccount_0 = subaccounts[0] + print(f"{subaccount_0}") + subaccount_0_subaccountNumber = subaccount_0["subaccountNumber"] + except Exception: + print("failed to get subaccounts") + + try: + subaccount_response = client.account.get_subaccount(address, 0) + print(f"{subaccount_response.data}") + subaccount = subaccount_response.data["subaccount"] + print(f"{subaccount}") + subaccount_subaccountNumber = subaccount["subaccountNumber"] + except Exception: + print("failed to get subaccount") + + # Get positions + try: + asset_positions_response = client.account.get_subaccount_asset_positions(address, 0) + print(f"{asset_positions_response.data}") + asset_positions = asset_positions_response.data["positions"] + if len(asset_positions) > 0: + asset_positions_0 = asset_positions[0] + print(f"{asset_positions_0}") + except Exception: + print("failed to get asset positions") + + try: + perpetual_positions_response = client.account.get_subaccount_perpetual_positions(address, 0) + print(f"{perpetual_positions_response.data}") + perpetual_positions = perpetual_positions_response.data["positions"] + if len(perpetual_positions) > 0: + perpetual_positions_0 = perpetual_positions[0] + print(f"{perpetual_positions_0}") + except Exception: + print("failed to get perpetual positions") + + # Get transfers + try: + transfers_response = client.account.get_subaccount_transfers(address, 0) + print(f"{transfers_response.data}") + transfers = transfers_response.data["transfers"] + if len(transfers) > 0: + transfers_0 = transfers[0] + print(f"{transfers_0}") + except Exception: + print("failed to get transfers") + + # Get orders + try: + orders_response = client.account.get_subaccount_orders(address, 0) + print(f"{orders_response.data}") + orders = orders_response.data + if len(orders) > 0: + order_0 = orders[0] + print(f"{order_0}") + order_0_id = order_0["id"] + order_response = client.account.get_order(order_id=order_0_id) + order = order_response.data + order_id = order["id"] + except: + print("failed to get orders") + + # Get fills + try: + fills_response = client.account.get_subaccount_fills(address, 0) + print(f"{fills_response.data}") + fills = fills_response.data["fills"] + if len(fills) > 0: + fill_0 = fills[0] + print(f"{fill_0}") + except Exception: + print("failed to get fills") + + # Get funding + try: + funding_response = client.account.get_subaccount_funding(address, 0) + print(f"{funding_response.data}") + funding = funding_response.data["fundingPayments"] + if len(funding) > 0: + funding_0 = funding[0] + print(f"{funding_0}") + except Exception: + print("failed to get funding") + + # Get historical pnl + try: + historical_pnl_response = client.account.get_subaccount_historical_pnls(address, 0) + print(f"{historical_pnl_response.data}") + historical_pnl = historical_pnl_response.data["historicalPnl"] + if len(historical_pnl) > 0: + historical_pnl_0 = historical_pnl[0] + print(f"{historical_pnl_0}") + except Exception: + print("failed to get historical pnl") + +except Exception: + print("from_mnemonic failed") diff --git a/v4-client-py/examples/mainnet_examples/mainnet_long_term_order_cancel_example.py b/v4-client-py/examples/mainnet_examples/mainnet_long_term_order_cancel_example.py new file mode 100644 index 00000000..63977e2c --- /dev/null +++ b/v4-client-py/examples/mainnet_examples/mainnet_long_term_order_cancel_example.py @@ -0,0 +1,109 @@ +import asyncio +import logging +import os +import sys +from random import randrange + +from v4_client_py.chain.aerial.wallet import LocalWallet +from v4_client_py.clients import CompositeClient, Subaccount +from v4_client_py.clients.constants import BECH32_PREFIX, Network + +from v4_client_py.clients.helpers.chain_helpers import ( + ORDER_FLAGS_LONG_TERM, + OrderType, + OrderSide, + OrderTimeInForce, + OrderExecution, +) + +from tests.constants import MAX_CLIENT_ID + +# Set the mnemonic as a variable in your shell +MNEMONIC = os.environ.get("MNEMONIC") +if MNEMONIC is None: + print("MNEMONIC not provided.") + sys.exit(1) + +# define objects to be used with the SDK +wallet = LocalWallet.from_mnemonic(MNEMONIC, BECH32_PREFIX) +network = Network.mainnet() +client = CompositeClient( + network, +) +subaccount = Subaccount(wallet, 0) + + +def define_order() -> dict: + return { + "subaccount": subaccount, + "market": "ETH-USD", + "type": OrderType.LIMIT, + "side": OrderSide.SELL, + "price": 40000, + "size": 0.01, + "client_id": randrange(0, MAX_CLIENT_ID), + "time_in_force": OrderTimeInForce.GTT, + "good_till_block": 0, + # long term orders use GTBT + "good_til_time_in_seconds": 60, + "execution": OrderExecution.DEFAULT, + "post_only": False, + "reduce_only": False, + } + + +async def main() -> None: + """ + Note this example places a stateful order. + Programmatic traders should generally not use stateful orders for following reasons: + - Stateful orders received out of order by validators will fail sequence number validation + and be dropped. + - Stateful orders have worse time priority since they are only matched after they are included + on the block. + - Stateful order rate limits are more restrictive than Short-Term orders, specifically max 2 per + block / 20 per 100 blocks. + - Stateful orders can only be canceled after they’ve been included in a block. + """ + order = define_order() + try: + tx = client.place_order( + subaccount=order["subaccount"], + market=order["market"], + type=order["type"], + side=order["side"], + price=order["price"], + size=order["size"], + client_id=order["client_id"], + time_in_force=order["time_in_force"], + good_til_block=order["good_till_block"], + good_til_time_in_seconds=order["good_til_time_in_seconds"], + execution=order["execution"], + post_only=order["post_only"], + reduce_only=order["reduce_only"], + ) + print("** Long Term Order Tx**") + print(tx.tx_hash) + except Exception as error: + print("**Long Term Order Failed**") + print(error) + + # cancel a long term order. + try: + tx = client.cancel_order( + subaccount=order["subaccount"], + client_id=order["client_id"], + market=order["market"], + order_flags=ORDER_FLAGS_LONG_TERM, + good_til_time_in_seconds=order["good_til_time_in_seconds"], + good_til_block=order["good_till_block"], # long term orders use GTBT + ) + print("**Cancel Long Term Order Tx**") + print(tx.tx_hash) + except Exception as error: + print("**Cancel Long Term Order Failed**") + print(error) + + +if __name__ == "__main__": + logging.basicConfig(level=logging.INFO) + asyncio.get_event_loop().run_until_complete(main()) diff --git a/v4-client-py/examples/mainnet_examples/mainnet_long_term_order_composite_example.py b/v4-client-py/examples/mainnet_examples/mainnet_long_term_order_composite_example.py new file mode 100644 index 00000000..30950ad4 --- /dev/null +++ b/v4-client-py/examples/mainnet_examples/mainnet_long_term_order_composite_example.py @@ -0,0 +1,93 @@ +import asyncio +import logging +import os +import sys +from random import randrange + +from v4_client_py.chain.aerial.wallet import LocalWallet +from v4_client_py.clients import CompositeClient, Subaccount +from v4_client_py.clients.constants import BECH32_PREFIX, Network + +from v4_client_py.clients.helpers.chain_helpers import ( + ORDER_FLAGS_LONG_TERM, + OrderType, + OrderSide, + OrderTimeInForce, + OrderExecution, +) + +from tests.constants import MAX_CLIENT_ID + +# Set the mnemonic as a variable in your shell +MNEMONIC = os.environ.get("MNEMONIC") +if MNEMONIC is None: + print("MNEMONIC not provided.") + sys.exit(1) + +# define objects to be used with the SDK +wallet = LocalWallet.from_mnemonic(MNEMONIC, BECH32_PREFIX) +network = Network.mainnet() +client = CompositeClient( + network, +) +subaccount = Subaccount(wallet, 0) + + +def define_order() -> dict: + return { + "subaccount": subaccount, + "market": "ETH-USD", + "type": OrderType.LIMIT, + "side": OrderSide.SELL, + "price": 40000, + "size": 0.01, + "client_id": randrange(0, MAX_CLIENT_ID), + "time_in_force": OrderTimeInForce.GTT, + "good_till_block": 0, + # long term orders use GTBT + "good_til_time_in_seconds": 60, + "execution": OrderExecution.DEFAULT, + "post_only": False, + "reduce_only": False, + } + + +async def main() -> None: + """ + Note this example places a stateful order. + Programmatic traders should generally not use stateful orders for following reasons: + - Stateful orders received out of order by validators will fail sequence number validation + and be dropped. + - Stateful orders have worse time priority since they are only matched after they are included + on the block. + - Stateful order rate limits are more restrictive than Short-Term orders, specifically max 2 per + block / 20 per 100 blocks. + - Stateful orders can only be canceled after they’ve been included in a block. + """ + order = define_order() + try: + tx = client.place_order( + subaccount=order["subaccount"], + market=order["market"], + type=order["type"], + side=order["side"], + price=order["price"], + size=order["size"], + client_id=order["client_id"], + time_in_force=order["time_in_force"], + good_til_block=order["good_till_block"], + good_til_time_in_seconds=order["good_til_time_in_seconds"], + execution=order["execution"], + post_only=order["post_only"], + reduce_only=order["reduce_only"], + ) + print("** Long Term Order Tx**") + print(tx.tx_hash) + except Exception as error: + print("**Long Term Order Failed**") + print(error) + + +if __name__ == "__main__": + logging.basicConfig(level=logging.INFO) + asyncio.get_event_loop().run_until_complete(main()) diff --git a/v4-client-py/examples/mainnet_examples/mainnet_short_term_order_cancel_example.py b/v4-client-py/examples/mainnet_examples/mainnet_short_term_order_cancel_example.py new file mode 100644 index 00000000..781de7d5 --- /dev/null +++ b/v4-client-py/examples/mainnet_examples/mainnet_short_term_order_cancel_example.py @@ -0,0 +1,88 @@ +import asyncio +import logging +import os +import sys +from random import randrange + +from v4_client_py.chain.aerial.wallet import LocalWallet +from v4_client_py.clients import CompositeClient, Subaccount +from v4_client_py.clients.constants import BECH32_PREFIX, Network + +from v4_client_py.clients.helpers.chain_helpers import ( + ORDER_FLAGS_SHORT_TERM, + Order_TimeInForce, + OrderSide, +) +from tests.constants import MAX_CLIENT_ID + +# Set the mnemonic as a variable in your shell +MNEMONIC = os.environ.get("MNEMONIC") +if MNEMONIC is None: + print("MNEMONIC not provided.") + sys.exit(1) + +# define objects to be used with the SDK +wallet = LocalWallet.from_mnemonic(MNEMONIC, BECH32_PREFIX) +network = Network.mainnet() +client = CompositeClient( + network, +) +subaccount = Subaccount(wallet, 0) + + +def define_order() -> dict: + return { + "subaccount": subaccount, + "market": "ETH-USD", + "side": OrderSide.SELL, + "price": 40000, + "size": 0.01, + "client_id": randrange(0, MAX_CLIENT_ID), + "good_till_block": client.get_current_block() + 11, + # Note, you can change this to any number between `current_block+1` + # to `current_block+1 + SHORT_BLOCK_WINDOW` + "time_in_force": Order_TimeInForce.TIME_IN_FORCE_UNSPECIFIED, + "reduce_only": False, + } + + +async def main() -> None: + order = define_order() + try: + tx = client.place_short_term_order( + subaccount=order["subaccount"], + market=order["market"], + side=order["side"], + price=order["price"], + size=order["size"], + client_id=order["client_id"], + good_til_block=order["good_till_block"], + time_in_force=order["time_in_force"], + reduce_only=order["reduce_only"], + ) + print("**Short Term Order Tx**") + print(tx.tx_hash) + except Exception as error: + print("**Short Term Order Failed**") + print(error) + + # cancel a short term order. + try: + tx = client.cancel_order( + subaccount=order["subaccount"], + client_id=order["client_id"], + market=order["market"], + order_flags=ORDER_FLAGS_SHORT_TERM, + good_til_time_in_seconds=0, # short term orders use GTB. + good_til_block=order["good_till_block"], # GTB should be the same or greater than order to cancel + ) + print("**Cancel Short Term Order Tx**") + print(tx.tx_hash) + except Exception as error: + print("**Cancel Short Term Order Failed**") + print(error) + + +if __name__ == "__main__": + logging.basicConfig(level=logging.INFO) + asyncio.get_event_loop().run_until_complete(main()) diff --git a/v4-client-py/examples/mainnet_examples/mainnet_short_term_order_composite_example.py b/v4-client-py/examples/mainnet_examples/mainnet_short_term_order_composite_example.py new file mode 100644 index 00000000..15ef466c --- /dev/null +++ b/v4-client-py/examples/mainnet_examples/mainnet_short_term_order_composite_example.py @@ -0,0 +1,72 @@ +import asyncio +import logging +import os +import sys +from random import randrange + +from v4_client_py.chain.aerial.wallet import LocalWallet +from v4_client_py.clients import CompositeClient, Subaccount +from v4_client_py.clients.constants import BECH32_PREFIX, Network + +from v4_client_py.clients.helpers.chain_helpers import ( + ORDER_FLAGS_SHORT_TERM, + Order_TimeInForce, + OrderSide, +) +from tests.constants import MAX_CLIENT_ID + +# Set the mnemonic as a variable in your shell +MNEMONIC = os.environ.get("MNEMONIC") +if MNEMONIC is None: + print("MNEMONIC not provided.") + sys.exit(1) + +# define objects to be used with the SDK +wallet = LocalWallet.from_mnemonic(MNEMONIC, BECH32_PREFIX) +network = Network.mainnet() +client = CompositeClient( + network, +) +subaccount = Subaccount(wallet, 0) + + +def define_order() -> dict: + return { + "subaccount": subaccount, + "market": "ETH-USD", + "side": OrderSide.SELL, + "price": 40000, + "size": 0.01, + "client_id": randrange(0, MAX_CLIENT_ID), + "good_till_block": client.get_current_block() + 11, + # Note, you can change this to any number between `current_block+1` + # to `current_block+1 + SHORT_BLOCK_WINDOW` + "time_in_force": Order_TimeInForce.TIME_IN_FORCE_UNSPECIFIED, + "reduce_only": False, + } + + +async def main() -> None: + order = define_order() + try: + tx = client.place_short_term_order( + subaccount=order["subaccount"], + market=order["market"], + side=order["side"], + price=order["price"], + size=order["size"], + client_id=order["client_id"], + good_til_block=order["good_till_block"], + time_in_force=order["time_in_force"], + reduce_only=order["reduce_only"], + ) + print("**Short Term Order Tx**") + print(tx.tx_hash) + except Exception as error: + print("**Short Term Order Failed**") + print(error) + + +if __name__ == "__main__": + logging.basicConfig(level=logging.INFO) + asyncio.get_event_loop().run_until_complete(main()) diff --git a/v4-client-py/examples/mainnet_examples/mainnet_ws_get_fills.py b/v4-client-py/examples/mainnet_examples/mainnet_ws_get_fills.py new file mode 100644 index 00000000..d33a39c4 --- /dev/null +++ b/v4-client-py/examples/mainnet_examples/mainnet_ws_get_fills.py @@ -0,0 +1,70 @@ +import asyncio +import json +import os +import sys + +from v4_client_py.clients.dydx_socket_client import SocketClient +from v4_client_py.clients.constants import Network + +ADDRESS = os.environ.get("ADDRESS") +if ADDRESS is None: + print("ADDRESS not provided.") + sys.exit(1) + + +def for_fills(fills_data): + try: + for fill in fills_data: + print("Received fill:", fill) + except Exception as e: + print(e) + + +def check_fills(message_data): + try: + if "contents" in message_data and "fills" in message_data["contents"]: + if fills_data := message_data["contents"]["fills"]: + for_fills(fills_data) + else: + print("No fills information in the message.") + else: + print("No 'contents' or 'fills' key in the message.") + except Exception as e: + print(e) + + +def on_open(ws): + print("WebSocket connection opened") + ws.send_ping_if_inactive_for(30) + + +def on_message(ws, message): + print(message) + payload = json.loads(message) + if payload["type"] == "connected": + my_ws.subscribe_to_subaccount(ADDRESS, 0) + else: + check_fills(payload) + ws.send_ping_if_inactive_for(30) + ws.subscribe_to_markets() + + +def on_close(ws): + print("WebSocket connection closed") + + +async def main(): + try: + my_ws.connect() + except Exception as e: + print(f"An error occurred: {e}") + + +# Run the event loop forever +if __name__ == "__main__": + my_ws = SocketClient( + config=Network.mainnet().indexer_config, on_message=on_message, on_open=on_open, on_close=on_close + ) + print(my_ws) + + asyncio.get_event_loop().run_until_complete(main()) diff --git a/v4-client-py/v4_client_py/chain/aerial/config.py b/v4-client-py/v4_client_py/chain/aerial/config.py index 97c6b2b4..30e97601 100644 --- a/v4-client-py/v4_client_py/chain/aerial/config.py +++ b/v4-client-py/v4_client_py/chain/aerial/config.py @@ -117,8 +117,8 @@ def fetchai_mainnet(cls) -> "NetworkConfig": :return: fetch mainnet configuration """ return NetworkConfig( - chain_id="fetchhub-4", - url="grpc+https://grpc-fetchhub.fetch.ai", + chain_id="dydx-mainnet-1", + url="grpc+https://grpc.dydx.nodestake.top", fee_minimum_gas_price=0, fee_denomination="afet", staking_denomination="afet", diff --git a/v4-client-py/v4_client_py/clients/constants.py b/v4-client-py/v4_client_py/clients/constants.py index 86920ca4..51c4bf1d 100644 --- a/v4-client-py/v4_client_py/clients/constants.py +++ b/v4-client-py/v4_client_py/clients/constants.py @@ -3,10 +3,10 @@ # ------------ API URLs ------------ -INDEXER_API_HOST_MAINNET = None +INDEXER_API_HOST_MAINNET = "https://indexer.dydx.trade/" INDEXER_API_HOST_TESTNET = 'https://dydx-testnet.imperator.co' -INDEXER_WS_HOST_MAINNET = None +INDEXER_WS_HOST_MAINNET = "wss://indexer.dydx.trade/v4/ws" INDEXER_WS_HOST_TESTNET = 'wss://indexer.v4testnet.dydx.exchange/v4/ws' FAUCET_API_HOST_TESTNET = 'https://faucet.v4testnet.dydx.exchange' @@ -14,11 +14,11 @@ VALIDATOR_API_HOST_MAINNET = None VALIDATOR_API_HOST_TESTNET = 'https://dydx-testnet-archive.allthatnode.com' -VALIDATOR_GRPC_MAINNET = None +VALIDATOR_GRPC_MAINNET = "dydx-mainnet-full-grpc.public.blastapi.io:443" VALIDATOR_GRPC_TESTNET = 'dydx-testnet-archive.allthatnode.com:9090' # ------------ Ethereum Network IDs ------------ -NETWORK_ID_MAINNET = None +NETWORK_ID_MAINNET = "dydx-mainnet-1" NETWORK_ID_TESTNET = 'dydx-testnet-4' # ------------ Market Statistic Day Types ------------ diff --git a/v4-client-py/v4_client_py/clients/modules/post.py b/v4-client-py/v4_client_py/clients/modules/post.py index 7fc1bc7f..26e1385a 100644 --- a/v4-client-py/v4_client_py/clients/modules/post.py +++ b/v4-client-py/v4_client_py/clients/modules/post.py @@ -43,7 +43,9 @@ def send_message( ''' wallet = subaccount.wallet - network = NetworkConfig.fetch_dydx_testnet() + # here to be selected testent or mainnet network + #network = NetworkConfig.fetch_dydx_testnet() + network = NetworkConfig.fetchai_mainnet() ledger = LedgerClient(network) tx = Transaction() tx.add_message(msg) From ec13b40b55e5b785f32608ef396af1064386d2d2 Mon Sep 17 00:00:00 2001 From: carlos Date: Tue, 19 Dec 2023 14:40:18 +0200 Subject: [PATCH 02/18] remove unnecessary file --- v4-client-py/23.3.2 | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 v4-client-py/23.3.2 diff --git a/v4-client-py/23.3.2 b/v4-client-py/23.3.2 deleted file mode 100644 index e69de29b..00000000 From ce3ab191d7a84a3b58d9ecf6405553619d5ecc09 Mon Sep 17 00:00:00 2001 From: carlos Date: Tue, 19 Dec 2023 15:39:02 +0200 Subject: [PATCH 03/18] fix post.py to get the network config based on the class network selected --- .../mainnet_account_endpoints.py | 8 +------- .../mainnet_long_term_order_cancel_example.py | 9 ++------- ...mainnet_long_term_order_composite_example.py | 8 +------- .../mainnet_short_term_order_cancel_example.py | 8 +------- ...ainnet_short_term_order_composite_example.py | 8 +------- .../mainnet_examples/mainnet_ws_get_fills.py | 8 +------- .../v4_client_py/clients/modules/post.py | 17 ++++++++++++++--- 7 files changed, 21 insertions(+), 45 deletions(-) diff --git a/v4-client-py/examples/mainnet_examples/mainnet_account_endpoints.py b/v4-client-py/examples/mainnet_examples/mainnet_account_endpoints.py index e482adf9..325ffc89 100644 --- a/v4-client-py/examples/mainnet_examples/mainnet_account_endpoints.py +++ b/v4-client-py/examples/mainnet_examples/mainnet_account_endpoints.py @@ -1,13 +1,7 @@ from v4_client_py.clients import IndexerClient, Subaccount from v4_client_py.clients.constants import Network -import os -import sys -# Set the mnemonic as a variable in your shell -MNEMONIC = os.environ.get("MNEMONIC") -if MNEMONIC is None: - print("MNEMONIC not provided.") - sys.exit(1) +MNEMONIC = "" client = IndexerClient( config=Network.mainnet().indexer_config, diff --git a/v4-client-py/examples/mainnet_examples/mainnet_long_term_order_cancel_example.py b/v4-client-py/examples/mainnet_examples/mainnet_long_term_order_cancel_example.py index 63977e2c..45f434ed 100644 --- a/v4-client-py/examples/mainnet_examples/mainnet_long_term_order_cancel_example.py +++ b/v4-client-py/examples/mainnet_examples/mainnet_long_term_order_cancel_example.py @@ -1,7 +1,5 @@ import asyncio import logging -import os -import sys from random import randrange from v4_client_py.chain.aerial.wallet import LocalWallet @@ -18,11 +16,8 @@ from tests.constants import MAX_CLIENT_ID -# Set the mnemonic as a variable in your shell -MNEMONIC = os.environ.get("MNEMONIC") -if MNEMONIC is None: - print("MNEMONIC not provided.") - sys.exit(1) +MNEMONIC = "" + # define objects to be used with the SDK wallet = LocalWallet.from_mnemonic(MNEMONIC, BECH32_PREFIX) diff --git a/v4-client-py/examples/mainnet_examples/mainnet_long_term_order_composite_example.py b/v4-client-py/examples/mainnet_examples/mainnet_long_term_order_composite_example.py index 30950ad4..fb6fc95e 100644 --- a/v4-client-py/examples/mainnet_examples/mainnet_long_term_order_composite_example.py +++ b/v4-client-py/examples/mainnet_examples/mainnet_long_term_order_composite_example.py @@ -1,7 +1,5 @@ import asyncio import logging -import os -import sys from random import randrange from v4_client_py.chain.aerial.wallet import LocalWallet @@ -18,11 +16,7 @@ from tests.constants import MAX_CLIENT_ID -# Set the mnemonic as a variable in your shell -MNEMONIC = os.environ.get("MNEMONIC") -if MNEMONIC is None: - print("MNEMONIC not provided.") - sys.exit(1) +MNEMONIC = "" # define objects to be used with the SDK wallet = LocalWallet.from_mnemonic(MNEMONIC, BECH32_PREFIX) diff --git a/v4-client-py/examples/mainnet_examples/mainnet_short_term_order_cancel_example.py b/v4-client-py/examples/mainnet_examples/mainnet_short_term_order_cancel_example.py index 781de7d5..6081142f 100644 --- a/v4-client-py/examples/mainnet_examples/mainnet_short_term_order_cancel_example.py +++ b/v4-client-py/examples/mainnet_examples/mainnet_short_term_order_cancel_example.py @@ -1,7 +1,5 @@ import asyncio import logging -import os -import sys from random import randrange from v4_client_py.chain.aerial.wallet import LocalWallet @@ -15,11 +13,7 @@ ) from tests.constants import MAX_CLIENT_ID -# Set the mnemonic as a variable in your shell -MNEMONIC = os.environ.get("MNEMONIC") -if MNEMONIC is None: - print("MNEMONIC not provided.") - sys.exit(1) +MNEMONIC = "" # define objects to be used with the SDK wallet = LocalWallet.from_mnemonic(MNEMONIC, BECH32_PREFIX) diff --git a/v4-client-py/examples/mainnet_examples/mainnet_short_term_order_composite_example.py b/v4-client-py/examples/mainnet_examples/mainnet_short_term_order_composite_example.py index 15ef466c..1d6bc1ba 100644 --- a/v4-client-py/examples/mainnet_examples/mainnet_short_term_order_composite_example.py +++ b/v4-client-py/examples/mainnet_examples/mainnet_short_term_order_composite_example.py @@ -1,7 +1,5 @@ import asyncio import logging -import os -import sys from random import randrange from v4_client_py.chain.aerial.wallet import LocalWallet @@ -15,11 +13,7 @@ ) from tests.constants import MAX_CLIENT_ID -# Set the mnemonic as a variable in your shell -MNEMONIC = os.environ.get("MNEMONIC") -if MNEMONIC is None: - print("MNEMONIC not provided.") - sys.exit(1) +MNEMONIC = "" # define objects to be used with the SDK wallet = LocalWallet.from_mnemonic(MNEMONIC, BECH32_PREFIX) diff --git a/v4-client-py/examples/mainnet_examples/mainnet_ws_get_fills.py b/v4-client-py/examples/mainnet_examples/mainnet_ws_get_fills.py index d33a39c4..7742f61e 100644 --- a/v4-client-py/examples/mainnet_examples/mainnet_ws_get_fills.py +++ b/v4-client-py/examples/mainnet_examples/mainnet_ws_get_fills.py @@ -1,16 +1,10 @@ import asyncio import json -import os -import sys from v4_client_py.clients.dydx_socket_client import SocketClient from v4_client_py.clients.constants import Network -ADDRESS = os.environ.get("ADDRESS") -if ADDRESS is None: - print("ADDRESS not provided.") - sys.exit(1) - +ADDRESS = "" def for_fills(fills_data): try: diff --git a/v4-client-py/v4_client_py/clients/modules/post.py b/v4-client-py/v4_client_py/clients/modules/post.py index 26e1385a..74e4d7fd 100644 --- a/v4-client-py/v4_client_py/clients/modules/post.py +++ b/v4-client-py/v4_client_py/clients/modules/post.py @@ -13,6 +13,7 @@ from ...chain.aerial.tx_helpers import SubmittedTx from ...chain.aerial.client import LedgerClient, NetworkConfig from ...chain.aerial.client.utils import prepare_and_broadcast_basic_transaction +from v4_client_py.clients.constants import NETWORK_ID_MAINNET, NETWORK_ID_TESTNET class Post: def __init__( @@ -21,6 +22,17 @@ def __init__( ): self.config = config self.composer = Composer() + + def fetch_network_config(self): + if self.config.chain_id == NETWORK_ID_MAINNET: + return NetworkConfig.fetchai_mainnet() + elif self.config.chain_id == NETWORK_ID_TESTNET: + return NetworkConfig.fetch_dydx_testnet() + else: + raise Exception ( + 'Do not which network config to choose...' + 'Please set a proper one in /v4_client_py/clients/constants.py' + ) def send_message( self, @@ -43,10 +55,9 @@ def send_message( ''' wallet = subaccount.wallet - # here to be selected testent or mainnet network - #network = NetworkConfig.fetch_dydx_testnet() - network = NetworkConfig.fetchai_mainnet() + network = self.fetch_network_config() ledger = LedgerClient(network) + tx = Transaction() tx.add_message(msg) gas_limit = 0 if zeroFee else None From 834e0a0ea6cada43949cc43166e596496067dced Mon Sep 17 00:00:00 2001 From: carlos Date: Tue, 19 Dec 2023 15:40:46 +0200 Subject: [PATCH 04/18] fix readme md --- v4-client-py/examples/mainnet_examples/README.md | 6 ------ 1 file changed, 6 deletions(-) diff --git a/v4-client-py/examples/mainnet_examples/README.md b/v4-client-py/examples/mainnet_examples/README.md index fe4bb053..5a16083f 100644 --- a/v4-client-py/examples/mainnet_examples/README.md +++ b/v4-client-py/examples/mainnet_examples/README.md @@ -16,11 +16,5 @@ pip3 install -r requirements.txt ``` export PYTHONPATH='cd ~/.../v4-clients/v4-client-py' ``` -4. Set in v4_client_py/clients/modules/post.py the mainnet network instead of testnet (lines 46 to 48) -``` -# here to be selected testent or mainnet network -#network = NetworkConfig.fetch_dydx_testnet() -network = NetworkConfig.fetchai_mainnet() -``` Now you are ready to use the examples in this folder. \ No newline at end of file From d3ca7634ec2c4cef7e3d6f57375e24174109b15e Mon Sep 17 00:00:00 2001 From: carlos Date: Wed, 20 Dec 2023 09:11:14 +0200 Subject: [PATCH 05/18] > --- v4-client-py/v4_client_py/clients/constants.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/v4-client-py/v4_client_py/clients/constants.py b/v4-client-py/v4_client_py/clients/constants.py index 51c4bf1d..86920ca4 100644 --- a/v4-client-py/v4_client_py/clients/constants.py +++ b/v4-client-py/v4_client_py/clients/constants.py @@ -3,10 +3,10 @@ # ------------ API URLs ------------ -INDEXER_API_HOST_MAINNET = "https://indexer.dydx.trade/" +INDEXER_API_HOST_MAINNET = None INDEXER_API_HOST_TESTNET = 'https://dydx-testnet.imperator.co' -INDEXER_WS_HOST_MAINNET = "wss://indexer.dydx.trade/v4/ws" +INDEXER_WS_HOST_MAINNET = None INDEXER_WS_HOST_TESTNET = 'wss://indexer.v4testnet.dydx.exchange/v4/ws' FAUCET_API_HOST_TESTNET = 'https://faucet.v4testnet.dydx.exchange' @@ -14,11 +14,11 @@ VALIDATOR_API_HOST_MAINNET = None VALIDATOR_API_HOST_TESTNET = 'https://dydx-testnet-archive.allthatnode.com' -VALIDATOR_GRPC_MAINNET = "dydx-mainnet-full-grpc.public.blastapi.io:443" +VALIDATOR_GRPC_MAINNET = None VALIDATOR_GRPC_TESTNET = 'dydx-testnet-archive.allthatnode.com:9090' # ------------ Ethereum Network IDs ------------ -NETWORK_ID_MAINNET = "dydx-mainnet-1" +NETWORK_ID_MAINNET = None NETWORK_ID_TESTNET = 'dydx-testnet-4' # ------------ Market Statistic Day Types ------------ From 6bb13c7b104e22c3f2d31f7c1684628b6c720e86 Mon Sep 17 00:00:00 2001 From: carlos Date: Tue, 26 Dec 2023 19:02:33 +0200 Subject: [PATCH 06/18] add aerial configs --- .../mainnet_account_endpoints.py | 3 ++- .../mainnet_long_term_order_cancel_example.py | 4 +-- ...innet_long_term_order_composite_example.py | 4 +-- ...mainnet_short_term_order_cancel_example.py | 4 +-- ...nnet_short_term_order_composite_example.py | 4 +-- .../v4_client_py/chain/aerial/config.py | 26 +++++++++++-------- .../v4_client_py/clients/constants.py | 15 +++++++---- .../clients/dydx_composite_client.py | 3 +-- 8 files changed, 36 insertions(+), 27 deletions(-) diff --git a/v4-client-py/examples/mainnet_examples/mainnet_account_endpoints.py b/v4-client-py/examples/mainnet_examples/mainnet_account_endpoints.py index 325ffc89..4a3da12b 100644 --- a/v4-client-py/examples/mainnet_examples/mainnet_account_endpoints.py +++ b/v4-client-py/examples/mainnet_examples/mainnet_account_endpoints.py @@ -1,7 +1,8 @@ from v4_client_py.clients import IndexerClient, Subaccount from v4_client_py.clients.constants import Network +from tests.constants import DYDX_TEST_MNEMONIC -MNEMONIC = "" +MNEMONIC = DYDX_TEST_MNEMONIC client = IndexerClient( config=Network.mainnet().indexer_config, diff --git a/v4-client-py/examples/mainnet_examples/mainnet_long_term_order_cancel_example.py b/v4-client-py/examples/mainnet_examples/mainnet_long_term_order_cancel_example.py index 45f434ed..a993e55b 100644 --- a/v4-client-py/examples/mainnet_examples/mainnet_long_term_order_cancel_example.py +++ b/v4-client-py/examples/mainnet_examples/mainnet_long_term_order_cancel_example.py @@ -14,9 +14,9 @@ OrderExecution, ) -from tests.constants import MAX_CLIENT_ID +from tests.constants import DYDX_TEST_MNEMONIC, MAX_CLIENT_ID -MNEMONIC = "" +MNEMONIC = DYDX_TEST_MNEMONIC # define objects to be used with the SDK diff --git a/v4-client-py/examples/mainnet_examples/mainnet_long_term_order_composite_example.py b/v4-client-py/examples/mainnet_examples/mainnet_long_term_order_composite_example.py index fb6fc95e..42d0b1e7 100644 --- a/v4-client-py/examples/mainnet_examples/mainnet_long_term_order_composite_example.py +++ b/v4-client-py/examples/mainnet_examples/mainnet_long_term_order_composite_example.py @@ -14,9 +14,9 @@ OrderExecution, ) -from tests.constants import MAX_CLIENT_ID +from tests.constants import MAX_CLIENT_ID, DYDX_TEST_MNEMONIC -MNEMONIC = "" +MNEMONIC = DYDX_TEST_MNEMONIC # define objects to be used with the SDK wallet = LocalWallet.from_mnemonic(MNEMONIC, BECH32_PREFIX) diff --git a/v4-client-py/examples/mainnet_examples/mainnet_short_term_order_cancel_example.py b/v4-client-py/examples/mainnet_examples/mainnet_short_term_order_cancel_example.py index 6081142f..8d584dd1 100644 --- a/v4-client-py/examples/mainnet_examples/mainnet_short_term_order_cancel_example.py +++ b/v4-client-py/examples/mainnet_examples/mainnet_short_term_order_cancel_example.py @@ -11,9 +11,9 @@ Order_TimeInForce, OrderSide, ) -from tests.constants import MAX_CLIENT_ID +from tests.constants import MAX_CLIENT_ID, DYDX_TEST_MNEMONIC -MNEMONIC = "" +MNEMONIC = DYDX_TEST_MNEMONIC # define objects to be used with the SDK wallet = LocalWallet.from_mnemonic(MNEMONIC, BECH32_PREFIX) diff --git a/v4-client-py/examples/mainnet_examples/mainnet_short_term_order_composite_example.py b/v4-client-py/examples/mainnet_examples/mainnet_short_term_order_composite_example.py index 1d6bc1ba..9782df3f 100644 --- a/v4-client-py/examples/mainnet_examples/mainnet_short_term_order_composite_example.py +++ b/v4-client-py/examples/mainnet_examples/mainnet_short_term_order_composite_example.py @@ -11,9 +11,9 @@ Order_TimeInForce, OrderSide, ) -from tests.constants import MAX_CLIENT_ID +from tests.constants import MAX_CLIENT_ID, DYDX_TEST_MNEMONIC -MNEMONIC = "" +MNEMONIC = DYDX_TEST_MNEMONIC # define objects to be used with the SDK wallet = LocalWallet.from_mnemonic(MNEMONIC, BECH32_PREFIX) diff --git a/v4-client-py/v4_client_py/chain/aerial/config.py b/v4-client-py/v4_client_py/chain/aerial/config.py index 30e97601..3f4b9a40 100644 --- a/v4-client-py/v4_client_py/chain/aerial/config.py +++ b/v4-client-py/v4_client_py/chain/aerial/config.py @@ -1,16 +1,24 @@ - """Network configurations.""" import warnings from dataclasses import dataclass from typing import Optional, Union +from v4_client_py.clients.constants import ( + AERIAL_CONFIG_CHAIN_ID_TESTNET, + AERIAL_CONFIG_URL_TESTNET, + AERIAL_CONFIG_CHAIN_ID_MAINNET, + AERIAL_CONFIG_URL_MAINNET, +) + + class NetworkConfigError(RuntimeError): """Network config error. :param RuntimeError: Runtime error """ + URL_PREFIXES = ( "grpc+https", "grpc+http", @@ -45,16 +53,12 @@ def validate(self): raise NetworkConfigError("URL must be set") if not any( map( - lambda x: self.url.startswith( # noqa: # pylint: disable=unnecessary-lambda - x - ), + lambda x: self.url.startswith(x), # noqa: # pylint: disable=unnecessary-lambda URL_PREFIXES, ) ): prefix_list = ", ".join(map(lambda x: f'"{x}"', URL_PREFIXES)) - raise NetworkConfigError( - f"URL must start with one of the following prefixes: {prefix_list}" - ) + raise NetworkConfigError(f"URL must start with one of the following prefixes: {prefix_list}") @classmethod def fetchai_dorado_testnet(cls) -> "NetworkConfig": @@ -78,8 +82,8 @@ def fetch_dydx_testnet(cls) -> "NetworkConfig": :return: Network configuration """ return NetworkConfig( - chain_id="dydx-testnet-4", - url="grpc+https://dydx-testnet-archive.allthatnode.com:9090", + chain_id=AERIAL_CONFIG_CHAIN_ID_TESTNET, + url=f"grpc+{AERIAL_CONFIG_URL_TESTNET}", fee_minimum_gas_price=4630550000000000, fee_denomination="adv4tnt", staking_denomination="dv4tnt", @@ -117,8 +121,8 @@ def fetchai_mainnet(cls) -> "NetworkConfig": :return: fetch mainnet configuration """ return NetworkConfig( - chain_id="dydx-mainnet-1", - url="grpc+https://grpc.dydx.nodestake.top", + chain_id=AERIAL_CONFIG_CHAIN_ID_MAINNET, + url=f"rest+{AERIAL_CONFIG_URL_MAINNET}", fee_minimum_gas_price=0, fee_denomination="afet", staking_denomination="afet", diff --git a/v4-client-py/v4_client_py/clients/constants.py b/v4-client-py/v4_client_py/clients/constants.py index 86920ca4..45984460 100644 --- a/v4-client-py/v4_client_py/clients/constants.py +++ b/v4-client-py/v4_client_py/clients/constants.py @@ -1,12 +1,10 @@ from enum import Enum -from ..chain.aerial.config import NetworkConfig - # ------------ API URLs ------------ INDEXER_API_HOST_MAINNET = None INDEXER_API_HOST_TESTNET = 'https://dydx-testnet.imperator.co' -INDEXER_WS_HOST_MAINNET = None +INDEXER_WS_HOST_MAINNET = None INDEXER_WS_HOST_TESTNET = 'wss://indexer.v4testnet.dydx.exchange/v4/ws' FAUCET_API_HOST_TESTNET = 'https://faucet.v4testnet.dydx.exchange' @@ -14,13 +12,20 @@ VALIDATOR_API_HOST_MAINNET = None VALIDATOR_API_HOST_TESTNET = 'https://dydx-testnet-archive.allthatnode.com' -VALIDATOR_GRPC_MAINNET = None +VALIDATOR_GRPC_MAINNET = None VALIDATOR_GRPC_TESTNET = 'dydx-testnet-archive.allthatnode.com:9090' -# ------------ Ethereum Network IDs ------------ +# ------------ Ethereum Network IDs../../v4_client_py/clients/constants.py ------------ NETWORK_ID_MAINNET = None NETWORK_ID_TESTNET = 'dydx-testnet-4' +# ----------- Aerial configs ------------------- +AERIAL_CONFIG_CHAIN_ID_TESTNET = "dydx-testnet-4" +AERIAL_CONFIG_CHAIN_ID_MAINNET = None + +AERIAL_CONFIG_URL_TESTNET = "https://dydx-testnet-archive.allthatnode.com:9090" +AERIAL_CONFIG_URL_MAINNET = None + # ------------ Market Statistic Day Types ------------ MARKET_STATISTIC_DAY_ONE = '1' MARKET_STATISTIC_DAY_SEVEN = '7' diff --git a/v4-client-py/v4_client_py/clients/dydx_composite_client.py b/v4-client-py/v4_client_py/clients/dydx_composite_client.py index 11d71f87..486acf66 100644 --- a/v4-client-py/v4_client_py/clients/dydx_composite_client.py +++ b/v4-client-py/v4_client_py/clients/dydx_composite_client.py @@ -61,8 +61,7 @@ def generate_good_til_fields( good_til_block: int, good_til_time_in_seconds: int, ) -> Tuple[int, int]: - is_stateful_order = is_order_flag_stateful_order(order_flags) - if is_stateful_order: + if is_stateful_order := is_order_flag_stateful_order(order_flags): return 0, self.calculate_good_til_block_time(good_til_time_in_seconds) else: return good_til_block, 0 From 41ac8a4620354941bcc83c3eb8cfdddbefad5f5f Mon Sep 17 00:00:00 2001 From: carlos Date: Tue, 26 Dec 2023 19:16:01 +0200 Subject: [PATCH 07/18] rm unnecessary line --- v4-client-py/v4_client_py/clients/constants.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/v4-client-py/v4_client_py/clients/constants.py b/v4-client-py/v4_client_py/clients/constants.py index 45984460..206b227c 100644 --- a/v4-client-py/v4_client_py/clients/constants.py +++ b/v4-client-py/v4_client_py/clients/constants.py @@ -15,7 +15,7 @@ VALIDATOR_GRPC_MAINNET = None VALIDATOR_GRPC_TESTNET = 'dydx-testnet-archive.allthatnode.com:9090' -# ------------ Ethereum Network IDs../../v4_client_py/clients/constants.py ------------ +# ------------ Ethereum Network IDs------------ NETWORK_ID_MAINNET = None NETWORK_ID_TESTNET = 'dydx-testnet-4' From a7156f00e1b5a939e6942767eebf358a5bb2568f Mon Sep 17 00:00:00 2001 From: carlos Date: Fri, 5 Jan 2024 15:48:43 +0200 Subject: [PATCH 08/18] > --- v4-client-py/v4_client_py/clients/constants.py | 1 + 1 file changed, 1 insertion(+) diff --git a/v4-client-py/v4_client_py/clients/constants.py b/v4-client-py/v4_client_py/clients/constants.py index 206b227c..eba47f33 100644 --- a/v4-client-py/v4_client_py/clients/constants.py +++ b/v4-client-py/v4_client_py/clients/constants.py @@ -1,5 +1,6 @@ from enum import Enum +#TODO: Add mainnet # ------------ API URLs ------------ INDEXER_API_HOST_MAINNET = None INDEXER_API_HOST_TESTNET = 'https://dydx-testnet.imperator.co' From fd8f6509e95bf13976cae9c41b529a3fcfd79f18 Mon Sep 17 00:00:00 2001 From: carlos Date: Tue, 9 Jan 2024 20:42:41 +0200 Subject: [PATCH 09/18] add prefix url in constants --- v4-client-py/v4_client_py/chain/aerial/config.py | 5 +++-- v4-client-py/v4_client_py/clients/constants.py | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/v4-client-py/v4_client_py/chain/aerial/config.py b/v4-client-py/v4_client_py/chain/aerial/config.py index 3f4b9a40..08671fba 100644 --- a/v4-client-py/v4_client_py/chain/aerial/config.py +++ b/v4-client-py/v4_client_py/chain/aerial/config.py @@ -9,6 +9,7 @@ AERIAL_CONFIG_URL_TESTNET, AERIAL_CONFIG_CHAIN_ID_MAINNET, AERIAL_CONFIG_URL_MAINNET, + GRPC_OR_REST, ) @@ -83,7 +84,7 @@ def fetch_dydx_testnet(cls) -> "NetworkConfig": """ return NetworkConfig( chain_id=AERIAL_CONFIG_CHAIN_ID_TESTNET, - url=f"grpc+{AERIAL_CONFIG_URL_TESTNET}", + url=f"{GRPC_OR_REST}+{AERIAL_CONFIG_URL_TESTNET}", fee_minimum_gas_price=4630550000000000, fee_denomination="adv4tnt", staking_denomination="dv4tnt", @@ -122,7 +123,7 @@ def fetchai_mainnet(cls) -> "NetworkConfig": """ return NetworkConfig( chain_id=AERIAL_CONFIG_CHAIN_ID_MAINNET, - url=f"rest+{AERIAL_CONFIG_URL_MAINNET}", + url=f"{GRPC_OR_REST}+{AERIAL_CONFIG_URL_MAINNET}", fee_minimum_gas_price=0, fee_denomination="afet", staking_denomination="afet", diff --git a/v4-client-py/v4_client_py/clients/constants.py b/v4-client-py/v4_client_py/clients/constants.py index eba47f33..ed74f21d 100644 --- a/v4-client-py/v4_client_py/clients/constants.py +++ b/v4-client-py/v4_client_py/clients/constants.py @@ -24,6 +24,7 @@ AERIAL_CONFIG_CHAIN_ID_TESTNET = "dydx-testnet-4" AERIAL_CONFIG_CHAIN_ID_MAINNET = None +GRPC_OR_REST = 'grpc' AERIAL_CONFIG_URL_TESTNET = "https://dydx-testnet-archive.allthatnode.com:9090" AERIAL_CONFIG_URL_MAINNET = None From 8642130da2600a1f9b5d53e0c44f1bfca9e9247c Mon Sep 17 00:00:00 2001 From: carlos Date: Tue, 9 Jan 2024 20:44:46 +0200 Subject: [PATCH 10/18] separate prefixes for mainnet and testnet --- v4-client-py/v4_client_py/chain/aerial/config.py | 7 ++++--- v4-client-py/v4_client_py/clients/constants.py | 4 +++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/v4-client-py/v4_client_py/chain/aerial/config.py b/v4-client-py/v4_client_py/chain/aerial/config.py index 08671fba..3dc5df1a 100644 --- a/v4-client-py/v4_client_py/chain/aerial/config.py +++ b/v4-client-py/v4_client_py/chain/aerial/config.py @@ -9,7 +9,8 @@ AERIAL_CONFIG_URL_TESTNET, AERIAL_CONFIG_CHAIN_ID_MAINNET, AERIAL_CONFIG_URL_MAINNET, - GRPC_OR_REST, + GRPC_OR_REST_MAINNET, + GRPC_OR_REST_TESTNET, ) @@ -84,7 +85,7 @@ def fetch_dydx_testnet(cls) -> "NetworkConfig": """ return NetworkConfig( chain_id=AERIAL_CONFIG_CHAIN_ID_TESTNET, - url=f"{GRPC_OR_REST}+{AERIAL_CONFIG_URL_TESTNET}", + url=f"{GRPC_OR_REST_TESTNET}+{AERIAL_CONFIG_URL_TESTNET}", fee_minimum_gas_price=4630550000000000, fee_denomination="adv4tnt", staking_denomination="dv4tnt", @@ -123,7 +124,7 @@ def fetchai_mainnet(cls) -> "NetworkConfig": """ return NetworkConfig( chain_id=AERIAL_CONFIG_CHAIN_ID_MAINNET, - url=f"{GRPC_OR_REST}+{AERIAL_CONFIG_URL_MAINNET}", + url=f"{GRPC_OR_REST_MAINNET}+{AERIAL_CONFIG_URL_MAINNET}", fee_minimum_gas_price=0, fee_denomination="afet", staking_denomination="afet", diff --git a/v4-client-py/v4_client_py/clients/constants.py b/v4-client-py/v4_client_py/clients/constants.py index ed74f21d..d0b60661 100644 --- a/v4-client-py/v4_client_py/clients/constants.py +++ b/v4-client-py/v4_client_py/clients/constants.py @@ -24,7 +24,9 @@ AERIAL_CONFIG_CHAIN_ID_TESTNET = "dydx-testnet-4" AERIAL_CONFIG_CHAIN_ID_MAINNET = None -GRPC_OR_REST = 'grpc' +GRPC_OR_REST_TESTNET = 'grpc' +GRPC_OR_REST_MAINNET = None + AERIAL_CONFIG_URL_TESTNET = "https://dydx-testnet-archive.allthatnode.com:9090" AERIAL_CONFIG_URL_MAINNET = None From 48394612d579ba2255ce2ec4d1a8be6f5fb41c15 Mon Sep 17 00:00:00 2001 From: carlos Date: Tue, 9 Jan 2024 20:50:20 +0200 Subject: [PATCH 11/18] update urls endpoint for testnet --- v4-client-py/v4_client_py/clients/constants.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/v4-client-py/v4_client_py/clients/constants.py b/v4-client-py/v4_client_py/clients/constants.py index d0b60661..7cc11669 100644 --- a/v4-client-py/v4_client_py/clients/constants.py +++ b/v4-client-py/v4_client_py/clients/constants.py @@ -14,7 +14,7 @@ VALIDATOR_API_HOST_TESTNET = 'https://dydx-testnet-archive.allthatnode.com' VALIDATOR_GRPC_MAINNET = None -VALIDATOR_GRPC_TESTNET = 'dydx-testnet-archive.allthatnode.com:9090' +VALIDATOR_GRPC_TESTNET = 'https://test-dydx-grpc.kingnodes.com:443' # ------------ Ethereum Network IDs------------ NETWORK_ID_MAINNET = None @@ -27,7 +27,7 @@ GRPC_OR_REST_TESTNET = 'grpc' GRPC_OR_REST_MAINNET = None -AERIAL_CONFIG_URL_TESTNET = "https://dydx-testnet-archive.allthatnode.com:9090" +AERIAL_CONFIG_URL_TESTNET = 'https://test-dydx-grpc.kingnodes.com:443' AERIAL_CONFIG_URL_MAINNET = None # ------------ Market Statistic Day Types ------------ From 3631129367f5614f913d9d55d5e2f431e76385b4 Mon Sep 17 00:00:00 2001 From: carlos Date: Tue, 9 Jan 2024 20:51:13 +0200 Subject: [PATCH 12/18] update validator api host testnet url --- v4-client-py/v4_client_py/clients/constants.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/v4-client-py/v4_client_py/clients/constants.py b/v4-client-py/v4_client_py/clients/constants.py index 7cc11669..597098a7 100644 --- a/v4-client-py/v4_client_py/clients/constants.py +++ b/v4-client-py/v4_client_py/clients/constants.py @@ -11,7 +11,7 @@ FAUCET_API_HOST_TESTNET = 'https://faucet.v4testnet.dydx.exchange' VALIDATOR_API_HOST_MAINNET = None -VALIDATOR_API_HOST_TESTNET = 'https://dydx-testnet-archive.allthatnode.com' +VALIDATOR_API_HOST_TESTNET = 'https://test-dydx.kingnodes.com' VALIDATOR_GRPC_MAINNET = None VALIDATOR_GRPC_TESTNET = 'https://test-dydx-grpc.kingnodes.com:443' From f1f79c4fae6e10300851434ca880171808b59048 Mon Sep 17 00:00:00 2001 From: carlos Date: Sat, 13 Jan 2024 11:09:40 +0200 Subject: [PATCH 13/18] switch to good_til_block --- .../mainnet_long_term_order_cancel_example.py | 6 +++--- .../mainnet_long_term_order_composite_example.py | 4 ++-- .../mainnet_short_term_order_cancel_example.py | 6 +++--- .../mainnet_short_term_order_composite_example.py | 4 ++-- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/v4-client-py/examples/mainnet_examples/mainnet_long_term_order_cancel_example.py b/v4-client-py/examples/mainnet_examples/mainnet_long_term_order_cancel_example.py index a993e55b..94473876 100644 --- a/v4-client-py/examples/mainnet_examples/mainnet_long_term_order_cancel_example.py +++ b/v4-client-py/examples/mainnet_examples/mainnet_long_term_order_cancel_example.py @@ -38,7 +38,7 @@ def define_order() -> dict: "size": 0.01, "client_id": randrange(0, MAX_CLIENT_ID), "time_in_force": OrderTimeInForce.GTT, - "good_till_block": 0, + "good_til_block": 0, # long term orders use GTBT "good_til_time_in_seconds": 60, "execution": OrderExecution.DEFAULT, @@ -70,7 +70,7 @@ async def main() -> None: size=order["size"], client_id=order["client_id"], time_in_force=order["time_in_force"], - good_til_block=order["good_till_block"], + good_til_block=order["good_til_block"], good_til_time_in_seconds=order["good_til_time_in_seconds"], execution=order["execution"], post_only=order["post_only"], @@ -90,7 +90,7 @@ async def main() -> None: market=order["market"], order_flags=ORDER_FLAGS_LONG_TERM, good_til_time_in_seconds=order["good_til_time_in_seconds"], - good_til_block=order["good_till_block"], # long term orders use GTBT + good_til_block=order["good_til_block"], # long term orders use GTBT ) print("**Cancel Long Term Order Tx**") print(tx.tx_hash) diff --git a/v4-client-py/examples/mainnet_examples/mainnet_long_term_order_composite_example.py b/v4-client-py/examples/mainnet_examples/mainnet_long_term_order_composite_example.py index 42d0b1e7..4bbae244 100644 --- a/v4-client-py/examples/mainnet_examples/mainnet_long_term_order_composite_example.py +++ b/v4-client-py/examples/mainnet_examples/mainnet_long_term_order_composite_example.py @@ -37,7 +37,7 @@ def define_order() -> dict: "size": 0.01, "client_id": randrange(0, MAX_CLIENT_ID), "time_in_force": OrderTimeInForce.GTT, - "good_till_block": 0, + "good_til_block": 0, # long term orders use GTBT "good_til_time_in_seconds": 60, "execution": OrderExecution.DEFAULT, @@ -69,7 +69,7 @@ async def main() -> None: size=order["size"], client_id=order["client_id"], time_in_force=order["time_in_force"], - good_til_block=order["good_till_block"], + good_til_block=order["good_til_block"], good_til_time_in_seconds=order["good_til_time_in_seconds"], execution=order["execution"], post_only=order["post_only"], diff --git a/v4-client-py/examples/mainnet_examples/mainnet_short_term_order_cancel_example.py b/v4-client-py/examples/mainnet_examples/mainnet_short_term_order_cancel_example.py index 8d584dd1..6f2ba202 100644 --- a/v4-client-py/examples/mainnet_examples/mainnet_short_term_order_cancel_example.py +++ b/v4-client-py/examples/mainnet_examples/mainnet_short_term_order_cancel_example.py @@ -32,7 +32,7 @@ def define_order() -> dict: "price": 40000, "size": 0.01, "client_id": randrange(0, MAX_CLIENT_ID), - "good_till_block": client.get_current_block() + 11, + "good_til_block": client.get_current_block() + 11, # Note, you can change this to any number between `current_block+1` # to `current_block+1 + SHORT_BLOCK_WINDOW` "time_in_force": Order_TimeInForce.TIME_IN_FORCE_UNSPECIFIED, @@ -50,7 +50,7 @@ async def main() -> None: price=order["price"], size=order["size"], client_id=order["client_id"], - good_til_block=order["good_till_block"], + good_til_block=order["good_til_block"], time_in_force=order["time_in_force"], reduce_only=order["reduce_only"], ) @@ -68,7 +68,7 @@ async def main() -> None: market=order["market"], order_flags=ORDER_FLAGS_SHORT_TERM, good_til_time_in_seconds=0, # short term orders use GTB. - good_til_block=order["good_till_block"], # GTB should be the same or greater than order to cancel + good_til_block=order["good_til_block"], # GTB should be the same or greater than order to cancel ) print("**Cancel Short Term Order Tx**") print(tx.tx_hash) diff --git a/v4-client-py/examples/mainnet_examples/mainnet_short_term_order_composite_example.py b/v4-client-py/examples/mainnet_examples/mainnet_short_term_order_composite_example.py index 9782df3f..40da9080 100644 --- a/v4-client-py/examples/mainnet_examples/mainnet_short_term_order_composite_example.py +++ b/v4-client-py/examples/mainnet_examples/mainnet_short_term_order_composite_example.py @@ -32,7 +32,7 @@ def define_order() -> dict: "price": 40000, "size": 0.01, "client_id": randrange(0, MAX_CLIENT_ID), - "good_till_block": client.get_current_block() + 11, + "good_til_block": client.get_current_block() + 11, # Note, you can change this to any number between `current_block+1` # to `current_block+1 + SHORT_BLOCK_WINDOW` "time_in_force": Order_TimeInForce.TIME_IN_FORCE_UNSPECIFIED, @@ -50,7 +50,7 @@ async def main() -> None: price=order["price"], size=order["size"], client_id=order["client_id"], - good_til_block=order["good_till_block"], + good_til_block=order["good_til_block"], time_in_force=order["time_in_force"], reduce_only=order["reduce_only"], ) From 711302c81d45fe74643dfdc25ae15dc3626aca88 Mon Sep 17 00:00:00 2001 From: carlos Date: Thu, 18 Jan 2024 12:18:23 +0200 Subject: [PATCH 14/18] add working version of new configs --- .../examples/mainnet_examples/README.md | 17 +++++++++++++++-- ...mainnet_short_term_order_cancel_example.py | 19 ++++++++++++++++++- .../mainnet_examples/mainnet_ws_get_fills.py | 1 + 3 files changed, 34 insertions(+), 3 deletions(-) diff --git a/v4-client-py/examples/mainnet_examples/README.md b/v4-client-py/examples/mainnet_examples/README.md index 5a16083f..3770da35 100644 --- a/v4-client-py/examples/mainnet_examples/README.md +++ b/v4-client-py/examples/mainnet_examples/README.md @@ -14,7 +14,20 @@ pip3 install -r requirements.txt ``` 3. Export PYTHONPATH for your current location ``` -export PYTHONPATH='cd ~/.../v4-clients/v4-client-py' +export PYTHONPATH='~/.../v4-clients/v4-client-py' +``` + +Now you are ready to use the examples in this folder. + +# Set up your configurations to run example files + +``` +VALIDATOR_GRPC_ENDPOINT = <> +AERIAL_CONFIG_URL = <> +AERIAL_GRPC_OR_REST_PREFIX = <> +INDEXER_REST_ENDPOINT = <> +INDEXER_WS_ENDPOINT = <> +CHAIN_ID = <> +ENV = <> ``` -Now you are ready to use the examples in this folder. \ No newline at end of file diff --git a/v4-client-py/examples/mainnet_examples/mainnet_short_term_order_cancel_example.py b/v4-client-py/examples/mainnet_examples/mainnet_short_term_order_cancel_example.py index 6f2ba202..b8ca6657 100644 --- a/v4-client-py/examples/mainnet_examples/mainnet_short_term_order_cancel_example.py +++ b/v4-client-py/examples/mainnet_examples/mainnet_short_term_order_cancel_example.py @@ -15,9 +15,26 @@ MNEMONIC = DYDX_TEST_MNEMONIC +VALIDATOR_GRPC_ENDPOINT = "test-dydx-grpc.kingnodes.com:443" +AERIAL_CONFIG_URL = "https://test-dydx-grpc.kingnodes.com:443" +AERIAL_GRPC_OR_REST_PREFIX = "grpc" +INDEXER_REST_ENDPOINT = "https://dydx-testnet.imperator.co" +INDEXER_WS_ENDPOINT = "wss://indexer.v4testnet.dydx.exchange/v4/ws" +CHAIN_ID = "dydx-testnet-4" +ENV = "testnet" + + # define objects to be used with the SDK wallet = LocalWallet.from_mnemonic(MNEMONIC, BECH32_PREFIX) -network = Network.mainnet() +network = Network.config_network( + validator_grpc_endpoint=VALIDATOR_GRPC_ENDPOINT, + rest_endpoint=INDEXER_REST_ENDPOINT, + grpc_or_rest_prefix=AERIAL_GRPC_OR_REST_PREFIX, + aerial_url=AERIAL_CONFIG_URL, + websocket_endpoint=INDEXER_WS_ENDPOINT, + chain_id=CHAIN_ID, + env=ENV, +) client = CompositeClient( network, ) diff --git a/v4-client-py/examples/mainnet_examples/mainnet_ws_get_fills.py b/v4-client-py/examples/mainnet_examples/mainnet_ws_get_fills.py index 7742f61e..a954cfa0 100644 --- a/v4-client-py/examples/mainnet_examples/mainnet_ws_get_fills.py +++ b/v4-client-py/examples/mainnet_examples/mainnet_ws_get_fills.py @@ -6,6 +6,7 @@ ADDRESS = "" + def for_fills(fills_data): try: for fill in fills_data: From 70b9826d1a1a1689ce9a139c4b6a34dfc17c7eba Mon Sep 17 00:00:00 2001 From: carlos Date: Thu, 18 Jan 2024 12:42:04 +0200 Subject: [PATCH 15/18] add custom network --- v4-client-py/examples/account_endpoints.py | 88 +++++----- v4-client-py/examples/chain_client/Account.py | 6 +- .../examples/chain_client/BankBalance.py | 8 +- .../examples/chain_client/BankBalances.py | 8 +- v4-client-py/examples/chain_client/GetTx.py | 10 +- v4-client-py/examples/chain_client/test.py | 2 +- v4-client-py/examples/composite_example.py | 37 ++-- v4-client-py/examples/faucet_endpoint.py | 8 +- .../long_term_order_cancel_example.py | 33 ++-- .../examples/mainnet_examples/README.md | 3 +- .../mainnet_account_endpoints.py | 6 +- .../mainnet_long_term_order_cancel_example.py | 9 +- ...innet_long_term_order_composite_example.py | 8 +- ...mainnet_short_term_order_cancel_example.py | 23 +-- ...nnet_short_term_order_composite_example.py | 8 +- v4-client-py/examples/markets_endpoints.py | 62 +++---- .../short_term_order_cancel_example.py | 30 ++-- .../short_term_order_composite_example.py | 25 +-- .../examples/transfer_example_deposit.py | 9 +- .../transfer_example_subaccount_transfer.py | 9 +- .../examples/transfer_example_withdraw.py | 9 +- v4-client-py/examples/utility_endpoints.py | 18 +- v4-client-py/examples/utils.py | 6 +- .../examples/validator_get_examples.py | 49 +++--- .../examples/validator_post_examples.py | 15 +- v4-client-py/examples/wallet_address.py | 6 +- v4-client-py/examples/websocket_example.py | 30 ++-- .../v4_client_py/chain/aerial/config.py | 66 ++----- .../v4_client_py/clients/constants.py | 158 +++++++---------- .../clients/dydx_composite_client.py | 162 +++++++++--------- .../v4_client_py/clients/modules/post.py | 100 +++++------ 31 files changed, 453 insertions(+), 558 deletions(-) diff --git a/v4-client-py/examples/account_endpoints.py b/v4-client-py/examples/account_endpoints.py index 6dc80828..5fb417cd 100644 --- a/v4-client-py/examples/account_endpoints.py +++ b/v4-client-py/examples/account_endpoints.py @@ -1,7 +1,7 @@ -'''Example for placing, replacing, and canceling orders. +"""Example for placing, replacing, and canceling orders. Usage: python -m examples.private_endpoints -''' +""" from v4_client_py.clients import IndexerClient, Subaccount from v4_client_py.clients.constants import Network @@ -9,114 +9,112 @@ from tests.constants import DYDX_TEST_MNEMONIC client = IndexerClient( - config=Network.testnet().indexer_config, + config=Network.config_network().indexer_config, ) try: subaccount = Subaccount.from_mnemonic(DYDX_TEST_MNEMONIC) address = subaccount.address - # Get subaccounts try: subaccounts_response = client.account.get_subaccounts(address) - print(f'{subaccounts_response.data}') - subaccounts = subaccounts_response.data['subaccounts'] + print(f"{subaccounts_response.data}") + subaccounts = subaccounts_response.data["subaccounts"] subaccount_0 = subaccounts[0] - print(f'{subaccount_0}') - subaccount_0_subaccountNumber = subaccount_0['subaccountNumber'] + print(f"{subaccount_0}") + subaccount_0_subaccountNumber = subaccount_0["subaccountNumber"] except: - print('failed to get subaccounts') + print("failed to get subaccounts") try: subaccount_response = client.account.get_subaccount(address, 0) - print(f'{subaccount_response.data}') - subaccount = subaccount_response.data['subaccount'] - print(f'{subaccount}') - subaccount_subaccountNumber = subaccount['subaccountNumber'] + print(f"{subaccount_response.data}") + subaccount = subaccount_response.data["subaccount"] + print(f"{subaccount}") + subaccount_subaccountNumber = subaccount["subaccountNumber"] except: - print('failed to get subaccount') + print("failed to get subaccount") # Get positions try: asset_positions_response = client.account.get_subaccount_asset_positions(address, 0) - print(f'{asset_positions_response.data}') - asset_positions = asset_positions_response.data['positions'] + print(f"{asset_positions_response.data}") + asset_positions = asset_positions_response.data["positions"] if len(asset_positions) > 0: asset_positions_0 = asset_positions[0] - print(f'{asset_positions_0}') + print(f"{asset_positions_0}") except: - print('failed to get asset positions') + print("failed to get asset positions") try: perpetual_positions_response = client.account.get_subaccount_perpetual_positions(address, 0) - print(f'{perpetual_positions_response.data}') - perpetual_positions = perpetual_positions_response.data['positions'] + print(f"{perpetual_positions_response.data}") + perpetual_positions = perpetual_positions_response.data["positions"] if len(perpetual_positions) > 0: perpetual_positions_0 = perpetual_positions[0] - print(f'{perpetual_positions_0}') + print(f"{perpetual_positions_0}") except: - print('failed to get perpetual positions') + print("failed to get perpetual positions") # Get transfers try: transfers_response = client.account.get_subaccount_transfers(address, 0) - print(f'{transfers_response.data}') - transfers = transfers_response.data['transfers'] + print(f"{transfers_response.data}") + transfers = transfers_response.data["transfers"] if len(transfers) > 0: transfers_0 = transfers[0] - print(f'{transfers_0}') + print(f"{transfers_0}") except: - print('failed to get transfers') + print("failed to get transfers") # Get orders try: orders_response = client.account.get_subaccount_orders(address, 0) - print(f'{orders_response.data}') + print(f"{orders_response.data}") orders = orders_response.data if len(orders) > 0: order_0 = orders[0] - print(f'{order_0}') - order_0_id = order_0['id'] + print(f"{order_0}") + order_0_id = order_0["id"] order_response = client.account.get_order(order_id=order_0_id) order = order_response.data - order_id = order['id'] + order_id = order["id"] except: - print('failed to get orders') - + print("failed to get orders") # Get fills try: fills_response = client.account.get_subaccount_fills(address, 0) - print(f'{fills_response.data}') - fills = fills_response.data['fills'] + print(f"{fills_response.data}") + fills = fills_response.data["fills"] if len(fills) > 0: fill_0 = fills[0] - print(f'{fill_0}') + print(f"{fill_0}") except: - print('failed to get fills') + print("failed to get fills") # Get funding try: funding_response = client.account.get_subaccount_funding(address, 0) - print(f'{funding_response.data}') - funding = funding_response.data['fundingPayments'] + print(f"{funding_response.data}") + funding = funding_response.data["fundingPayments"] if len(funding) > 0: funding_0 = funding[0] - print(f'{funding_0}') + print(f"{funding_0}") except: - print('failed to get funding') + print("failed to get funding") # Get historical pnl try: historical_pnl_response = client.account.get_subaccount_historical_pnls(address, 0) - print(f'{historical_pnl_response.data}') - historical_pnl = historical_pnl_response.data['historicalPnl'] + print(f"{historical_pnl_response.data}") + historical_pnl = historical_pnl_response.data["historicalPnl"] if len(historical_pnl) > 0: historical_pnl_0 = historical_pnl[0] - print(f'{historical_pnl_0}') + print(f"{historical_pnl_0}") except: - print('failed to get historical pnl') + print("failed to get historical pnl") except: - print('from_mnemonic failed') \ No newline at end of file + print("from_mnemonic failed") diff --git a/v4-client-py/examples/chain_client/Account.py b/v4-client-py/examples/chain_client/Account.py index 2dc29c35..e7b46aa6 100644 --- a/v4-client-py/examples/chain_client/Account.py +++ b/v4-client-py/examples/chain_client/Account.py @@ -7,15 +7,17 @@ from tests.constants import DYDX_TEST_MNEMONIC client = ValidatorClient( - config=Network.testnet().validator_config, + config=Network.testnet().validator_config, ) subaccount = Subaccount.from_mnemonic(DYDX_TEST_MNEMONIC) address = subaccount.address + async def main() -> None: acc = client.get.account(address=address) print(acc) -if __name__ == '__main__': + +if __name__ == "__main__": logging.basicConfig(level=logging.INFO) asyncio.get_event_loop().run_until_complete(main()) diff --git a/v4-client-py/examples/chain_client/BankBalance.py b/v4-client-py/examples/chain_client/BankBalance.py index 17f558ed..6e52c1e9 100644 --- a/v4-client-py/examples/chain_client/BankBalance.py +++ b/v4-client-py/examples/chain_client/BankBalance.py @@ -8,16 +8,18 @@ from tests.constants import DYDX_TEST_MNEMONIC client = ValidatorClient( - config=Network.testnet().validator_config, + config=Network.testnet().validator_config, ) subaccount = Subaccount.from_mnemonic(DYDX_TEST_MNEMONIC) address = subaccount.address + async def main() -> None: denom = "USDC" bank_balance = await client.get.bank_balance(address=address, denom=denom) print(bank_balance) -if __name__ == '__main__': + +if __name__ == "__main__": logging.basicConfig(level=logging.INFO) - asyncio.get_event_loop().run_until_complete(main()) \ No newline at end of file + asyncio.get_event_loop().run_until_complete(main()) diff --git a/v4-client-py/examples/chain_client/BankBalances.py b/v4-client-py/examples/chain_client/BankBalances.py index 6605d0f2..2c11646f 100644 --- a/v4-client-py/examples/chain_client/BankBalances.py +++ b/v4-client-py/examples/chain_client/BankBalances.py @@ -8,15 +8,17 @@ from tests.constants import DYDX_TEST_MNEMONIC client = ValidatorClient( - config=Network.testnet().validator_config, + config=Network.testnet().validator_config, ) subaccount = Subaccount.from_mnemonic(DYDX_TEST_MNEMONIC) address = subaccount.address + async def main() -> None: all_bank_balances = await client.get.bank_balances(address=address) print(all_bank_balances) -if __name__ == '__main__': + +if __name__ == "__main__": logging.basicConfig(level=logging.INFO) - asyncio.get_event_loop().run_until_complete(main()) \ No newline at end of file + asyncio.get_event_loop().run_until_complete(main()) diff --git a/v4-client-py/examples/chain_client/GetTx.py b/v4-client-py/examples/chain_client/GetTx.py index 2a4d9927..b61c736d 100644 --- a/v4-client-py/examples/chain_client/GetTx.py +++ b/v4-client-py/examples/chain_client/GetTx.py @@ -7,16 +7,18 @@ from tests.constants import DYDX_TEST_MNEMONIC client = ValidatorClient( - config=Network.testnet().validator_config, + config=Network.testnet().validator_config, ) subaccount = Subaccount.from_mnemonic(DYDX_TEST_MNEMONIC) address = subaccount.address + async def main() -> None: - tx_hash = '8247FEF19BB29BD93922803E9919620252DBC0BA4BE7D96E212D8F5EBC122B48' + tx_hash = "8247FEF19BB29BD93922803E9919620252DBC0BA4BE7D96E212D8F5EBC122B48" tx_logs = await client.get.tx(tx_hash=tx_hash) print(tx_logs) -if __name__ == '__main__': + +if __name__ == "__main__": logging.basicConfig(level=logging.INFO) - asyncio.get_event_loop().run_until_complete(main()) \ No newline at end of file + asyncio.get_event_loop().run_until_complete(main()) diff --git a/v4-client-py/examples/chain_client/test.py b/v4-client-py/examples/chain_client/test.py index 39a6e96f..c224f55a 100644 --- a/v4-client-py/examples/chain_client/test.py +++ b/v4-client-py/examples/chain_client/test.py @@ -1 +1 @@ -test='123' \ No newline at end of file +test = "123" diff --git a/v4-client-py/examples/composite_example.py b/v4-client-py/examples/composite_example.py index 04f5b2c9..da34d9ba 100644 --- a/v4-client-py/examples/composite_example.py +++ b/v4-client-py/examples/composite_example.py @@ -1,7 +1,7 @@ -'''Example for trading with human readable numbers +"""Example for trading with human readable numbers Usage: python -m examples.composite_example -''' +""" import asyncio import logging from random import randrange @@ -10,9 +10,9 @@ from v4_client_py.clients.constants import BECH32_PREFIX, Network from v4_client_py.clients.helpers.chain_helpers import ( - OrderType, - OrderSide, - OrderTimeInForce, + OrderType, + OrderSide, + OrderTimeInForce, OrderExecution, ) from examples.utils import loadJson @@ -22,12 +22,12 @@ async def main() -> None: wallet = LocalWallet.from_mnemonic(DYDX_TEST_MNEMONIC, BECH32_PREFIX) - network = Network.testnet() + network = Network.config_network() client = CompositeClient( network, ) subaccount = Subaccount(wallet, 0) - ordersParams = loadJson('human_readable_orders.json') + ordersParams = loadJson("human_readable_orders.json") for orderParams in ordersParams: type = OrderType[orderParams["type"]] side = OrderSide[orderParams["side"]] @@ -48,7 +48,7 @@ async def main() -> None: try: tx = client.place_order( subaccount, - market='ETH-USD', + market="ETH-USD", type=type, side=side, price=price, @@ -59,39 +59,40 @@ async def main() -> None: good_til_time_in_seconds=time_in_force_seconds, execution=OrderExecution.DEFAULT, post_only=post_only, - reduce_only=False + reduce_only=False, ) - print('**Order Tx**') + print("**Order Tx**") print(tx) except Exception as error: - print('**Order Failed**') + print("**Order Failed**") print(str(error)) await asyncio.sleep(5) # wait for placeOrder to complete - try: tx = client.place_order( subaccount, - market='ETH-USD', + market="ETH-USD", type=OrderType.STOP_MARKET, side=OrderSide.SELL, price=900.0, size=0.01, client_id=randrange(0, 100000000), time_in_force=OrderTimeInForce.GTT, - good_til_block=0, # long term orders use GTBT + good_til_block=0, # long term orders use GTBT good_til_time_in_seconds=1000, execution=OrderExecution.IOC, post_only=False, reduce_only=False, trigger_price=1000, ) - print('**Order Tx**') + print("**Order Tx**") print(tx) except Exception as error: - print('**Order Failed**') + print("**Order Failed**") print(str(error)) -if __name__ == '__main__': + + +if __name__ == "__main__": logging.basicConfig(level=logging.INFO) - asyncio.get_event_loop().run_until_complete(main()) \ No newline at end of file + asyncio.get_event_loop().run_until_complete(main()) diff --git a/v4-client-py/examples/faucet_endpoint.py b/v4-client-py/examples/faucet_endpoint.py index bbdb4dcf..e1a6dde4 100644 --- a/v4-client-py/examples/faucet_endpoint.py +++ b/v4-client-py/examples/faucet_endpoint.py @@ -1,14 +1,14 @@ -'''Example for depositing with faucet. +"""Example for depositing with faucet. Usage: python -m examples.faucet_endpoint -''' +""" from v4_client_py.clients import FaucetClient, Subaccount from v4_client_py.clients.constants import Network from tests.constants import DYDX_TEST_MNEMONIC client = FaucetClient( - host=Network.testnet().faucet_endpoint, + host=Network.config_network().faucet_endpoint, ) subaccount = Subaccount.from_mnemonic(DYDX_TEST_MNEMONIC) @@ -19,4 +19,4 @@ faucet_response = client.fill(address, 0, 2000) print(faucet_response.data) faucet_http_code = faucet_response.status_code -print(faucet_http_code) \ No newline at end of file +print(faucet_http_code) diff --git a/v4-client-py/examples/long_term_order_cancel_example.py b/v4-client-py/examples/long_term_order_cancel_example.py index f8950fc4..52703a4a 100644 --- a/v4-client-py/examples/long_term_order_cancel_example.py +++ b/v4-client-py/examples/long_term_order_cancel_example.py @@ -1,7 +1,7 @@ -'''Example for trading with human readable numbers +"""Example for trading with human readable numbers Usage: python -m examples.composite_example -''' +""" import asyncio import logging from random import randrange @@ -11,9 +11,9 @@ from v4_client_py.clients.helpers.chain_helpers import ( ORDER_FLAGS_LONG_TERM, - OrderType, - OrderSide, - OrderTimeInForce, + OrderType, + OrderSide, + OrderTimeInForce, OrderExecution, ) @@ -22,7 +22,7 @@ async def main() -> None: wallet = LocalWallet.from_mnemonic(DYDX_TEST_MNEMONIC, BECH32_PREFIX) - network = Network.testnet() + network = Network.config_network() client = CompositeClient( network, ) @@ -43,23 +43,23 @@ async def main() -> None: try: tx = client.place_order( subaccount, - market='ETH-USD', + market="ETH-USD", type=OrderType.LIMIT, side=OrderSide.SELL, price=40000, size=0.01, client_id=long_term_order_client_id, time_in_force=OrderTimeInForce.GTT, - good_til_block=0, # long term orders use GTBT + good_til_block=0, # long term orders use GTBT good_til_time_in_seconds=60, execution=OrderExecution.DEFAULT, post_only=False, - reduce_only=False + reduce_only=False, ) - print('** Long Term Order Tx**') + print("** Long Term Order Tx**") print(tx.tx_hash) except Exception as error: - print('**Long Term Order Failed**') + print("**Long Term Order Failed**") print(str(error)) # cancel a long term order. @@ -67,17 +67,18 @@ async def main() -> None: tx = client.cancel_order( subaccount, long_term_order_client_id, - 'ETH-USD', + "ETH-USD", ORDER_FLAGS_LONG_TERM, good_til_time_in_seconds=120, - good_til_block=0, # long term orders use GTBT + good_til_block=0, # long term orders use GTBT ) - print('**Cancel Long Term Order Tx**') + print("**Cancel Long Term Order Tx**") print(tx.tx_hash) except Exception as error: - print('**Cancel Long Term Order Failed**') + print("**Cancel Long Term Order Failed**") print(str(error)) -if __name__ == '__main__': + +if __name__ == "__main__": logging.basicConfig(level=logging.INFO) asyncio.get_event_loop().run_until_complete(main()) diff --git a/v4-client-py/examples/mainnet_examples/README.md b/v4-client-py/examples/mainnet_examples/README.md index 3770da35..bde4dac7 100644 --- a/v4-client-py/examples/mainnet_examples/README.md +++ b/v4-client-py/examples/mainnet_examples/README.md @@ -19,7 +19,8 @@ export PYTHONPATH='~/.../v4-clients/v4-client-py' Now you are ready to use the examples in this folder. -# Set up your configurations to run example files +# Set up your configurations in constants.py +~/.../v4-clients/v4-client-py/v4_client_py/clients/constats.py ``` VALIDATOR_GRPC_ENDPOINT = <> diff --git a/v4-client-py/examples/mainnet_examples/mainnet_account_endpoints.py b/v4-client-py/examples/mainnet_examples/mainnet_account_endpoints.py index 4a3da12b..ad8c15fe 100644 --- a/v4-client-py/examples/mainnet_examples/mainnet_account_endpoints.py +++ b/v4-client-py/examples/mainnet_examples/mainnet_account_endpoints.py @@ -2,14 +2,12 @@ from v4_client_py.clients.constants import Network from tests.constants import DYDX_TEST_MNEMONIC -MNEMONIC = DYDX_TEST_MNEMONIC - client = IndexerClient( - config=Network.mainnet().indexer_config, + config=Network.config_network().indexer_config, ) try: - subaccount = Subaccount.from_mnemonic(MNEMONIC) + subaccount = Subaccount.from_mnemonic(DYDX_TEST_MNEMONIC) address = subaccount.address # Get subaccounts diff --git a/v4-client-py/examples/mainnet_examples/mainnet_long_term_order_cancel_example.py b/v4-client-py/examples/mainnet_examples/mainnet_long_term_order_cancel_example.py index 94473876..acbdbb34 100644 --- a/v4-client-py/examples/mainnet_examples/mainnet_long_term_order_cancel_example.py +++ b/v4-client-py/examples/mainnet_examples/mainnet_long_term_order_cancel_example.py @@ -16,18 +16,15 @@ from tests.constants import DYDX_TEST_MNEMONIC, MAX_CLIENT_ID -MNEMONIC = DYDX_TEST_MNEMONIC - - -# define objects to be used with the SDK -wallet = LocalWallet.from_mnemonic(MNEMONIC, BECH32_PREFIX) -network = Network.mainnet() +wallet = LocalWallet.from_mnemonic(DYDX_TEST_MNEMONIC, BECH32_PREFIX) +network = Network.config_network() client = CompositeClient( network, ) subaccount = Subaccount(wallet, 0) + def define_order() -> dict: return { "subaccount": subaccount, diff --git a/v4-client-py/examples/mainnet_examples/mainnet_long_term_order_composite_example.py b/v4-client-py/examples/mainnet_examples/mainnet_long_term_order_composite_example.py index 4bbae244..a03d5782 100644 --- a/v4-client-py/examples/mainnet_examples/mainnet_long_term_order_composite_example.py +++ b/v4-client-py/examples/mainnet_examples/mainnet_long_term_order_composite_example.py @@ -16,17 +16,13 @@ from tests.constants import MAX_CLIENT_ID, DYDX_TEST_MNEMONIC -MNEMONIC = DYDX_TEST_MNEMONIC - -# define objects to be used with the SDK -wallet = LocalWallet.from_mnemonic(MNEMONIC, BECH32_PREFIX) -network = Network.mainnet() +wallet = LocalWallet.from_mnemonic(DYDX_TEST_MNEMONIC, BECH32_PREFIX) +network = Network.config_network() client = CompositeClient( network, ) subaccount = Subaccount(wallet, 0) - def define_order() -> dict: return { "subaccount": subaccount, diff --git a/v4-client-py/examples/mainnet_examples/mainnet_short_term_order_cancel_example.py b/v4-client-py/examples/mainnet_examples/mainnet_short_term_order_cancel_example.py index b8ca6657..c32d4084 100644 --- a/v4-client-py/examples/mainnet_examples/mainnet_short_term_order_cancel_example.py +++ b/v4-client-py/examples/mainnet_examples/mainnet_short_term_order_cancel_example.py @@ -13,28 +13,9 @@ ) from tests.constants import MAX_CLIENT_ID, DYDX_TEST_MNEMONIC -MNEMONIC = DYDX_TEST_MNEMONIC - -VALIDATOR_GRPC_ENDPOINT = "test-dydx-grpc.kingnodes.com:443" -AERIAL_CONFIG_URL = "https://test-dydx-grpc.kingnodes.com:443" -AERIAL_GRPC_OR_REST_PREFIX = "grpc" -INDEXER_REST_ENDPOINT = "https://dydx-testnet.imperator.co" -INDEXER_WS_ENDPOINT = "wss://indexer.v4testnet.dydx.exchange/v4/ws" -CHAIN_ID = "dydx-testnet-4" -ENV = "testnet" - - # define objects to be used with the SDK -wallet = LocalWallet.from_mnemonic(MNEMONIC, BECH32_PREFIX) -network = Network.config_network( - validator_grpc_endpoint=VALIDATOR_GRPC_ENDPOINT, - rest_endpoint=INDEXER_REST_ENDPOINT, - grpc_or_rest_prefix=AERIAL_GRPC_OR_REST_PREFIX, - aerial_url=AERIAL_CONFIG_URL, - websocket_endpoint=INDEXER_WS_ENDPOINT, - chain_id=CHAIN_ID, - env=ENV, -) +wallet = LocalWallet.from_mnemonic(DYDX_TEST_MNEMONIC, BECH32_PREFIX) +network = Network.config_network() client = CompositeClient( network, ) diff --git a/v4-client-py/examples/mainnet_examples/mainnet_short_term_order_composite_example.py b/v4-client-py/examples/mainnet_examples/mainnet_short_term_order_composite_example.py index 40da9080..775d0fb1 100644 --- a/v4-client-py/examples/mainnet_examples/mainnet_short_term_order_composite_example.py +++ b/v4-client-py/examples/mainnet_examples/mainnet_short_term_order_composite_example.py @@ -13,17 +13,13 @@ ) from tests.constants import MAX_CLIENT_ID, DYDX_TEST_MNEMONIC -MNEMONIC = DYDX_TEST_MNEMONIC - -# define objects to be used with the SDK -wallet = LocalWallet.from_mnemonic(MNEMONIC, BECH32_PREFIX) -network = Network.mainnet() +wallet = LocalWallet.from_mnemonic(DYDX_TEST_MNEMONIC, BECH32_PREFIX) +network = Network.config_network() client = CompositeClient( network, ) subaccount = Subaccount(wallet, 0) - def define_order() -> dict: return { "subaccount": subaccount, diff --git a/v4-client-py/examples/markets_endpoints.py b/v4-client-py/examples/markets_endpoints.py index 373aefff..3eb0a416 100644 --- a/v4-client-py/examples/markets_endpoints.py +++ b/v4-client-py/examples/markets_endpoints.py @@ -1,93 +1,93 @@ -'''Example for placing, replacing, and canceling orders. +"""Example for placing, replacing, and canceling orders. Usage: python -m examples.markets_endpoints -''' +""" from v4_client_py.clients import IndexerClient from v4_client_py.clients.constants import Network, MARKET_BTC_USD client = IndexerClient( - config=Network.testnet().indexer_config, + config=Network.config_network().indexer_config, ) # Get perp markets try: markets_response = client.markets.get_perpetual_markets() print(markets_response.data) - btc_market = markets_response.data['markets']['BTC-USD'] - btc_market_status = btc_market['status'] + btc_market = markets_response.data["markets"]["BTC-USD"] + btc_market_status = btc_market["status"] except: - print('failed to get markets') + print("failed to get markets") try: btc_market_response = client.markets.get_perpetual_markets(MARKET_BTC_USD) print(btc_market_response.data) - btc_market = btc_market_response.data['markets']['BTC-USD'] - btc_market_status = btc_market['status'] + btc_market = btc_market_response.data["markets"]["BTC-USD"] + btc_market_status = btc_market["status"] except: - print('failed to get BTC market') + print("failed to get BTC market") # Get sparklines try: sparklines_response = client.markets.get_perpetual_markets_sparklines() print(sparklines_response.data) sparklines = sparklines_response.data - btc_sparkline = sparklines['BTC-USD'] + btc_sparkline = sparklines["BTC-USD"] except: - print('failed to get sparklines') + print("failed to get sparklines") # Get perp market trades try: btc_market_trades_response = client.markets.get_perpetual_market_trades(MARKET_BTC_USD) print(btc_market_trades_response.data) - btc_market_trades = btc_market_trades_response.data['trades'] + btc_market_trades = btc_market_trades_response.data["trades"] btc_market_trades_0 = btc_market_trades[0] except: - print('failed to get market trades') + print("failed to get market trades") # Get perp market orderbook try: btc_market_orderbook_response = client.markets.get_perpetual_market_orderbook(MARKET_BTC_USD) print(btc_market_orderbook_response.data) btc_market_orderbook = btc_market_orderbook_response.data - btc_market_orderbook_asks = btc_market_orderbook['asks'] - btc_market_orderbook_bids = btc_market_orderbook['bids'] + btc_market_orderbook_asks = btc_market_orderbook["asks"] + btc_market_orderbook_bids = btc_market_orderbook["bids"] if len(btc_market_orderbook_asks) > 0: btc_market_orderbook_asks_0 = btc_market_orderbook_asks[0] print(btc_market_orderbook_asks_0) - btc_market_orderbook_asks_0_price = btc_market_orderbook_asks_0['price'] - btc_market_orderbook_asks_0_size = btc_market_orderbook_asks_0['size'] + btc_market_orderbook_asks_0_price = btc_market_orderbook_asks_0["price"] + btc_market_orderbook_asks_0_size = btc_market_orderbook_asks_0["size"] except: - print('failed to get market orderbook') + print("failed to get market orderbook") # Get perp market candles try: - btc_market_candles_response = client.markets.get_perpetual_market_candles(MARKET_BTC_USD, '1MIN') + btc_market_candles_response = client.markets.get_perpetual_market_candles(MARKET_BTC_USD, "1MIN") print(btc_market_candles_response.data) - btc_market_candles = btc_market_candles_response.data['candles'] + btc_market_candles = btc_market_candles_response.data["candles"] if len(btc_market_candles) > 0: btc_market_candles_0 = btc_market_candles[0] print(btc_market_candles_0) - btc_market_candles_0_startedAt = btc_market_candles_0['startedAt'] - btc_market_candles_0_low = btc_market_candles_0['low'] - btc_market_candles_0_hight = btc_market_candles_0['high'] - btc_market_candles_0_open = btc_market_candles_0['open'] - btc_market_candles_0_close = btc_market_candles_0['close'] - btc_market_candles_0_baseTokenVolume = btc_market_candles_0['baseTokenVolume'] - btc_market_candles_0_usdVolume = btc_market_candles_0['usdVolume'] - btc_market_candles_0_trades = btc_market_candles_0['trades'] + btc_market_candles_0_startedAt = btc_market_candles_0["startedAt"] + btc_market_candles_0_low = btc_market_candles_0["low"] + btc_market_candles_0_hight = btc_market_candles_0["high"] + btc_market_candles_0_open = btc_market_candles_0["open"] + btc_market_candles_0_close = btc_market_candles_0["close"] + btc_market_candles_0_baseTokenVolume = btc_market_candles_0["baseTokenVolume"] + btc_market_candles_0_usdVolume = btc_market_candles_0["usdVolume"] + btc_market_candles_0_trades = btc_market_candles_0["trades"] except: - print('failed to get market cancles') + print("failed to get market cancles") # Get perp market funding try: btc_market_funding_response = client.markets.get_perpetual_market_funding(MARKET_BTC_USD) print(btc_market_funding_response.data) - btc_market_funding= btc_market_funding_response.data['historicalFunding'] + btc_market_funding = btc_market_funding_response.data["historicalFunding"] if len(btc_market_funding) > 0: btc_market_funding_0 = btc_market_funding[0] print(btc_market_funding_0) except: - print('failed to get market historical funding') + print("failed to get market historical funding") diff --git a/v4-client-py/examples/short_term_order_cancel_example.py b/v4-client-py/examples/short_term_order_cancel_example.py index 01864fa2..a22135bc 100644 --- a/v4-client-py/examples/short_term_order_cancel_example.py +++ b/v4-client-py/examples/short_term_order_cancel_example.py @@ -1,7 +1,7 @@ -'''Example for trading with human readable numbers +"""Example for trading with human readable numbers Usage: python -m examples.composite_example -''' +""" import asyncio import logging from random import randrange @@ -12,14 +12,14 @@ from v4_client_py.clients.helpers.chain_helpers import ( ORDER_FLAGS_SHORT_TERM, Order_TimeInForce, - OrderSide, + OrderSide, ) from tests.constants import DYDX_TEST_MNEMONIC, MAX_CLIENT_ID async def main() -> None: wallet = LocalWallet.from_mnemonic(DYDX_TEST_MNEMONIC, BECH32_PREFIX) - network = Network.testnet() + network = Network.config_network() client = CompositeClient( network, ) @@ -36,19 +36,19 @@ async def main() -> None: try: tx = client.place_short_term_order( subaccount, - market='ETH-USD', + market="ETH-USD", side=OrderSide.SELL, price=40000, size=0.01, client_id=short_term_client_id, good_til_block=good_til_block, time_in_force=Order_TimeInForce.TIME_IN_FORCE_UNSPECIFIED, - reduce_only=False + reduce_only=False, ) - print('**Short Term Order Tx**') + print("**Short Term Order Tx**") print(tx.tx_hash) except Exception as error: - print('**Short Term Order Failed**') + print("**Short Term Order Failed**") print(str(error)) # cancel a short term order. @@ -56,18 +56,18 @@ async def main() -> None: tx = client.cancel_order( subaccount, short_term_client_id, - 'ETH-USD', + "ETH-USD", ORDER_FLAGS_SHORT_TERM, - good_til_time_in_seconds=0, # short term orders use GTB. - good_til_block=good_til_block, # GTB should be the same or greater than order to cancel + good_til_time_in_seconds=0, # short term orders use GTB. + good_til_block=good_til_block, # GTB should be the same or greater than order to cancel ) - print('**Cancel Short Term Order Tx**') + print("**Cancel Short Term Order Tx**") print(tx.tx_hash) except Exception as error: - print('**Cancel Short Term Order Failed**') + print("**Cancel Short Term Order Failed**") print(str(error)) -if __name__ == '__main__': +if __name__ == "__main__": logging.basicConfig(level=logging.INFO) - asyncio.get_event_loop().run_until_complete(main()) \ No newline at end of file + asyncio.get_event_loop().run_until_complete(main()) diff --git a/v4-client-py/examples/short_term_order_composite_example.py b/v4-client-py/examples/short_term_order_composite_example.py index d80b23fc..e7522dc2 100644 --- a/v4-client-py/examples/short_term_order_composite_example.py +++ b/v4-client-py/examples/short_term_order_composite_example.py @@ -1,7 +1,7 @@ -'''Example for trading with human readable numbers +"""Example for trading with human readable numbers Usage: python -m examples.composite_example -''' +""" import asyncio import logging from random import randrange @@ -10,7 +10,7 @@ from v4_client_py.clients.constants import BECH32_PREFIX, Network from v4_client_py.clients.helpers.chain_helpers import ( - OrderSide, + OrderSide, ) from examples.utils import loadJson, orderExecutionToTimeInForce @@ -19,12 +19,12 @@ async def main() -> None: wallet = LocalWallet.from_mnemonic(DYDX_TEST_MNEMONIC, BECH32_PREFIX) - network = Network.testnet() + network = Network.config_network() client = CompositeClient( network, ) subaccount = Subaccount(wallet, 0) - ordersParams = loadJson('human_readable_short_term_orders.json') + ordersParams = loadJson("human_readable_short_term_orders.json") for orderParams in ordersParams: side = OrderSide[orderParams["side"]] @@ -34,32 +34,33 @@ async def main() -> None: # Note, you can change this to any number between `next_valid_block_height` to `next_valid_block_height + SHORT_BLOCK_WINDOW` good_til_block = next_valid_block_height + 10 - time_in_force = orderExecutionToTimeInForce(orderParams['timeInForce']) + time_in_force = orderExecutionToTimeInForce(orderParams["timeInForce"]) price = orderParams.get("price", 1350) # uint32 - client_id = randrange(0, 2 ** 32 - 1) + client_id = randrange(0, 2**32 - 1) try: tx = client.place_short_term_order( subaccount, - market='ETH-USD', + market="ETH-USD", side=side, price=price, size=0.01, client_id=client_id, good_til_block=good_til_block, time_in_force=time_in_force, - reduce_only=False + reduce_only=False, ) - print('**Order Tx**') + print("**Order Tx**") print(tx.tx_hash) except Exception as error: - print('**Order Failed**') + print("**Order Failed**") print(str(error)) await asyncio.sleep(5) # wait for placeOrder to complete -if __name__ == '__main__': + +if __name__ == "__main__": logging.basicConfig(level=logging.INFO) asyncio.get_event_loop().run_until_complete(main()) diff --git a/v4-client-py/examples/transfer_example_deposit.py b/v4-client-py/examples/transfer_example_deposit.py index d58de223..97c73774 100644 --- a/v4-client-py/examples/transfer_example_deposit.py +++ b/v4-client-py/examples/transfer_example_deposit.py @@ -10,9 +10,9 @@ async def main() -> None: - network = Network.testnet() + network = Network.config_network() client = ValidatorClient(network.validator_config) - wallet = LocalWallet.from_mnemonic(DYDX_TEST_MNEMONIC, BECH32_PREFIX); + wallet = LocalWallet.from_mnemonic(DYDX_TEST_MNEMONIC, BECH32_PREFIX) subaccount = Subaccount(wallet, 0) try: tx = client.post.deposit( @@ -20,13 +20,12 @@ async def main() -> None: 0, 5_000_000, ) - print('**Deposit Tx**') + print("**Deposit Tx**") print(tx) except Exception as e: print(e) - -if __name__ == '__main__': +if __name__ == "__main__": logging.basicConfig(level=logging.INFO) asyncio.get_event_loop().run_until_complete(main()) diff --git a/v4-client-py/examples/transfer_example_subaccount_transfer.py b/v4-client-py/examples/transfer_example_subaccount_transfer.py index 8b23ba2d..01d0c9be 100644 --- a/v4-client-py/examples/transfer_example_subaccount_transfer.py +++ b/v4-client-py/examples/transfer_example_subaccount_transfer.py @@ -10,9 +10,9 @@ async def main() -> None: - network = Network.testnet() + network = Network.config_network() client = ValidatorClient(network.validator_config) - wallet = LocalWallet.from_mnemonic(DYDX_TEST_MNEMONIC, BECH32_PREFIX); + wallet = LocalWallet.from_mnemonic(DYDX_TEST_MNEMONIC, BECH32_PREFIX) subaccount = Subaccount(wallet, 0) try: tx = client.post.transfer( @@ -22,13 +22,12 @@ async def main() -> None: asset_id=0, amount=5_000_000, ) - print('**Transfer Tx**') + print("**Transfer Tx**") print(tx) except Exception as e: print(e) - -if __name__ == '__main__': +if __name__ == "__main__": logging.basicConfig(level=logging.INFO) asyncio.get_event_loop().run_until_complete(main()) diff --git a/v4-client-py/examples/transfer_example_withdraw.py b/v4-client-py/examples/transfer_example_withdraw.py index d6341259..558cde62 100644 --- a/v4-client-py/examples/transfer_example_withdraw.py +++ b/v4-client-py/examples/transfer_example_withdraw.py @@ -10,9 +10,9 @@ async def main() -> None: - network = Network.testnet() + network = Network.config_network() client = ValidatorClient(network.validator_config) - wallet = LocalWallet.from_mnemonic(DYDX_TEST_MNEMONIC, BECH32_PREFIX); + wallet = LocalWallet.from_mnemonic(DYDX_TEST_MNEMONIC, BECH32_PREFIX) subaccount = Subaccount(wallet, 0) try: tx = client.post.withdraw( @@ -20,13 +20,12 @@ async def main() -> None: 0, 10_000_000, ) - print('**Withdraw Tx**') + print("**Withdraw Tx**") print(tx) except Exception as e: print(e) - -if __name__ == '__main__': +if __name__ == "__main__": logging.basicConfig(level=logging.INFO) asyncio.get_event_loop().run_until_complete(main()) diff --git a/v4-client-py/examples/utility_endpoints.py b/v4-client-py/examples/utility_endpoints.py index dfca8804..c2fe81d9 100644 --- a/v4-client-py/examples/utility_endpoints.py +++ b/v4-client-py/examples/utility_endpoints.py @@ -1,29 +1,29 @@ -'''Example for getting Indexer server time and height. +"""Example for getting Indexer server time and height. Usage: python -m examples.utility_endpoints -''' +""" from v4_client_py.clients import IndexerClient from v4_client_py.clients.constants import Network client = IndexerClient( - config=Network.testnet().indexer_config, + config=Network.config_network().indexer_config, ) # Get indexer server time try: time_response = client.utility.get_time() print(time_response.data) - time_iso = time_response.data['iso'] - time_epoch = time_response.data['epoch'] + time_iso = time_response.data["iso"] + time_epoch = time_response.data["epoch"] except: - print('failed to get time') + print("failed to get time") # Get indexer height try: height_response = client.utility.get_height() print(height_response.data) - height = height_response.data['height'] - height_time = height_response.data['time'] + height = height_response.data["height"] + height_time = height_response.data["time"] except: - print('failed to get height') + print("failed to get height") diff --git a/v4-client-py/examples/utils.py b/v4-client-py/examples/utils.py index 5ec2ea8b..b1b96710 100644 --- a/v4-client-py/examples/utils.py +++ b/v4-client-py/examples/utils.py @@ -1,4 +1,3 @@ - from enum import Enum import json import os @@ -6,6 +5,7 @@ from v4_client_py.clients.helpers.chain_helpers import Order_TimeInForce, is_order_flag_stateful_order + def loadJson(filename): current_directory = os.path.dirname(os.path.abspath(__file__)) json_file_path = os.path.join(current_directory, filename) @@ -13,12 +13,14 @@ def loadJson(filename): with open(json_file_path, "r") as file: return json.load(file) + class HumanReadableOrderTimeInForce(Enum): DEFAULT = "DEFAULT" FOK = "FOK" IOC = "IOC" POST_ONLY = "POST_ONLY" + def orderExecutionToTimeInForce(orderExecution: HumanReadableOrderTimeInForce) -> Order_TimeInForce: if orderExecution == HumanReadableOrderTimeInForce.DEFAULT.value: return Order_TimeInForce.TIME_IN_FORCE_UNSPECIFIED @@ -29,4 +31,4 @@ def orderExecutionToTimeInForce(orderExecution: HumanReadableOrderTimeInForce) - elif orderExecution == HumanReadableOrderTimeInForce.POST_ONLY.value: return Order_TimeInForce.TIME_IN_FORCE_POST_ONLY else: - raise ValueError('Unrecognized order execution') + raise ValueError("Unrecognized order execution") diff --git a/v4-client-py/examples/validator_get_examples.py b/v4-client-py/examples/validator_get_examples.py index 4e17a303..4992ad37 100644 --- a/v4-client-py/examples/validator_get_examples.py +++ b/v4-client-py/examples/validator_get_examples.py @@ -8,91 +8,92 @@ async def main() -> None: - network = Network.testnet() + network = Network.config_network() client = ValidatorClient(network.validator_config) address = DYDX_TEST_ADDRESS try: acc = client.get.account(address=address) - print('account:') + print("account:") print(acc) except Exception as e: - print('failed to get account') + print("failed to get account") print(e) try: bank_balances = client.get.bank_balances(address) - print('bank balances:') + print("bank balances:") print(bank_balances) except Exception as e: - print('failed to get bank balances') + print("failed to get bank balances") print(e) try: - bank_balance = client.get.bank_balance(address, 'ibc/8E27BA2D5493AF5636760E354E46004562C46AB7EC0CC4C1CA14E9E20E2545B5') - print('bank balance:') + bank_balance = client.get.bank_balance( + address, "ibc/8E27BA2D5493AF5636760E354E46004562C46AB7EC0CC4C1CA14E9E20E2545B5" + ) + print("bank balance:") print(bank_balance) except Exception as e: - print('failed to get bank balances') + print("failed to get bank balances") print(e) - try: all_subaccounts = client.get.subaccounts() - print('subaccounts:') + print("subaccounts:") print(all_subaccounts) except Exception as e: - print('failed to get all subaccounts') + print("failed to get all subaccounts") print(e) try: subaccount = client.get.subaccount(address, 0) - print('subaccount:') + print("subaccount:") print(subaccount) except Exception as e: - print('failed to get subaccount') + print("failed to get subaccount") print(e) try: clob_pairs = client.get.clob_pairs() - print('clob pairs:') + print("clob pairs:") print(clob_pairs) except Exception as e: - print('failed to get all clob pairs') + print("failed to get all clob pairs") print(e) try: clob_pair = client.get.clob_pair(1) - print('clob pair:') + print("clob pair:") print(clob_pair) except Exception as e: - print('failed to get clob pair') + print("failed to get clob pair") print(e) try: prices = client.get.prices() - print('prices:') + print("prices:") print(prices) except Exception as e: - print('failed to get all prices') + print("failed to get all prices") print(e) try: price = client.get.price(1) - print('price:') + print("price:") print(price) except Exception as e: - print('failed to get price') + print("failed to get price") print(e) try: config = client.get.equity_tier_limit_config() - print('equity_tier_limit_configuration:') + print("equity_tier_limit_configuration:") print(config) except Exception as e: - print('failed to get equity_tier_limit_configuration') + print("failed to get equity_tier_limit_configuration") print(e) -if __name__ == '__main__': +if __name__ == "__main__": logging.basicConfig(level=logging.INFO) asyncio.get_event_loop().run_until_complete(main()) diff --git a/v4-client-py/examples/validator_post_examples.py b/v4-client-py/examples/validator_post_examples.py index cb3c7815..9303fb8a 100644 --- a/v4-client-py/examples/validator_post_examples.py +++ b/v4-client-py/examples/validator_post_examples.py @@ -28,6 +28,7 @@ "client_metadata": 0, } + def dummy_order(height): placeOrder = default_order.copy() placeOrder["client_id"] = random.randint(0, 1000000000) @@ -40,12 +41,13 @@ def dummy_order(height): placeOrder["side"] = Order.SIDE_SELL return placeOrder + async def main() -> None: - network = Network.testnet() + network = Network.config_network() client = ValidatorClient(network.validator_config) - wallet = LocalWallet.from_mnemonic(DYDX_TEST_MNEMONIC, BECH32_PREFIX); + wallet = LocalWallet.from_mnemonic(DYDX_TEST_MNEMONIC, BECH32_PREFIX) subaccount = Subaccount(wallet, 0) - ordersParams = loadJson('raw_orders.json') + ordersParams = loadJson("raw_orders.json") for orderParams in ordersParams: last_block = client.get.latest_block() height = last_block.block.header.height @@ -70,14 +72,15 @@ async def main() -> None: place_order["good_til_block_time"] = 0 tx = client.post.place_order_object(subaccount, place_order) - print('**Order Tx**') + print("**Order Tx**") print(tx) except Exception as error: - print('**Order Failed**') + print("**Order Failed**") print(str(error)) await asyncio.sleep(5) # wait for placeOrder to complete -if __name__ == '__main__': + +if __name__ == "__main__": logging.basicConfig(level=logging.INFO) asyncio.get_event_loop().run_until_complete(main()) diff --git a/v4-client-py/examples/wallet_address.py b/v4-client-py/examples/wallet_address.py index 383b6c44..746ca608 100644 --- a/v4-client-py/examples/wallet_address.py +++ b/v4-client-py/examples/wallet_address.py @@ -6,10 +6,10 @@ # We recommend using comspy to derive address from mnemonic wallet = LocalWallet.from_mnemonic(mnemonic=DYDX_TEST_MNEMONIC, prefix=BECH32_PREFIX) private_key = wallet.signer().private_key_hex -assert(private_key==DYDX_TEST_PRIVATE_KEY) +assert private_key == DYDX_TEST_PRIVATE_KEY public_key = wallet.public_key().public_key_hex address = wallet.address() -print(f'public key:{public_key}, address:{address}') +print(f"public key:{public_key}, address:{address}") -assert(address==DYDX_TEST_ADDRESS) \ No newline at end of file +assert address == DYDX_TEST_ADDRESS diff --git a/v4-client-py/examples/websocket_example.py b/v4-client-py/examples/websocket_example.py index 5b764762..bf54367d 100644 --- a/v4-client-py/examples/websocket_example.py +++ b/v4-client-py/examples/websocket_example.py @@ -1,7 +1,7 @@ -'''Example for connecting to private WebSockets with an existing account. +"""Example for connecting to private WebSockets with an existing account. Usage: python -m examples.websocket_example -''' +""" import asyncio import json @@ -11,29 +11,31 @@ from tests.constants import DYDX_TEST_ADDRESS + def on_open(ws): - print('WebSocket connection opened') + print("WebSocket connection opened") ws.send_ping_if_inactive_for(30) + def on_message(ws, message): - print(f'Received message: {message}') + print(f"Received message: {message}") payload = json.loads(message) - if (payload['type'] == 'connected'): + if payload["type"] == "connected": my_ws.subscribe_to_markets() - my_ws.subscribe_to_orderbook('ETH-USD') - my_ws.subscribe_to_trades('ETH-USD') - my_ws.subscribe_to_candles('ETH-USD') + my_ws.subscribe_to_orderbook("ETH-USD") + my_ws.subscribe_to_trades("ETH-USD") + my_ws.subscribe_to_candles("ETH-USD") my_ws.subscribe_to_subaccount(DYDX_TEST_ADDRESS, 0) ws.send_ping_if_inactive_for(30) ws.subscribe_to_markets() + def on_close(ws): - print('WebSocket connection closed') + print("WebSocket connection closed") + + +my_ws = SocketClient(config=Network.config_network().indexer_config, on_message=on_message, on_open=on_open, on_close=on_close) -my_ws = SocketClient(config=Network.testnet().indexer_config, - on_message=on_message, - on_open=on_open, - on_close=on_close) async def main(): my_ws.connect() @@ -41,4 +43,6 @@ async def main(): # Do some stuff... # my_ws.close() + + asyncio.get_event_loop().run_until_complete(main()) diff --git a/v4-client-py/v4_client_py/chain/aerial/config.py b/v4-client-py/v4_client_py/chain/aerial/config.py index 3dc5df1a..77c5ce8c 100644 --- a/v4-client-py/v4_client_py/chain/aerial/config.py +++ b/v4-client-py/v4_client_py/chain/aerial/config.py @@ -4,15 +4,6 @@ from dataclasses import dataclass from typing import Optional, Union -from v4_client_py.clients.constants import ( - AERIAL_CONFIG_CHAIN_ID_TESTNET, - AERIAL_CONFIG_URL_TESTNET, - AERIAL_CONFIG_CHAIN_ID_MAINNET, - AERIAL_CONFIG_URL_MAINNET, - GRPC_OR_REST_MAINNET, - GRPC_OR_REST_TESTNET, -) - class NetworkConfigError(RuntimeError): """Network config error. @@ -77,21 +68,6 @@ def fetchai_dorado_testnet(cls) -> "NetworkConfig": faucet_url="https://faucet-dorado.fetch.ai", ) - @classmethod - def fetch_dydx_testnet(cls) -> "NetworkConfig": - """Dydx testnet. - - :return: Network configuration - """ - return NetworkConfig( - chain_id=AERIAL_CONFIG_CHAIN_ID_TESTNET, - url=f"{GRPC_OR_REST_TESTNET}+{AERIAL_CONFIG_URL_TESTNET}", - fee_minimum_gas_price=4630550000000000, - fee_denomination="adv4tnt", - staking_denomination="dv4tnt", - faucet_url="http://faucet.v4testnet.dydx.exchange", - ) - @classmethod def fetchai_alpha_testnet(cls): """Get the fetchai alpha testnet. @@ -116,33 +92,6 @@ def fetch_dydx_stable_testnet(cls): """ return cls.fetch_dydx_testnet() - @classmethod - def fetchai_mainnet(cls) -> "NetworkConfig": - """Get the fetchai mainnet configuration. - - :return: fetch mainnet configuration - """ - return NetworkConfig( - chain_id=AERIAL_CONFIG_CHAIN_ID_MAINNET, - url=f"{GRPC_OR_REST_MAINNET}+{AERIAL_CONFIG_URL_MAINNET}", - fee_minimum_gas_price=0, - fee_denomination="afet", - staking_denomination="afet", - faucet_url=None, - ) - - @classmethod - def fetch_mainnet(cls) -> "NetworkConfig": - """Get the fetch mainnet. - - :return: fetch mainnet configurations - """ - warnings.warn( - "fetch_mainnet is deprecated, use fetchai_mainnet instead", - DeprecationWarning, - ) - return cls.fetchai_mainnet() - @classmethod def latest_stable_testnet(cls) -> "NetworkConfig": """Get the latest stable testnet. @@ -154,3 +103,18 @@ def latest_stable_testnet(cls) -> "NetworkConfig": DeprecationWarning, ) return cls.fetch_dydx_stable_testnet() + + @classmethod + def fetchai_network_config(cls, chain_id: str, url_prefix: str, url: str) -> "NetworkConfig": + """Get the fetchai mainnet configuration. + + :return: fetch mainnet configuration + """ + return cls( + chain_id=chain_id, + url=f"{url_prefix}+{url}", + fee_minimum_gas_price=0, + fee_denomination="afet", + staking_denomination="afet", + faucet_url=None, + ) diff --git a/v4-client-py/v4_client_py/clients/constants.py b/v4-client-py/v4_client_py/clients/constants.py index 597098a7..4e0d202e 100644 --- a/v4-client-py/v4_client_py/clients/constants.py +++ b/v4-client-py/v4_client_py/clients/constants.py @@ -1,84 +1,63 @@ from enum import Enum -#TODO: Add mainnet -# ------------ API URLs ------------ -INDEXER_API_HOST_MAINNET = None -INDEXER_API_HOST_TESTNET = 'https://dydx-testnet.imperator.co' - -INDEXER_WS_HOST_MAINNET = None -INDEXER_WS_HOST_TESTNET = 'wss://indexer.v4testnet.dydx.exchange/v4/ws' - -FAUCET_API_HOST_TESTNET = 'https://faucet.v4testnet.dydx.exchange' - -VALIDATOR_API_HOST_MAINNET = None -VALIDATOR_API_HOST_TESTNET = 'https://test-dydx.kingnodes.com' - -VALIDATOR_GRPC_MAINNET = None -VALIDATOR_GRPC_TESTNET = 'https://test-dydx-grpc.kingnodes.com:443' - -# ------------ Ethereum Network IDs------------ -NETWORK_ID_MAINNET = None -NETWORK_ID_TESTNET = 'dydx-testnet-4' - -# ----------- Aerial configs ------------------- -AERIAL_CONFIG_CHAIN_ID_TESTNET = "dydx-testnet-4" -AERIAL_CONFIG_CHAIN_ID_MAINNET = None - -GRPC_OR_REST_TESTNET = 'grpc' -GRPC_OR_REST_MAINNET = None - -AERIAL_CONFIG_URL_TESTNET = 'https://test-dydx-grpc.kingnodes.com:443' -AERIAL_CONFIG_URL_MAINNET = None +# define constants +VALIDATOR_GRPC_ENDPOINT = '{get from deployer}' +AERIAL_CONFIG_URL = '{get from deployer}' +AERIAL_GRPC_OR_REST_PREFIX = '{get from deployer}' +INDEXER_REST_ENDPOINT = '{get from deployer}' +INDEXER_WS_ENDPOINT = '{get from deployer}' +CHAIN_ID = '{get from deployer}' +ENV = '{get from deployer}' # ------------ Market Statistic Day Types ------------ -MARKET_STATISTIC_DAY_ONE = '1' -MARKET_STATISTIC_DAY_SEVEN = '7' -MARKET_STATISTIC_DAY_THIRTY = '30' +MARKET_STATISTIC_DAY_ONE = "1" +MARKET_STATISTIC_DAY_SEVEN = "7" +MARKET_STATISTIC_DAY_THIRTY = "30" # ------------ Order Types ------------ -ORDER_TYPE_LIMIT = 'LIMIT' -ORDER_TYPE_MARKET = 'MARKET' -ORDER_TYPE_STOP = 'STOP_LIMIT' -ORDER_TYPE_TRAILING_STOP = 'TRAILING_STOP' -ORDER_TYPE_TAKE_PROFIT = 'TAKE_PROFIT' +ORDER_TYPE_LIMIT = "LIMIT" +ORDER_TYPE_MARKET = "MARKET" +ORDER_TYPE_STOP = "STOP_LIMIT" +ORDER_TYPE_TRAILING_STOP = "TRAILING_STOP" +ORDER_TYPE_TAKE_PROFIT = "TAKE_PROFIT" # ------------ Order Side ------------ -ORDER_SIDE_BUY = 'BUY' -ORDER_SIDE_SELL = 'SELL' +ORDER_SIDE_BUY = "BUY" +ORDER_SIDE_SELL = "SELL" # ------------ Time in Force Types ------------ -TIME_IN_FORCE_GTT = 'GTT' -TIME_IN_FORCE_FOK = 'FOK' -TIME_IN_FORCE_IOC = 'IOC' +TIME_IN_FORCE_GTT = "GTT" +TIME_IN_FORCE_FOK = "FOK" +TIME_IN_FORCE_IOC = "IOC" # ------------ Position Status Types ------------ -POSITION_STATUS_OPEN = 'OPEN' -POSITION_STATUS_CLOSED = 'CLOSED' -POSITION_STATUS_LIQUIDATED = 'LIQUIDATED' +POSITION_STATUS_OPEN = "OPEN" +POSITION_STATUS_CLOSED = "CLOSED" +POSITION_STATUS_LIQUIDATED = "LIQUIDATED" # ------------ Order Status Types ------------ -ORDER_STATUS_PENDING = 'PENDING' -ORDER_STATUS_OPEN = 'OPEN' -ORDER_STATUS_FILLED = 'FILLED' -ORDER_STATUS_CANCELED = 'CANCELED' -ORDER_STATUS_UNTRIGGERED = 'UNTRIGGERED' +ORDER_STATUS_PENDING = "PENDING" +ORDER_STATUS_OPEN = "OPEN" +ORDER_STATUS_FILLED = "FILLED" +ORDER_STATUS_CANCELED = "CANCELED" +ORDER_STATUS_UNTRIGGERED = "UNTRIGGERED" # ------------ Transfer Status Types ------------ -TRANSFER_STATUS_PENDING = 'PENDING' -TRANSFER_STATUS_CONFIRMED = 'CONFIRMED' -TRANSFER_STATUS_QUEUED = 'QUEUED' -TRANSFER_STATUS_CANCELED = 'CANCELED' -TRANSFER_STATUS_UNCONFIRMED = 'UNCONFIRMED' +TRANSFER_STATUS_PENDING = "PENDING" +TRANSFER_STATUS_CONFIRMED = "CONFIRMED" +TRANSFER_STATUS_QUEUED = "QUEUED" +TRANSFER_STATUS_CANCELED = "CANCELED" +TRANSFER_STATUS_UNCONFIRMED = "UNCONFIRMED" # ------------ Markets ------------ -MARKET_BTC_USD = 'BTC-USD' -MARKET_ETH_USD = 'ETH-USD' +MARKET_BTC_USD = "BTC-USD" +MARKET_ETH_USD = "ETH-USD" # ------------ Assets ------------ -ASSET_USDC = 'USDC' -ASSET_BTC = 'BTC' -ASSET_ETH = 'ETH' +ASSET_USDC = "USDC" +ASSET_BTC = "BTC" +ASSET_ETH = "ETH" COLLATERAL_ASSET = ASSET_USDC # ------------ Synthetic Assets by Market ------------ @@ -92,7 +71,8 @@ MAX_MEMO_CHARACTERS = 256 -BECH32_PREFIX = 'dydx' +BECH32_PREFIX = "dydx" + class BroadcastMode(Enum): BroadcastTxSync = 0 @@ -105,21 +85,19 @@ def __init__( rest_endpoint: str, websocket_endpoint: str, ): - if rest_endpoint.endswith('/'): + if rest_endpoint.endswith("/"): rest_endpoint = rest_endpoint[:-1] self.rest_endpoint = rest_endpoint self.websocket_endpoint = websocket_endpoint + class ValidatorConfig: - def __init__( - self, - grpc_endpoint: str, - chain_id: str, - ssl_enabled: bool, - ): + def __init__(self, grpc_endpoint: str, chain_id: str, ssl_enabled: bool, url_prefix: str, aerial_url: str): self.grpc_endpoint = grpc_endpoint self.chain_id = chain_id self.ssl_enabled = ssl_enabled + self.url_prefix = url_prefix + self.url = aerial_url class Network: @@ -133,45 +111,25 @@ def __init__( self.env = env self.validator_config = validator_config self.indexer_config = indexer_config - if faucet_endpoint is not None and faucet_endpoint.endswith('/'): + if faucet_endpoint is not None and faucet_endpoint.endswith("/"): faucet_endpoint = faucet_endpoint[:-1] self.faucet_endpoint = faucet_endpoint @classmethod - def testnet(cls): - validator_config=ValidatorConfig( - grpc_endpoint=VALIDATOR_GRPC_TESTNET, - chain_id=NETWORK_ID_TESTNET, - ssl_enabled=True - ) - indexer_config=IndexerConfig( - rest_endpoint=INDEXER_API_HOST_TESTNET, - websocket_endpoint=INDEXER_WS_HOST_TESTNET, + def config_network( + cls + ) -> "Network": + validator_config = ValidatorConfig( + grpc_endpoint=VALIDATOR_GRPC_ENDPOINT, + chain_id=CHAIN_ID, + ssl_enabled=True, + url_prefix=AERIAL_GRPC_OR_REST_PREFIX, + aerial_url=AERIAL_CONFIG_URL, ) + indexer_config = IndexerConfig(rest_endpoint=INDEXER_REST_ENDPOINT, websocket_endpoint=INDEXER_WS_ENDPOINT) return cls( - env='testnet', - validator_config=validator_config, - indexer_config=indexer_config, - faucet_endpoint=FAUCET_API_HOST_TESTNET, - ) - - @classmethod - def mainnet(cls): - validator_config=ValidatorConfig( - grpc_endpoint=VALIDATOR_GRPC_MAINNET, - chain_id=NETWORK_ID_MAINNET, - ssl_enabled=True - ) - indexer_config=IndexerConfig( - rest_endpoint=INDEXER_API_HOST_MAINNET, - websocket_endpoint=INDEXER_WS_HOST_MAINNET, - ) - return cls( - env='mainnet', + env=ENV, validator_config=validator_config, indexer_config=indexer_config, faucet_endpoint=None, ) - - def string(self): - return self.env diff --git a/v4-client-py/v4_client_py/clients/dydx_composite_client.py b/v4-client-py/v4_client_py/clients/dydx_composite_client.py index 486acf66..627e50f1 100644 --- a/v4-client-py/v4_client_py/clients/dydx_composite_client.py +++ b/v4-client-py/v4_client_py/clients/dydx_composite_client.py @@ -8,14 +8,14 @@ QUOTE_QUANTUMS_ATOMIC_RESOLUTION, Order, Order_TimeInForce, - OrderType, - OrderSide, - OrderTimeInForce, + OrderType, + OrderSide, + OrderTimeInForce, OrderExecution, calculate_side, - calculate_quantums, - calculate_subticks, - calculate_time_in_force, + calculate_quantums, + calculate_subticks, + calculate_time_in_force, calculate_order_flags, ORDER_FLAGS_SHORT_TERM, SHORT_BLOCK_WINDOW, @@ -34,9 +34,9 @@ class CompositeClient: def __init__( self, network: Network, - api_timeout = None, - send_options = None, - credentials = grpc.ssl_channel_credentials(), + api_timeout=None, + send_options=None, + credentials=grpc.ssl_channel_credentials(), ): self.indexer_client = IndexerClient(network.indexer_config, api_timeout, send_options) self.validator_client = ValidatorClient(network.validator_config, credentials) @@ -100,7 +100,7 @@ def place_order( reduce_only: bool, trigger_price: float = None, ) -> SubmittedTx: - ''' + """ Place order :param subaccount: required @@ -140,7 +140,7 @@ def place_order( :type reduce_only: bool :returns: Tx information - ''' + """ msg = self.place_order_message( subaccount=subaccount, market=market, @@ -171,7 +171,7 @@ def place_short_term_order( time_in_force: Order_TimeInForce, reduce_only: bool, ) -> SubmittedTx: - ''' + """ Place Short-Term order :param subaccount: required @@ -202,7 +202,7 @@ def place_short_term_order( :type reduce_only: bool :returns: Tx information - ''' + """ msg = self.place_short_term_order_message( subaccount=subaccount, market=market, @@ -216,27 +216,35 @@ def place_short_term_order( reduce_only=reduce_only, ) return self.validator_client.post.send_message(subaccount=subaccount, msg=msg, zeroFee=True) - + def calculate_client_metadata(self, order_type: OrderType) -> int: - ''' + """ Calculate Client Metadata :param order_type: required :type order_type: OrderType :returns: Client Metadata - ''' - return 1 if (order_type == OrderType.MARKET or order_type == OrderType.STOP_MARKET or order_type == OrderType.TAKE_PROFIT_MARKET) else 0 + """ + return ( + 1 + if ( + order_type == OrderType.MARKET + or order_type == OrderType.STOP_MARKET + or order_type == OrderType.TAKE_PROFIT_MARKET + ) + else 0 + ) def calculate_condition_type(self, order_type: OrderType) -> Order.ConditionType: - ''' + """ Calculate Condition Type :param order_type: required :type order_type: OrderType :returns: Condition Type - ''' + """ if order_type == OrderType.LIMIT: return Order.CONDITION_TYPE_UNSPECIFIED elif order_type == OrderType.MARKET: @@ -246,17 +254,17 @@ def calculate_condition_type(self, order_type: OrderType) -> Order.ConditionType elif order_type == OrderType.TAKE_PROFIT_LIMIT or order_type == OrderType.TAKE_PROFIT_MARKET: return Order.CONDITION_TYPE_TAKE_PROFIT else: - raise ValueError('order_type is invalid') + raise ValueError("order_type is invalid") def calculate_conditional_order_trigger_subticks( - self, - order_type: OrderType, - atomic_resolution: int, - quantum_conversion_exponent: int, - subticks_per_tick: int, - trigger_price: float, - ) -> int: - ''' + self, + order_type: OrderType, + atomic_resolution: int, + quantum_conversion_exponent: int, + subticks_per_tick: int, + trigger_price: float, + ) -> int: + """ Calculate Conditional Order Trigger Subticks :param order_type: required @@ -275,15 +283,20 @@ def calculate_conditional_order_trigger_subticks( :type trigger_price: float :returns: Conditional Order Trigger Subticks - ''' + """ if order_type == OrderType.LIMIT or order_type == OrderType.MARKET: return 0 - elif order_type == OrderType.STOP_LIMIT or order_type == OrderType.STOP_MARKET or order_type == OrderType.TAKE_PROFIT_LIMIT or order_type == OrderType.TAKE_PROFIT_MARKET: + elif ( + order_type == OrderType.STOP_LIMIT + or order_type == OrderType.STOP_MARKET + or order_type == OrderType.TAKE_PROFIT_LIMIT + or order_type == OrderType.TAKE_PROFIT_MARKET + ): if trigger_price is None: - raise ValueError('trigger_price is required for conditional orders') + raise ValueError("trigger_price is required for conditional orders") return calculate_subticks(trigger_price, atomic_resolution, quantum_conversion_exponent, subticks_per_tick) else: - raise ValueError('order_type is invalid') + raise ValueError("order_type is invalid") def place_order_message( self, @@ -303,12 +316,12 @@ def place_order_message( trigger_price: float = None, ) -> MsgPlaceOrder: markets_response = self.indexer_client.markets.get_perpetual_markets(market) - market = markets_response.data['markets'][market] - clob_pair_id = market['clobPairId'] - atomic_resolution = market['atomicResolution'] - step_base_quantums = market['stepBaseQuantums'] - quantum_conversion_exponent = market['quantumConversionExponent'] - subticks_per_tick = market['subticksPerTick'] + market = markets_response.data["markets"][market] + clob_pair_id = market["clobPairId"] + atomic_resolution = market["atomicResolution"] + step_base_quantums = market["stepBaseQuantums"] + quantum_conversion_exponent = market["quantumConversionExponent"] + subticks_per_tick = market["subticksPerTick"] order_side = calculate_side(side) quantums = calculate_quantums(size, atomic_resolution, step_base_quantums) subticks = calculate_subticks(price, atomic_resolution, quantum_conversion_exponent, subticks_per_tick) @@ -322,12 +335,8 @@ def place_order_message( client_metadata = self.calculate_client_metadata(type) condition_type = self.calculate_condition_type(type) conditional_order_trigger_subticks = self.calculate_conditional_order_trigger_subticks( - type, - atomic_resolution, - quantum_conversion_exponent, - subticks_per_tick, - trigger_price - ) + type, atomic_resolution, quantum_conversion_exponent, subticks_per_tick, trigger_price + ) return self.validator_client.post.composer.compose_msg_place_order( address=subaccount.address, subaccount_number=subaccount.subaccount_number, @@ -364,12 +373,12 @@ def place_short_term_order_message( # Construct the MsgPlaceOrder. markets_response = self.indexer_client.markets.get_perpetual_markets(market) - market = markets_response.data['markets'][market] - clob_pair_id = market['clobPairId'] - atomic_resolution = market['atomicResolution'] - step_base_quantums = market['stepBaseQuantums'] - quantum_conversion_exponent = market['quantumConversionExponent'] - subticks_per_tick = market['subticksPerTick'] + market = markets_response.data["markets"][market] + clob_pair_id = market["clobPairId"] + atomic_resolution = market["atomicResolution"] + step_base_quantums = market["stepBaseQuantums"] + quantum_conversion_exponent = market["quantumConversionExponent"] + subticks_per_tick = market["subticksPerTick"] order_side = calculate_side(side) quantums = calculate_quantums(size, atomic_resolution, step_base_quantums) subticks = calculate_subticks(price, atomic_resolution, quantum_conversion_exponent, subticks_per_tick) @@ -394,15 +403,15 @@ def place_short_term_order_message( ) def cancel_order( - self, + self, subaccount: Subaccount, client_id: int, market: str, order_flags: int, good_til_time_in_seconds: int, good_til_block: int, - ) -> SubmittedTx: - ''' + ) -> SubmittedTx: + """ Cancel order :param subaccount: required @@ -424,7 +433,7 @@ def cancel_order( :type good_til_block_time: int :returns: Tx information - ''' + """ msg = self.cancel_order_message( subaccount, market, @@ -436,15 +445,14 @@ def cancel_order( return self.validator_client.post.send_message(subaccount=subaccount, msg=msg, zeroFee=True) - def cancel_short_term_order( self, subaccount: Subaccount, client_id: int, market: str, good_til_block: int, - ) -> SubmittedTx: - ''' + ) -> SubmittedTx: + """ Cancel order :param subaccount: required @@ -460,7 +468,7 @@ def cancel_short_term_order( :type good_til_block: int :returns: Tx information - ''' + """ msg = self.cancel_order_message( subaccount, market, @@ -472,7 +480,6 @@ def cancel_short_term_order( return self.validator_client.post.send_message(subaccount=subaccount, msg=msg, zeroFee=True) - def cancel_order_message( self, subaccount: Subaccount, @@ -488,8 +495,8 @@ def cancel_order_message( # Construct the MsgPlaceOrder. markets_response = self.indexer_client.markets.get_perpetual_markets(market) - market = markets_response.data['markets'][market] - clob_pair_id = market['clobPairId'] + market = markets_response.data["markets"][market] + clob_pair_id = market["clobPairId"] good_til_block, good_til_block_time = self.generate_good_til_fields( order_flags, @@ -507,15 +514,14 @@ def cancel_order_message( good_til_block_time=good_til_block_time, ) - def transfer_to_subaccount( - self, + self, subaccount: Subaccount, recipient_address: str, recipient_subaccount_number: int, amount: float, - ) -> SubmittedTx: - ''' + ) -> SubmittedTx: + """ Cancel order :param subaccount: required @@ -531,7 +537,7 @@ def transfer_to_subaccount( :type amount: float :returns: Tx information - ''' + """ return self.validator_client.post.transfer( subaccount=subaccount, recipient_address=recipient_address, @@ -539,13 +545,13 @@ def transfer_to_subaccount( asset_id=0, amount=amount * 10**6, ) - + def deposit_to_subaccount( - self, + self, subaccount: Subaccount, amount: float, - ) -> SubmittedTx: - ''' + ) -> SubmittedTx: + """ Cancel order :param subaccount: required @@ -555,19 +561,19 @@ def deposit_to_subaccount( :type amount: float :returns: Tx information - ''' + """ return self.validator_client.post.deposit( subaccount=subaccount, asset_id=0, - quantums=amount * 10 ** (- QUOTE_QUANTUMS_ATOMIC_RESOLUTION), + quantums=amount * 10 ** (-QUOTE_QUANTUMS_ATOMIC_RESOLUTION), ) - + def withdraw_from_subaccount( - self, + self, subaccount: Subaccount, amount: float, - ) -> SubmittedTx: - ''' + ) -> SubmittedTx: + """ Cancel order :param subaccount: required @@ -577,9 +583,9 @@ def withdraw_from_subaccount( :type amount: float :returns: Tx information - ''' + """ return self.validator_client.post.withdraw( subaccount=subaccount, asset_id=0, - quantums=amount * 10 ** (- QUOTE_QUANTUMS_ATOMIC_RESOLUTION), + quantums=amount * 10 ** (-QUOTE_QUANTUMS_ATOMIC_RESOLUTION), ) diff --git a/v4-client-py/v4_client_py/clients/modules/post.py b/v4-client-py/v4_client_py/clients/modules/post.py index 74e4d7fd..ec8395b4 100644 --- a/v4-client-py/v4_client_py/clients/modules/post.py +++ b/v4-client-py/v4_client_py/clients/modules/post.py @@ -13,7 +13,7 @@ from ...chain.aerial.tx_helpers import SubmittedTx from ...chain.aerial.client import LedgerClient, NetworkConfig from ...chain.aerial.client.utils import prepare_and_broadcast_basic_transaction -from v4_client_py.clients.constants import NETWORK_ID_MAINNET, NETWORK_ID_TESTNET + class Post: def __init__( @@ -22,17 +22,6 @@ def __init__( ): self.config = config self.composer = Composer() - - def fetch_network_config(self): - if self.config.chain_id == NETWORK_ID_MAINNET: - return NetworkConfig.fetchai_mainnet() - elif self.config.chain_id == NETWORK_ID_TESTNET: - return NetworkConfig.fetch_dydx_testnet() - else: - raise Exception ( - 'Do not which network config to choose...' - 'Please set a proper one in /v4_client_py/clients/constants.py' - ) def send_message( self, @@ -41,8 +30,7 @@ def send_message( zeroFee: bool = False, broadcast_mode: BroadcastMode = None, ) -> SubmittedTx: - - ''' + """ Send a message :param subaccount: required @@ -52,26 +40,28 @@ def send_message( :type msg: Message :returns: Tx information - ''' + """ wallet = subaccount.wallet - network = self.fetch_network_config() + network = NetworkConfig.fetchai_network_config( + chain_id=self.config.chain_id, url_prefix=self.config.url_prefix, url=self.config.url + ) ledger = LedgerClient(network) - + tx = Transaction() tx.add_message(msg) gas_limit = 0 if zeroFee else None return prepare_and_broadcast_basic_transaction( - client=ledger, - tx=tx, - sender=wallet, + client=ledger, + tx=tx, + sender=wallet, gas_limit=gas_limit, memo=None, broadcast_mode=broadcast_mode if (broadcast_mode != None) else self.default_broadcast_mode(msg), fee=0 if zeroFee else None, - ) - + ) + def place_order( self, subaccount: Subaccount, @@ -86,11 +76,11 @@ def place_order( good_til_block: int, good_til_block_time: int, client_metadata: int, - condition_type: Order.ConditionType=Order.ConditionType.CONDITION_TYPE_UNSPECIFIED, - conditional_order_trigger_subticks: int=0, - broadcast_mode: BroadcastMode=None, + condition_type: Order.ConditionType = Order.ConditionType.CONDITION_TYPE_UNSPECIFIED, + conditional_order_trigger_subticks: int = 0, + broadcast_mode: BroadcastMode = None, ) -> SubmittedTx: - ''' + """ Place order :param subaccount: required @@ -127,40 +117,34 @@ def place_order( :type reduce_only: bool :returns: Tx information - ''' + """ # prepare tx msg subaccount_number = subaccount.subaccount_number msg = self.composer.compose_msg_place_order( address=subaccount.address, - subaccount_number=subaccount_number, - client_id=client_id, - clob_pair_id=clob_pair_id, - order_flags=order_flags, - good_til_block=good_til_block, - good_til_block_time=good_til_block_time, - side=side, - quantums=quantums, - subticks=subticks, - time_in_force=time_in_force, + subaccount_number=subaccount_number, + client_id=client_id, + clob_pair_id=clob_pair_id, + order_flags=order_flags, + good_til_block=good_til_block, + good_til_block_time=good_til_block_time, + side=side, + quantums=quantums, + subticks=subticks, + time_in_force=time_in_force, reduce_only=reduce_only, client_metadata=client_metadata, condition_type=condition_type, conditional_order_trigger_subticks=conditional_order_trigger_subticks, - ) - return self.send_message( - subaccount=subaccount, - msg=msg, - zeroFee=True, - broadcast_mode=broadcast_mode ) - + return self.send_message(subaccount=subaccount, msg=msg, zeroFee=True, broadcast_mode=broadcast_mode) def place_order_object( self, subaccount: Subaccount, place_order: any, - broadcast_mode: BroadcastMode=None, + broadcast_mode: BroadcastMode = None, ) -> SubmittedTx: return self.place_order( subaccount, @@ -186,9 +170,9 @@ def cancel_order( order_flags: int, good_til_block: int, good_til_block_time: int, - broadcast_mode: BroadcastMode=None, + broadcast_mode: BroadcastMode = None, ) -> SubmittedTx: - ''' + """ Cancel order :param subaccount: required @@ -213,23 +197,23 @@ def cancel_order( :type broadcast_mode: BroadcastMode :returns: Tx information - ''' + """ msg = self.composer.compose_msg_cancel_order( - subaccount.address, + subaccount.address, subaccount.subaccount_number, client_id, clob_pair_id, order_flags, good_til_block, good_til_block_time, - ) + ) return self.send_message(subaccount, msg, zeroFee=True, broadcast_mode=broadcast_mode) - + def cancel_order_object( self, subaccount: Subaccount, cancel_order: any, - broadcast_mode: BroadcastMode=None, + broadcast_mode: BroadcastMode = None, ) -> SubmittedTx: return self.cancel_order( subaccount, @@ -240,7 +224,7 @@ def cancel_order_object( cancel_order.good_til_block_time, broadcast_mode=broadcast_mode, ) - + def transfer( self, subaccount: Subaccount, @@ -248,7 +232,7 @@ def transfer( recipient_subaccount_number: int, asset_id: int, amount: int, - broadcast_mode: BroadcastMode=None, + broadcast_mode: BroadcastMode = None, ) -> SubmittedTx: msg = self.composer.compose_msg_transfer( subaccount.address, @@ -260,13 +244,12 @@ def transfer( ) return self.send_message(subaccount, msg, broadcast_mode=broadcast_mode) - def deposit( self, subaccount: Subaccount, asset_id: int, quantums: int, - broadcast_mode: BroadcastMode=None, + broadcast_mode: BroadcastMode = None, ) -> SubmittedTx: msg = self.composer.compose_msg_deposit_to_subaccount( subaccount.address, @@ -276,13 +259,12 @@ def deposit( ) return self.send_message(subaccount, msg, broadcast_mode=broadcast_mode) - def withdraw( self, subaccount: Subaccount, asset_id: int, quantums: int, - broadcast_mode: BroadcastMode=None, + broadcast_mode: BroadcastMode = None, ) -> SubmittedTx: msg = self.composer.compose_msg_withdraw_from_subaccount( subaccount.address, @@ -291,7 +273,7 @@ def withdraw( quantums, ) return self.send_message(subaccount, msg, broadcast_mode=broadcast_mode) - + def default_broadcast_mode(self, msg: _message.Message) -> BroadcastMode: if isinstance(msg, MsgPlaceOrder): order_flags = msg.order.order_id.order_flags From c180453ef294c8c084b2fbb2b5851c48dea513f1 Mon Sep 17 00:00:00 2001 From: carlos Date: Thu, 18 Jan 2024 12:43:01 +0200 Subject: [PATCH 16/18] remove incorrect folder --- v4-client-py/examples/chain_client/Account.py | 23 ----------------- .../examples/chain_client/BankBalance.py | 25 ------------------- .../examples/chain_client/BankBalances.py | 24 ------------------ v4-client-py/examples/chain_client/GetTx.py | 24 ------------------ v4-client-py/examples/chain_client/test.py | 1 - 5 files changed, 97 deletions(-) delete mode 100644 v4-client-py/examples/chain_client/Account.py delete mode 100644 v4-client-py/examples/chain_client/BankBalance.py delete mode 100644 v4-client-py/examples/chain_client/BankBalances.py delete mode 100644 v4-client-py/examples/chain_client/GetTx.py delete mode 100644 v4-client-py/examples/chain_client/test.py diff --git a/v4-client-py/examples/chain_client/Account.py b/v4-client-py/examples/chain_client/Account.py deleted file mode 100644 index e7b46aa6..00000000 --- a/v4-client-py/examples/chain_client/Account.py +++ /dev/null @@ -1,23 +0,0 @@ -import asyncio -import logging - -from v4_client_py.clients import ValidatorClient, Subaccount -from v4_client_py.clients.constants import Network - -from tests.constants import DYDX_TEST_MNEMONIC - -client = ValidatorClient( - config=Network.testnet().validator_config, -) -subaccount = Subaccount.from_mnemonic(DYDX_TEST_MNEMONIC) -address = subaccount.address - - -async def main() -> None: - acc = client.get.account(address=address) - print(acc) - - -if __name__ == "__main__": - logging.basicConfig(level=logging.INFO) - asyncio.get_event_loop().run_until_complete(main()) diff --git a/v4-client-py/examples/chain_client/BankBalance.py b/v4-client-py/examples/chain_client/BankBalance.py deleted file mode 100644 index 6e52c1e9..00000000 --- a/v4-client-py/examples/chain_client/BankBalance.py +++ /dev/null @@ -1,25 +0,0 @@ -import asyncio -import logging - - -from v4_client_py.clients import ValidatorClient, Subaccount -from v4_client_py.clients.constants import Network - -from tests.constants import DYDX_TEST_MNEMONIC - -client = ValidatorClient( - config=Network.testnet().validator_config, -) -subaccount = Subaccount.from_mnemonic(DYDX_TEST_MNEMONIC) -address = subaccount.address - - -async def main() -> None: - denom = "USDC" - bank_balance = await client.get.bank_balance(address=address, denom=denom) - print(bank_balance) - - -if __name__ == "__main__": - logging.basicConfig(level=logging.INFO) - asyncio.get_event_loop().run_until_complete(main()) diff --git a/v4-client-py/examples/chain_client/BankBalances.py b/v4-client-py/examples/chain_client/BankBalances.py deleted file mode 100644 index 2c11646f..00000000 --- a/v4-client-py/examples/chain_client/BankBalances.py +++ /dev/null @@ -1,24 +0,0 @@ -import asyncio -import logging - - -from v4_client_py.clients import ValidatorClient, Subaccount -from v4_client_py.clients.constants import Network - -from tests.constants import DYDX_TEST_MNEMONIC - -client = ValidatorClient( - config=Network.testnet().validator_config, -) -subaccount = Subaccount.from_mnemonic(DYDX_TEST_MNEMONIC) -address = subaccount.address - - -async def main() -> None: - all_bank_balances = await client.get.bank_balances(address=address) - print(all_bank_balances) - - -if __name__ == "__main__": - logging.basicConfig(level=logging.INFO) - asyncio.get_event_loop().run_until_complete(main()) diff --git a/v4-client-py/examples/chain_client/GetTx.py b/v4-client-py/examples/chain_client/GetTx.py deleted file mode 100644 index b61c736d..00000000 --- a/v4-client-py/examples/chain_client/GetTx.py +++ /dev/null @@ -1,24 +0,0 @@ -import asyncio -import logging - -from v4_client_py.clients import ValidatorClient, Subaccount -from v4_client_py.clients.constants import Network - -from tests.constants import DYDX_TEST_MNEMONIC - -client = ValidatorClient( - config=Network.testnet().validator_config, -) -subaccount = Subaccount.from_mnemonic(DYDX_TEST_MNEMONIC) -address = subaccount.address - - -async def main() -> None: - tx_hash = "8247FEF19BB29BD93922803E9919620252DBC0BA4BE7D96E212D8F5EBC122B48" - tx_logs = await client.get.tx(tx_hash=tx_hash) - print(tx_logs) - - -if __name__ == "__main__": - logging.basicConfig(level=logging.INFO) - asyncio.get_event_loop().run_until_complete(main()) diff --git a/v4-client-py/examples/chain_client/test.py b/v4-client-py/examples/chain_client/test.py deleted file mode 100644 index c224f55a..00000000 --- a/v4-client-py/examples/chain_client/test.py +++ /dev/null @@ -1 +0,0 @@ -test = "123" From b5d0eb869f0743e9d9508368fb8a451d40b1f516 Mon Sep 17 00:00:00 2001 From: carlos Date: Thu, 18 Jan 2024 13:03:55 +0200 Subject: [PATCH 17/18] remove unnecessary mainnet folder and move readme out --- .../examples/{mainnet_examples => }/README.md | 6 +- .../examples/mainnet_examples/__init__.py | 0 .../mainnet_account_endpoints.py | 114 ------------------ .../mainnet_long_term_order_cancel_example.py | 101 ---------------- ...innet_long_term_order_composite_example.py | 83 ------------- ...mainnet_short_term_order_cancel_example.py | 80 ------------ ...nnet_short_term_order_composite_example.py | 62 ---------- .../mainnet_examples/mainnet_ws_get_fills.py | 65 ---------- 8 files changed, 2 insertions(+), 509 deletions(-) rename v4-client-py/examples/{mainnet_examples => }/README.md (74%) delete mode 100644 v4-client-py/examples/mainnet_examples/__init__.py delete mode 100644 v4-client-py/examples/mainnet_examples/mainnet_account_endpoints.py delete mode 100644 v4-client-py/examples/mainnet_examples/mainnet_long_term_order_cancel_example.py delete mode 100644 v4-client-py/examples/mainnet_examples/mainnet_long_term_order_composite_example.py delete mode 100644 v4-client-py/examples/mainnet_examples/mainnet_short_term_order_cancel_example.py delete mode 100644 v4-client-py/examples/mainnet_examples/mainnet_short_term_order_composite_example.py delete mode 100644 v4-client-py/examples/mainnet_examples/mainnet_ws_get_fills.py diff --git a/v4-client-py/examples/mainnet_examples/README.md b/v4-client-py/examples/README.md similarity index 74% rename from v4-client-py/examples/mainnet_examples/README.md rename to v4-client-py/examples/README.md index bde4dac7..aa010d2e 100644 --- a/v4-client-py/examples/mainnet_examples/README.md +++ b/v4-client-py/examples/README.md @@ -1,6 +1,4 @@ -# User guide to test mainnet examples - -The examples present in this folder are meant to be used in the mainnet, thus, with real money. Use them at your own risk. +# User guide to test examples 1. Go to your repository location for the Python client ``` @@ -20,7 +18,7 @@ export PYTHONPATH='~/.../v4-clients/v4-client-py' Now you are ready to use the examples in this folder. # Set up your configurations in constants.py -~/.../v4-clients/v4-client-py/v4_client_py/clients/constats.py +~/.../v4-clients/v4-client-py/v4_client_py/clients/constants.py ``` VALIDATOR_GRPC_ENDPOINT = <> diff --git a/v4-client-py/examples/mainnet_examples/__init__.py b/v4-client-py/examples/mainnet_examples/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/v4-client-py/examples/mainnet_examples/mainnet_account_endpoints.py b/v4-client-py/examples/mainnet_examples/mainnet_account_endpoints.py deleted file mode 100644 index ad8c15fe..00000000 --- a/v4-client-py/examples/mainnet_examples/mainnet_account_endpoints.py +++ /dev/null @@ -1,114 +0,0 @@ -from v4_client_py.clients import IndexerClient, Subaccount -from v4_client_py.clients.constants import Network -from tests.constants import DYDX_TEST_MNEMONIC - -client = IndexerClient( - config=Network.config_network().indexer_config, -) - -try: - subaccount = Subaccount.from_mnemonic(DYDX_TEST_MNEMONIC) - address = subaccount.address - - # Get subaccounts - try: - subaccounts_response = client.account.get_subaccounts(address) - print(f"{subaccounts_response.data}") - subaccounts = subaccounts_response.data["subaccounts"] - subaccount_0 = subaccounts[0] - print(f"{subaccount_0}") - subaccount_0_subaccountNumber = subaccount_0["subaccountNumber"] - except Exception: - print("failed to get subaccounts") - - try: - subaccount_response = client.account.get_subaccount(address, 0) - print(f"{subaccount_response.data}") - subaccount = subaccount_response.data["subaccount"] - print(f"{subaccount}") - subaccount_subaccountNumber = subaccount["subaccountNumber"] - except Exception: - print("failed to get subaccount") - - # Get positions - try: - asset_positions_response = client.account.get_subaccount_asset_positions(address, 0) - print(f"{asset_positions_response.data}") - asset_positions = asset_positions_response.data["positions"] - if len(asset_positions) > 0: - asset_positions_0 = asset_positions[0] - print(f"{asset_positions_0}") - except Exception: - print("failed to get asset positions") - - try: - perpetual_positions_response = client.account.get_subaccount_perpetual_positions(address, 0) - print(f"{perpetual_positions_response.data}") - perpetual_positions = perpetual_positions_response.data["positions"] - if len(perpetual_positions) > 0: - perpetual_positions_0 = perpetual_positions[0] - print(f"{perpetual_positions_0}") - except Exception: - print("failed to get perpetual positions") - - # Get transfers - try: - transfers_response = client.account.get_subaccount_transfers(address, 0) - print(f"{transfers_response.data}") - transfers = transfers_response.data["transfers"] - if len(transfers) > 0: - transfers_0 = transfers[0] - print(f"{transfers_0}") - except Exception: - print("failed to get transfers") - - # Get orders - try: - orders_response = client.account.get_subaccount_orders(address, 0) - print(f"{orders_response.data}") - orders = orders_response.data - if len(orders) > 0: - order_0 = orders[0] - print(f"{order_0}") - order_0_id = order_0["id"] - order_response = client.account.get_order(order_id=order_0_id) - order = order_response.data - order_id = order["id"] - except: - print("failed to get orders") - - # Get fills - try: - fills_response = client.account.get_subaccount_fills(address, 0) - print(f"{fills_response.data}") - fills = fills_response.data["fills"] - if len(fills) > 0: - fill_0 = fills[0] - print(f"{fill_0}") - except Exception: - print("failed to get fills") - - # Get funding - try: - funding_response = client.account.get_subaccount_funding(address, 0) - print(f"{funding_response.data}") - funding = funding_response.data["fundingPayments"] - if len(funding) > 0: - funding_0 = funding[0] - print(f"{funding_0}") - except Exception: - print("failed to get funding") - - # Get historical pnl - try: - historical_pnl_response = client.account.get_subaccount_historical_pnls(address, 0) - print(f"{historical_pnl_response.data}") - historical_pnl = historical_pnl_response.data["historicalPnl"] - if len(historical_pnl) > 0: - historical_pnl_0 = historical_pnl[0] - print(f"{historical_pnl_0}") - except Exception: - print("failed to get historical pnl") - -except Exception: - print("from_mnemonic failed") diff --git a/v4-client-py/examples/mainnet_examples/mainnet_long_term_order_cancel_example.py b/v4-client-py/examples/mainnet_examples/mainnet_long_term_order_cancel_example.py deleted file mode 100644 index acbdbb34..00000000 --- a/v4-client-py/examples/mainnet_examples/mainnet_long_term_order_cancel_example.py +++ /dev/null @@ -1,101 +0,0 @@ -import asyncio -import logging -from random import randrange - -from v4_client_py.chain.aerial.wallet import LocalWallet -from v4_client_py.clients import CompositeClient, Subaccount -from v4_client_py.clients.constants import BECH32_PREFIX, Network - -from v4_client_py.clients.helpers.chain_helpers import ( - ORDER_FLAGS_LONG_TERM, - OrderType, - OrderSide, - OrderTimeInForce, - OrderExecution, -) - -from tests.constants import DYDX_TEST_MNEMONIC, MAX_CLIENT_ID - -wallet = LocalWallet.from_mnemonic(DYDX_TEST_MNEMONIC, BECH32_PREFIX) -network = Network.config_network() -client = CompositeClient( - network, -) -subaccount = Subaccount(wallet, 0) - - - -def define_order() -> dict: - return { - "subaccount": subaccount, - "market": "ETH-USD", - "type": OrderType.LIMIT, - "side": OrderSide.SELL, - "price": 40000, - "size": 0.01, - "client_id": randrange(0, MAX_CLIENT_ID), - "time_in_force": OrderTimeInForce.GTT, - "good_til_block": 0, - # long term orders use GTBT - "good_til_time_in_seconds": 60, - "execution": OrderExecution.DEFAULT, - "post_only": False, - "reduce_only": False, - } - - -async def main() -> None: - """ - Note this example places a stateful order. - Programmatic traders should generally not use stateful orders for following reasons: - - Stateful orders received out of order by validators will fail sequence number validation - and be dropped. - - Stateful orders have worse time priority since they are only matched after they are included - on the block. - - Stateful order rate limits are more restrictive than Short-Term orders, specifically max 2 per - block / 20 per 100 blocks. - - Stateful orders can only be canceled after they’ve been included in a block. - """ - order = define_order() - try: - tx = client.place_order( - subaccount=order["subaccount"], - market=order["market"], - type=order["type"], - side=order["side"], - price=order["price"], - size=order["size"], - client_id=order["client_id"], - time_in_force=order["time_in_force"], - good_til_block=order["good_til_block"], - good_til_time_in_seconds=order["good_til_time_in_seconds"], - execution=order["execution"], - post_only=order["post_only"], - reduce_only=order["reduce_only"], - ) - print("** Long Term Order Tx**") - print(tx.tx_hash) - except Exception as error: - print("**Long Term Order Failed**") - print(error) - - # cancel a long term order. - try: - tx = client.cancel_order( - subaccount=order["subaccount"], - client_id=order["client_id"], - market=order["market"], - order_flags=ORDER_FLAGS_LONG_TERM, - good_til_time_in_seconds=order["good_til_time_in_seconds"], - good_til_block=order["good_til_block"], # long term orders use GTBT - ) - print("**Cancel Long Term Order Tx**") - print(tx.tx_hash) - except Exception as error: - print("**Cancel Long Term Order Failed**") - print(error) - - -if __name__ == "__main__": - logging.basicConfig(level=logging.INFO) - asyncio.get_event_loop().run_until_complete(main()) diff --git a/v4-client-py/examples/mainnet_examples/mainnet_long_term_order_composite_example.py b/v4-client-py/examples/mainnet_examples/mainnet_long_term_order_composite_example.py deleted file mode 100644 index a03d5782..00000000 --- a/v4-client-py/examples/mainnet_examples/mainnet_long_term_order_composite_example.py +++ /dev/null @@ -1,83 +0,0 @@ -import asyncio -import logging -from random import randrange - -from v4_client_py.chain.aerial.wallet import LocalWallet -from v4_client_py.clients import CompositeClient, Subaccount -from v4_client_py.clients.constants import BECH32_PREFIX, Network - -from v4_client_py.clients.helpers.chain_helpers import ( - ORDER_FLAGS_LONG_TERM, - OrderType, - OrderSide, - OrderTimeInForce, - OrderExecution, -) - -from tests.constants import MAX_CLIENT_ID, DYDX_TEST_MNEMONIC - -wallet = LocalWallet.from_mnemonic(DYDX_TEST_MNEMONIC, BECH32_PREFIX) -network = Network.config_network() -client = CompositeClient( - network, -) -subaccount = Subaccount(wallet, 0) - -def define_order() -> dict: - return { - "subaccount": subaccount, - "market": "ETH-USD", - "type": OrderType.LIMIT, - "side": OrderSide.SELL, - "price": 40000, - "size": 0.01, - "client_id": randrange(0, MAX_CLIENT_ID), - "time_in_force": OrderTimeInForce.GTT, - "good_til_block": 0, - # long term orders use GTBT - "good_til_time_in_seconds": 60, - "execution": OrderExecution.DEFAULT, - "post_only": False, - "reduce_only": False, - } - - -async def main() -> None: - """ - Note this example places a stateful order. - Programmatic traders should generally not use stateful orders for following reasons: - - Stateful orders received out of order by validators will fail sequence number validation - and be dropped. - - Stateful orders have worse time priority since they are only matched after they are included - on the block. - - Stateful order rate limits are more restrictive than Short-Term orders, specifically max 2 per - block / 20 per 100 blocks. - - Stateful orders can only be canceled after they’ve been included in a block. - """ - order = define_order() - try: - tx = client.place_order( - subaccount=order["subaccount"], - market=order["market"], - type=order["type"], - side=order["side"], - price=order["price"], - size=order["size"], - client_id=order["client_id"], - time_in_force=order["time_in_force"], - good_til_block=order["good_til_block"], - good_til_time_in_seconds=order["good_til_time_in_seconds"], - execution=order["execution"], - post_only=order["post_only"], - reduce_only=order["reduce_only"], - ) - print("** Long Term Order Tx**") - print(tx.tx_hash) - except Exception as error: - print("**Long Term Order Failed**") - print(error) - - -if __name__ == "__main__": - logging.basicConfig(level=logging.INFO) - asyncio.get_event_loop().run_until_complete(main()) diff --git a/v4-client-py/examples/mainnet_examples/mainnet_short_term_order_cancel_example.py b/v4-client-py/examples/mainnet_examples/mainnet_short_term_order_cancel_example.py deleted file mode 100644 index c32d4084..00000000 --- a/v4-client-py/examples/mainnet_examples/mainnet_short_term_order_cancel_example.py +++ /dev/null @@ -1,80 +0,0 @@ -import asyncio -import logging -from random import randrange - -from v4_client_py.chain.aerial.wallet import LocalWallet -from v4_client_py.clients import CompositeClient, Subaccount -from v4_client_py.clients.constants import BECH32_PREFIX, Network - -from v4_client_py.clients.helpers.chain_helpers import ( - ORDER_FLAGS_SHORT_TERM, - Order_TimeInForce, - OrderSide, -) -from tests.constants import MAX_CLIENT_ID, DYDX_TEST_MNEMONIC - -# define objects to be used with the SDK -wallet = LocalWallet.from_mnemonic(DYDX_TEST_MNEMONIC, BECH32_PREFIX) -network = Network.config_network() -client = CompositeClient( - network, -) -subaccount = Subaccount(wallet, 0) - - -def define_order() -> dict: - return { - "subaccount": subaccount, - "market": "ETH-USD", - "side": OrderSide.SELL, - "price": 40000, - "size": 0.01, - "client_id": randrange(0, MAX_CLIENT_ID), - "good_til_block": client.get_current_block() + 11, - # Note, you can change this to any number between `current_block+1` - # to `current_block+1 + SHORT_BLOCK_WINDOW` - "time_in_force": Order_TimeInForce.TIME_IN_FORCE_UNSPECIFIED, - "reduce_only": False, - } - - -async def main() -> None: - order = define_order() - try: - tx = client.place_short_term_order( - subaccount=order["subaccount"], - market=order["market"], - side=order["side"], - price=order["price"], - size=order["size"], - client_id=order["client_id"], - good_til_block=order["good_til_block"], - time_in_force=order["time_in_force"], - reduce_only=order["reduce_only"], - ) - print("**Short Term Order Tx**") - print(tx.tx_hash) - except Exception as error: - print("**Short Term Order Failed**") - print(error) - - # cancel a short term order. - try: - tx = client.cancel_order( - subaccount=order["subaccount"], - client_id=order["client_id"], - market=order["market"], - order_flags=ORDER_FLAGS_SHORT_TERM, - good_til_time_in_seconds=0, # short term orders use GTB. - good_til_block=order["good_til_block"], # GTB should be the same or greater than order to cancel - ) - print("**Cancel Short Term Order Tx**") - print(tx.tx_hash) - except Exception as error: - print("**Cancel Short Term Order Failed**") - print(error) - - -if __name__ == "__main__": - logging.basicConfig(level=logging.INFO) - asyncio.get_event_loop().run_until_complete(main()) diff --git a/v4-client-py/examples/mainnet_examples/mainnet_short_term_order_composite_example.py b/v4-client-py/examples/mainnet_examples/mainnet_short_term_order_composite_example.py deleted file mode 100644 index 775d0fb1..00000000 --- a/v4-client-py/examples/mainnet_examples/mainnet_short_term_order_composite_example.py +++ /dev/null @@ -1,62 +0,0 @@ -import asyncio -import logging -from random import randrange - -from v4_client_py.chain.aerial.wallet import LocalWallet -from v4_client_py.clients import CompositeClient, Subaccount -from v4_client_py.clients.constants import BECH32_PREFIX, Network - -from v4_client_py.clients.helpers.chain_helpers import ( - ORDER_FLAGS_SHORT_TERM, - Order_TimeInForce, - OrderSide, -) -from tests.constants import MAX_CLIENT_ID, DYDX_TEST_MNEMONIC - -wallet = LocalWallet.from_mnemonic(DYDX_TEST_MNEMONIC, BECH32_PREFIX) -network = Network.config_network() -client = CompositeClient( - network, -) -subaccount = Subaccount(wallet, 0) - -def define_order() -> dict: - return { - "subaccount": subaccount, - "market": "ETH-USD", - "side": OrderSide.SELL, - "price": 40000, - "size": 0.01, - "client_id": randrange(0, MAX_CLIENT_ID), - "good_til_block": client.get_current_block() + 11, - # Note, you can change this to any number between `current_block+1` - # to `current_block+1 + SHORT_BLOCK_WINDOW` - "time_in_force": Order_TimeInForce.TIME_IN_FORCE_UNSPECIFIED, - "reduce_only": False, - } - - -async def main() -> None: - order = define_order() - try: - tx = client.place_short_term_order( - subaccount=order["subaccount"], - market=order["market"], - side=order["side"], - price=order["price"], - size=order["size"], - client_id=order["client_id"], - good_til_block=order["good_til_block"], - time_in_force=order["time_in_force"], - reduce_only=order["reduce_only"], - ) - print("**Short Term Order Tx**") - print(tx.tx_hash) - except Exception as error: - print("**Short Term Order Failed**") - print(error) - - -if __name__ == "__main__": - logging.basicConfig(level=logging.INFO) - asyncio.get_event_loop().run_until_complete(main()) diff --git a/v4-client-py/examples/mainnet_examples/mainnet_ws_get_fills.py b/v4-client-py/examples/mainnet_examples/mainnet_ws_get_fills.py deleted file mode 100644 index a954cfa0..00000000 --- a/v4-client-py/examples/mainnet_examples/mainnet_ws_get_fills.py +++ /dev/null @@ -1,65 +0,0 @@ -import asyncio -import json - -from v4_client_py.clients.dydx_socket_client import SocketClient -from v4_client_py.clients.constants import Network - -ADDRESS = "" - - -def for_fills(fills_data): - try: - for fill in fills_data: - print("Received fill:", fill) - except Exception as e: - print(e) - - -def check_fills(message_data): - try: - if "contents" in message_data and "fills" in message_data["contents"]: - if fills_data := message_data["contents"]["fills"]: - for_fills(fills_data) - else: - print("No fills information in the message.") - else: - print("No 'contents' or 'fills' key in the message.") - except Exception as e: - print(e) - - -def on_open(ws): - print("WebSocket connection opened") - ws.send_ping_if_inactive_for(30) - - -def on_message(ws, message): - print(message) - payload = json.loads(message) - if payload["type"] == "connected": - my_ws.subscribe_to_subaccount(ADDRESS, 0) - else: - check_fills(payload) - ws.send_ping_if_inactive_for(30) - ws.subscribe_to_markets() - - -def on_close(ws): - print("WebSocket connection closed") - - -async def main(): - try: - my_ws.connect() - except Exception as e: - print(f"An error occurred: {e}") - - -# Run the event loop forever -if __name__ == "__main__": - my_ws = SocketClient( - config=Network.mainnet().indexer_config, on_message=on_message, on_open=on_open, on_close=on_close - ) - print(my_ws) - - asyncio.get_event_loop().run_until_complete(main()) From a586f1adf136936747d93d3a9968c0f93fb6bfb1 Mon Sep 17 00:00:00 2001 From: carlos Date: Fri, 5 Apr 2024 10:09:34 +0300 Subject: [PATCH 18/18] remove custom ping --- .../clients/dydx_socket_client.py | 31 +------------------ 1 file changed, 1 insertion(+), 30 deletions(-) diff --git a/v4-client-py/v4_client_py/clients/dydx_socket_client.py b/v4-client-py/v4_client_py/clients/dydx_socket_client.py index 2a462d7b..85833fde 100644 --- a/v4-client-py/v4_client_py/clients/dydx_socket_client.py +++ b/v4-client-py/v4_client_py/clients/dydx_socket_client.py @@ -19,8 +19,6 @@ def __init__( self.on_open = on_open self.on_close = on_close self.last_activity_time = None - self.ping_thread = None - self.ping_sent_time = None def connect(self): self.ws = websocket.WebSocketApp(self.url, @@ -36,17 +34,9 @@ def _on_open(self, ws): else: print('WebSocket connection opened') self.last_activity_time = time.time() - self.ping_thread = threading.Thread(target=self._ping_thread_func) - self.ping_thread.start() def _on_message(self, ws, message): - if message == 'ping': - self.send('pong') - elif message == 'pong' and self.ping_sent_time is not None: - elapsed_time = time.time() - self.ping_sent_time - print(f'Received PONG after {elapsed_time:.2f} seconds') - self.ping_sent_time = None - elif self.on_message: + if self.on_message: self.on_message(ws, message) else: print(f'Received message: {message}') @@ -58,7 +48,6 @@ def _on_close(self, ws): else: print('WebSocket connection closed') self.last_activity_time = None - self.ping_thread = None def send(self, message): if self.ws: @@ -67,24 +56,6 @@ def send(self, message): else: print('Error: WebSocket is not connected') - def send_ping(self): - self.send('ping') - self.ping_sent_time = time.time() - - def _ping_thread_func(self): - while self.ws: - if self.last_activity_time and time.time() - self.last_activity_time > 30: - self.send_ping() - self.last_activity_time = time.time() - elif self.ping_sent_time and time.time() - self.ping_sent_time > 5: - print('Did not receive PONG in time, closing WebSocket...') - self.close() - break - time.sleep(1) - - def send_ping_if_inactive_for(self, duration): - self.last_activity_time = time.time() - duration - def close(self): if self.ws: self.ws.close()