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

Implement Network.customnet + customnet example #106

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all 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
5 changes: 5 additions & 0 deletions v4-client-py/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -130,3 +130,8 @@ dmypy.json

# IDE
.idea/

# Nix
shell.nix
flake.nix
flake.lock
118 changes: 118 additions & 0 deletions v4-client-py/examples/customnet_composite_example.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
'''Example for custom network trading with human readable numbers

Network.customnet(
grpc_endpoint: str,
chain_id: str,
rest_endpoint: str,
websocket_endpoint: str,
fee_minimum_gas_price: int|float,
fee_denomination: str,
staking_denomination: str,
ssl_enabled: bool=True,
faucet_endpoint: str=None,
)

Usage: python -m examples.customnet_composite_example
'''
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 (
OrderType,
OrderSide,
OrderTimeInForce,
OrderExecution,
)
from examples.utils import loadJson

from tests.constants import DYDX_TEST_MNEMONIC


async def main() -> None:
wallet = LocalWallet.from_mnemonic(DYDX_TEST_MNEMONIC, BECH32_PREFIX)
network = Network.customnet(
grpc_endpoint='dydx-testnet-archive.allthatnode.com:9090',
chain_id='dydx-testnet-4',
rest_endpoint='https://dydx-testnet.imperator.co',
websocket_endpoint='wss://indexer.v4testnet.dydx.exchange/v4/ws',
fee_minimum_gas_price=4630550000000000,
fee_denomination='adv4tnt',
staking_denomination='dv4tnt',
faucet_endpoint='https://faucet.v4testnet.dydx.exchange',
)
client = CompositeClient(
network,
)
subaccount = Subaccount(wallet, 0)
ordersParams = loadJson('human_readable_orders.json')
for orderParams in ordersParams:
type = OrderType[orderParams["type"]]
side = OrderSide[orderParams["side"]]
time_in_force_string = orderParams.get("timeInForce", "GTT")
time_in_force = OrderTimeInForce[time_in_force_string]
price = orderParams.get("price", 1350)

if time_in_force == OrderTimeInForce.GTT:
time_in_force_seconds = 60
good_til_block = 0
else:
latest_block = client.validator_client.get.latest_block()
next_valid_block = latest_block.block.header.height + 1
good_til_block = next_valid_block + 10
time_in_force_seconds = 0

post_only = orderParams.get("postOnly", False)
try:
tx = client.place_order(
subaccount,
market='ETH-USD',
type=type,
side=side,
price=price,
size=0.01,
client_id=randrange(0, 100000000),
time_in_force=time_in_force,
good_til_block=good_til_block,
good_til_time_in_seconds=time_in_force_seconds,
execution=OrderExecution.DEFAULT,
post_only=post_only,
reduce_only=False
)
print('**Order Tx**')
print(tx)
except Exception as error:
print('**Order Failed**')
print(str(error))

await asyncio.sleep(5) # wait for placeOrder to complete


try:
tx = client.place_order(
subaccount,
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_time_in_seconds=1000,
execution=OrderExecution.IOC,
post_only=False,
reduce_only=False,
trigger_price=1000,
)
print('**Order Tx**')
print(tx)
except Exception as error:
print('**Order Failed**')
print(str(error))
if __name__ == '__main__':
logging.basicConfig(level=logging.INFO)
asyncio.get_event_loop().run_until_complete(main())
102 changes: 85 additions & 17 deletions v4-client-py/v4_client_py/clients/constants.py
Original file line number Diff line number Diff line change
@@ -1,26 +1,37 @@
from enum import Enum
from typing import Optional, Union
from ..chain.aerial.config import NetworkConfig


# ------------ API URLs ------------
INDEXER_API_HOST_MAINNET = None
INDEXER_API_HOST_TESTNET = 'https://dydx-testnet.imperator.co'
INDEXER_API_HOST_MAINNET = ''
INDEXER_API_HOST_TESTNET = 'https://indexer.v4testnet.dydx.exchange'

INDEXER_WS_HOST_MAINNET = None
INDEXER_WS_HOST_MAINNET = ''
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://dydx-testnet-archive.allthatnode.com'
VALIDATOR_API_HOST_MAINNET = ''
VALIDATOR_API_HOST_TESTNET = 'https://test-dydx.kingnodes.com'

VALIDATOR_GRPC_MAINNET = None
VALIDATOR_GRPC_TESTNET = 'dydx-testnet-archive.allthatnode.com:9090'
VALIDATOR_GRPC_MAINNET = ''
VALIDATOR_GRPC_TESTNET = 'test-dydx-grpc.kingnodes.com:443'

# ------------ Ethereum Network IDs ------------
NETWORK_ID_MAINNET = None
NETWORK_ID_MAINNET = ''
NETWORK_ID_TESTNET = 'dydx-testnet-4'

# ------------ Network Config ------------
FEE_MINIMUM_MAINNET = 0
FEE_MINIMUM_TESTNET = 4630550000000000

FEE_DENOM_MAINNET = ''
FEE_DENOM_TESTNET = 'adv4tnt'

