Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add mainnet examples, readme and configs #97

Open
wants to merge 18 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 12 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions v4-client-py/examples/mainnet_examples/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# User guide to test mainnet examples

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need an #integration section in README.md, probably under #installation, with the simple instructions on how to use the code.

Essentially it should cover two things to get it started

  1. Set up network configuration
network = Network.config_network(
        grpc_endpoint = '{get from deployer}',
        rest_endpoint= '{get from deployer}',
        websocket_endpoint = '{get from deployer}',
        chain_id = '{get from deployer}',
    )
  1. Connect to client
    client = CompositeClient(
        network,
    )

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we still have the problem of the config.py for the NetworkConfig class that needs to be defined

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'
```

Now you are ready to use the examples in this folder.
Empty file.
116 changes: 116 additions & 0 deletions v4-client-py/examples/mainnet_examples/mainnet_account_endpoints.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
from v4_client_py.clients import IndexerClient, Subaccount
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,
)

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")
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
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

MNEMONIC = DYDX_TEST_MNEMONIC


# 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())
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
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

MNEMONIC = DYDX_TEST_MNEMONIC

# 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())
Loading