dydxprotocol/dydx-v3-python

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

normanlmfung opened this issue · 2 comments

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.create_order "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

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!

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