dydxprotocol / dydx-v3-python

Python client for dYdX (API v3)
Apache License 2.0
306 stars 176 forks source link

dydx-v3-python==1.9.1 client.private.create_order TypeError: int() can't convert non-string with explicit base #179

Open normanlmfung opened 1 year ago

normanlmfung commented 1 year ago

hi Team, I am following example here. With modifications (As seems API usage changed a little so sample no longer most up to date)

dydx-v3-python==1.9.1 client.private.createorder "TypeError: int() can't convert non-string with explicit base"_

Note that I got pass client instantiation, and called "get_account" to fetch position_id. Exception came in the end when "create_order" is called (Error stack revealed it's when client tried to sign the request when things fell apart).

from web3 import Web3 from dydx3 import Client from dydx3.constants import API_HOST_MAINNET from dydx3.constants import NETWORK_ID_MAINNET from dydx3.constants import MARKET_BTC_USD from dydx3.constants import ORDER_SIDE_BUY from dydx3.constants import ORDER_TYPE_LIMIT

LEDGER_WALLET_ETHEREUM_ADDRESS = "0x???????????????????????" API_KEY_CREDEMTIALS = { "walletAddress": "0x????????????????????????????????", "secret": "????????????????????????????????", "key": "????????????????????????????????", "passphrase": "????????????????????????????????", "legacySigning": False, "walletType": "METAMASK" } STARK_PUBLIC_KEY = "????????????????????????????????" STARK_PUBLIC_KEY_Y_COORDINATE = "????????????????????????????????" STARK_PRIVATE_KEY = "????????????????????????????????"

client = Client( network_id=NETWORK_ID_MAINNET, host=API_HOST_MAINNET, default_ethereum_address=LEDGER_WALLET_ETHEREUM_ADDRESS, web3=Web3(Web3.HTTPProvider(WEB_PROVIDER_URL)), api_key_credentials=API_KEY_CREDEMTIALS ) client.stark_private_key = { 'public_key' : "0x" + STARK_PUBLIC_KEY, 'public_key_y_coordinate' : "0x" + STARK_PUBLIC_KEY_Y_COORDINATE, 'private_key' : "0x" + STARK_PRIVATE_KEY }

account_response = client.private.get_account() position_id = account_response.data['account']['positionId']

order_response = client.private.create_order( position_id=position_id, market=MARKET_BTC_USD, side=ORDER_SIDE_BUY, order_type=ORDER_TYPE_LIMIT, post_only=True, size='0.001', price='1', limit_fee=0.0015, expiration_epoch_seconds=time.time() + 1000*60 )

Error at "create_order" was: Traceback (most recent call last): File "", line 1, in File "C:\Users\norman\AppData\Roaming\Python\Python39\site-packages\dydx3\modules\private.py", line 571, in create_order order_signature = order_to_sign.sign(self.stark_private_key) File "C:\Users\norman\AppData\Roaming\Python\Python39\site-packages\dydx3\starkex\signable.py", line 32, in sign r, s = sign(self.hash, int(private_key_hex, 16)) TypeError: int() can't convert non-string with explicit base

normanlmfung commented 1 year ago

I stepped into private.py, i think it's a bug in dydx3 client library.

stark_keys: { 'STARK_PUBLIC_KEY' : '0x?????????????????????????????????????', 'STARK_PUBLIC_KEY_Y_COORDINATE' : '0x?????????????????????????????????????', 'STARK_PRIVATE_KEY' : '0x?????????????????????????????????????' } client.stark_private_key = stark_keys

This way, client.private.stark_private_key will be a "Dict" as above variable "stark_keys". This will cause "sign" to blow up, as "sign" expect stark_private_key to be of format "0x????????????????????????", not a Dict! order_signature = order_to_sign.sign(self.stark_private_key)

I figured if I changed to below, get_account would still work and give me position_id: stark_keys: { 'STARK_PUBLIC_KEY' : '0x?????????????????????????????????????', 'STARK_PUBLIC_KEY_Y_COORDINATE' : '0x?????????????????????????????????????', 'STARK_PRIVATE_KEY' : '0x?????????????????????????????????????' } client.stark_private_key = stark_keys['private_key'] client.stark_public_key = stark_keys['public_key'] client.stark_public_key_y_coordinate = stark_keys['public_key_y_coordinate']

client.private.stark_private_key will be None! Again causing "sign" to blow up!

normanlmfung commented 1 year ago

Fixed example here: https://gist.github.com/normanlmfung/0a4bda9eb55d9d3560c76117bd6e2e50

Trick is:

client_private = client.private client_private.stark_private_key = stark_keys['private_key'] <---- Override stark_private_key here! order_response = client_private.create_order( position_id=position_id, market=MARKET_BTC_USD, side=ORDER_SIDE_BUY, order_type=ORDER_TYPE_LIMIT, post_only=True, size='0.001', price='1', limit_fee=0.0015, expiration_epoch_seconds=time.time() + 1000 * 60 )

order_id = order_response['order']['id']