dydxprotocol/dydx-v3-python

how to instantiate client for ledger wallets with no eth_private_key?

normanlmfung opened this issue · 2 comments

hi there,

how to instantiate client for ledger wallets with no eth_private_key?

I am following example here:

I want to simply query account "Equity".
client = Client(
network_id=NETWORK_ID_MAINNET,
host=API_HOST_MAINNET,
default_ethereum_address=ETHEREUM_ADDRESS,
eth_private_key=ETHEREUM_PRIVATE_KEY, <---- I dont have private key as it's ledger wallet, what to do?! (And I didnt use SAMPLE 1 to onboard the account. I done it via dydx website https://trade.dydx.exchange and there's no place from there where I can say export stark_public_key, stark_public_key_y_coordinate. Assuming this is what I need? I dont think "stark_private_key" can ever be exported?)
web3=Web3(Web3.HTTPProvider(WEB_PROVIDER_URL)),
)
stark_private_key = client.onboarding.derive_stark_key()
client.stark_private_key = stark_private_key

account_response = client.private.get_account().data['account']
account_free_collateral_usd = float(account_response['freeCollateral'])
account_equity_usd = float(account_response['equity'])

I checked client constructor:
class Client(object):
def init(
self,
host,
api_timeout=None,
default_ethereum_address=None,
eth_private_key=None,
eth_send_options=None,
network_id=None,
stark_private_key=None,
stark_public_key=None, <---- This is what I need?
stark_public_key_y_coordinate=None, <---- This is what I need?
web3=None,
web3_account=None,
web3_provider=None,
api_key_credentials=None,
crypto_c_exports_path=None,
)

Thanks in advance.

I also tried https://docs.dydx.exchange/?python#derive-starkkey

client.onboarding.derive_stark_key(ethereum_address=ETHEREUM_ADDRESS,)

Error was:
raise ValueError(response["error"])
ValueError: {'code': -32601, 'message': 'The method eth_signTypedData does not exist/is not available'}

I am guessing I can't just run derive_stark_key from some standalone python. I need to logon via https://trade.dydx.exchange, "Connect" to my wallet. Click approve from Ledger. Then from browser's Developer Console, somehow find the client object (How? I tried CTRL-SHIFT-F and search by "derive_stark_key", nothing. I searched "stark" also. But not sure how to go about get handle of "client" instance), then call "derive_stark_key" with it?

After digging around for awhile, I found this guy: https://www.reddit.com/r/dydxprotocol/comments/tn9hz9/derive_stark_key/

Basically, disconnect first. Then "Connect Wallet" again (With "Remember Me" enabled!). Then from Developer Tools (F12), under \ Local Storage \ https://trade.dydx.exchange, key = STARK_KEY_PAIRS, I found this object.

{
"walletAddress": "xxxxxx",
"publicKey": "xxxxx",
"publicKeyYCoordinate": "xxxxx",
"privateKey": "xxxxx", <----
"legacySigning": false,
"walletType": "METAMASK"
}

I used that,
client.stark_private_key = "... from Browser Developer Tools Local Storage ..."
account_response = client.private.get_account().data['account']

Still getting error:
File C:\ProgramData\Anaconda3\envs\py39\lib\site-packages\dydx3\dydx_client.py:147, in Client.private(self)
138 self._private = Private(
139 host=self.host,
140 network_id=self.network_id,
(...)
144 api_key_credentials=self.api_key_credentials,
145 )
146 else:
--> 147 raise Exception(
148 'Private endpoints not supported ' +
149 'since api_key_credentials were not specified',
150 )
151 return self._private

I dig further: https://blog.csdn.net/qq_27500493/article/details/120599965

You need to take two things from Local Storage!

a. \ Local Storage \ https://trade.dydx.exchange \ STARK_KEY_PAIRS

b. \ Local Storage \ https://trade.dydx.exchange \ API_KEY_PAIRS
On client instantiation, pass as "api_key_credentials" (Note format from local storage different from constructor arg "api_key_credentials")

From \ Local Storage \ https://trade.dydx.exchange \ API_KEY_PAIRS , format is like this:

{

"0xWALLET_ADDRESS": {

"walletAddress": "0xWALLET_ADDRESS",

"secret": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",

"key": "xxxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx",

"passphrase": "xxxxxxxxxxxxxxx",

"legacySigning": false,

"walletType": "METAMASK"

}

}

You need reformat to:

{

"walletAddress": "0xWALLET_ADDRESS",

"secret": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",

"key": "xxxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx",

"passphrase": "xxxxxxxxxxxxxxx",

"legacySigning": false,

"walletType": "METAMASK"

}

What a waste of time. But this works. Hope it helps someone else.

Solution in above