STAKE_DENOM_MAINNET = ''
STAKE_DENOM_TESTNET = 'dv4tnt'

# ------------ Market Statistic Day Types ------------
MARKET_STATISTIC_DAY_ONE = '1'
MARKET_STATISTIC_DAY_SEVEN = '7'
Expand Down Expand Up @@ -85,6 +96,7 @@

BECH32_PREFIX = 'dydx'


class BroadcastMode(Enum):
BroadcastTxSync = 0
BroadcastTxCommit = 1
Expand All @@ -101,16 +113,19 @@ def __init__(
self.rest_endpoint = rest_endpoint
self.websocket_endpoint = websocket_endpoint


class ValidatorConfig:
def __init__(
self,
grpc_endpoint: str,
chain_id: str,
ssl_enabled: bool,
network_config: NetworkConfig,
):
self.grpc_endpoint = grpc_endpoint
self.chain_id = chain_id
self.ssl_enabled = ssl_enabled
self.network_config = network_config


class Network:
Expand All @@ -119,7 +134,7 @@ def __init__(
env: str,
validator_config: ValidatorConfig,
indexer_config: IndexerConfig,
faucet_endpoint: str,
faucet_endpoint: Optional[str] = None,
):
self.env = env
self.validator_config = validator_config
Expand All @@ -130,12 +145,20 @@ def __init__(

@classmethod
def testnet(cls):
validator_config=ValidatorConfig(
validator_config = ValidatorConfig(
grpc_endpoint=VALIDATOR_GRPC_TESTNET,
chain_id=NETWORK_ID_TESTNET,
ssl_enabled=True
chain_id=NETWORK_ID_TESTNET,
ssl_enabled=True,
network_config=NetworkConfig(
chain_id=NETWORK_ID_TESTNET,
url='grpc+https://' + VALIDATOR_GRPC_TESTNET,
fee_minimum_gas_price=FEE_MINIMUM_TESTNET,
fee_denomination=FEE_DENOM_TESTNET,
staking_denomination=STAKE_DENOM_TESTNET,
faucet_url=FAUCET_API_HOST_TESTNET,
),
)
indexer_config=IndexerConfig(
indexer_config = IndexerConfig(
rest_endpoint=INDEXER_API_HOST_TESTNET,
websocket_endpoint=INDEXER_WS_HOST_TESTNET,
)
Expand All @@ -148,12 +171,20 @@ def testnet(cls):

@classmethod
def mainnet(cls):
validator_config=ValidatorConfig(
validator_config = ValidatorConfig(
grpc_endpoint=VALIDATOR_GRPC_MAINNET,
chain_id=NETWORK_ID_MAINNET,
ssl_enabled=True
chain_id=NETWORK_ID_MAINNET,
ssl_enabled=True,
network_config=NetworkConfig(
chain_id=NETWORK_ID_MAINNET,
url='grpc+https://' + VALIDATOR_GRPC_MAINNET,
fee_minimum_gas_price=FEE_MINIMUM_MAINNET,
fee_denomination=FEE_DENOM_MAINNET,
staking_denomination=STAKE_DENOM_MAINNET,
faucet_url=None,
),
)
indexer_config=IndexerConfig(
indexer_config = IndexerConfig(
rest_endpoint=INDEXER_API_HOST_MAINNET,
websocket_endpoint=INDEXER_WS_HOST_MAINNET,
)
Expand All @@ -164,5 +195,42 @@ def mainnet(cls):
faucet_endpoint=None,
)

@classmethod
def customnet(
cls,
grpc_endpoint: str,
chain_id: str,
rest_endpoint: str,
websocket_endpoint: str,
fee_minimum_gas_price: Union[int, float],
fee_denomination: str,
staking_denomination: str,
ssl_enabled: bool = True,
faucet_endpoint: Optional[str] = None,
):
validator_config = ValidatorConfig(
grpc_endpoint=grpc_endpoint,
chain_id=chain_id,
ssl_enabled=ssl_enabled,
network_config=NetworkConfig(
chain_id=chain_id,
url=['grpc+http://', 'grpc+https://'][ssl_enabled] + grpc_endpoint,
fee_minimum_gas_price=fee_minimum_gas_price,
fee_denomination=fee_denomination,
staking_denomination=staking_denomination,
faucet_url=faucet_endpoint,
)
)
indexer_config = IndexerConfig(
rest_endpoint=rest_endpoint,
websocket_endpoint=websocket_endpoint,
)
return cls(
env='customnet',
validator_config=validator_config,
indexer_config=indexer_config,
faucet_endpoint=faucet_endpoint,
)

def string(self):
return self.env
2 changes: 1 addition & 1 deletion v4-client-py/v4_client_py/clients/modules/post.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ def send_message(
'''

wallet = subaccount.wallet
network = NetworkConfig.fetch_dydx_testnet()
network = self.config.network_config
ledger = LedgerClient(network)
tx = Transaction()
tx.add_message(msg)
Expand Down