driftpy icon indicating copy to clipboard operation
driftpy copied to clipboard

Drift Client Subscribe Issue

Open slipshawn opened this issue 8 months ago • 3 comments

Subscribe call after initializing clien results in error. Following example documentation.

`drift_client = DriftClient( connection, wallet, account_subscription=AccountSubscriptionConfig("websocket"), )

await drift_client.add_user(0) await drift_client.subscribe()

File "C:\Users\ander.conda\envs\TradingPortal\Main\modules\crypto\drift\getting_started\perpmarkets_example.py", line 60, in main await drift_client.subscribe() File "C:\Users\ander\AppData\Roaming\Python\Python310\site-packages\driftpy\drift_client.py", line 201, in subscribe await self.account_subscriber.subscribe() File "C:\Users\ander\AppData\Roaming\Python\Python310\site-packages\driftpy\accounts\ws\drift_client.py", line 71, in subscribe ) = await find_all_market_and_oracles(self.program, data_and_slots=True) File "C:\Users\ander\AppData\Roaming\Python\Python310\site-packages\driftpy\constants\config.py", line 146, in find_all_market_and_oracles perp_markets: list[PerpMarketAccount] = [ File "C:\Users\ander\AppData\Roaming\Python\Python310\site-packages\driftpy\constants\config.py", line 147, in decode_account(account["account"]["data"][0], program) File "C:\Users\ander\AppData\Roaming\Python\Python310\site-packages\driftpy\constants\config.py", line 225, in decode_account return program.coder.accounts.decode(decoded_data) File "C:\Users\ander\AppData\Roaming\Python\Python310\site-packages\anchorpy\coder\accounts.py", line 51, in decode return self.parse(obj).data File "C:\Users\ander.conda\envs\TradingPortal\lib\site-packages\construct\core.py", line 288, in parse return self.parse_stream(io.BytesIO(data), **contextkw) File "C:\Users\ander.conda\envs\TradingPortal\lib\site-packages\construct\core.py", line 300, in parse_stream return self._parsereport(stream, context, "(parsing)") File "C:\Users\ander.conda\envs\TradingPortal\lib\site-packages\construct\core.py", line 312, in _parsereport obj = self._parse(stream, context, path) File "C:\Users\ander.conda\envs\TradingPortal\lib\site-packages\construct\core.py", line 703, in _parse obj = self.subcon._parsereport(stream, context, path) File "C:\Users\ander.conda\envs\TradingPortal\lib\site-packages\construct\core.py", line 312, in _parsereport obj = self._parse(stream, context, path) File "C:\Users\ander.conda\envs\TradingPortal\lib\site-packages\construct\core.py", line 2275, in _parse subobj = sc._parsereport(stream, context, path) File "C:\Users\ander.conda\envs\TradingPortal\lib\site-packages\construct\core.py", line 312, in _parsereport obj = self._parse(stream, context, path) File "C:\Users\ander.conda\envs\TradingPortal\lib\site-packages\construct\core.py", line 3919, in _parse return sc._parsereport(stream, context, path) File "C:\Users\ander.conda\envs\TradingPortal\lib\site-packages\construct\core.py", line 312, in _parsereport obj = self._parse(stream, context, path) File "C:\Users\ander.conda\envs\TradingPortal\lib\site-packages\construct\core.py", line 2653, in _parse return self.subcon._parsereport(stream, context, path) File "C:\Users\ander.conda\envs\TradingPortal\lib\site-packages\construct\core.py", line 312, in _parsereport obj = self._parse(stream, context, path) File "C:\Users\ander.conda\envs\TradingPortal\lib\site-packages\construct\core.py", line 703, in _parse obj = self.subcon._parsereport(stream, context, path) File "C:\Users\ander.conda\envs\TradingPortal\lib\site-packages\construct\core.py", line 312, in _parsereport obj = self._parse(stream, context, path) File "C:\Users\ander.conda\envs\TradingPortal\lib\site-packages\construct\core.py", line 2120, in _parse subobj = sc._parsereport(stream, context, path) File "C:\Users\ander.conda\envs\TradingPortal\lib\site-packages\construct\core.py", line 312, in _parsereport obj = self._parse(stream, context, path) File "C:\Users\ander.conda\envs\TradingPortal\lib\site-packages\construct\core.py", line 2653, in _parse return self.subcon._parsereport(stream, context, path) File "C:\Users\ander.conda\envs\TradingPortal\lib\site-packages\construct\core.py", line 312, in _parsereport obj = self._parse(stream, context, path) File "C:\Users\ander.conda\envs\TradingPortal\lib\site-packages\construct\core.py", line 703, in _parse obj = self.subcon._parsereport(stream, context, path) File "C:\Users\ander.conda\envs\TradingPortal\lib\site-packages\construct\core.py", line 312, in _parsereport obj = self._parse(stream, context, path) File "C:\Users\ander.conda\envs\TradingPortal\lib\site-packages\construct\core.py", line 2120, in _parse subobj = sc._parsereport(stream, context, path) File "C:\Users\ander.conda\envs\TradingPortal\lib\site-packages\construct\core.py", line 312, in _parsereport obj = self._parse(stream, context, path) File "C:\Users\ander.conda\envs\TradingPortal\lib\site-packages\construct\core.py", line 2653, in _parse return self.subcon._parsereport(stream, context, path) File "C:\Users\ander.conda\envs\TradingPortal\lib\site-packages\construct\core.py", line 312, in _parsereport obj = self._parse(stream, context, path) File "C:\Users\ander.conda\envs\TradingPortal\lib\site-packages\construct\core.py", line 704, in _parse return self._decode(obj, context, path) File "C:\Users\ander.conda\envs\TradingPortal\lib\site-packages\borsh_construct\enum.py", line 110, in _decode enum_variant = self.enum.getitem(index) File "C:\Users\ander.conda\envs\TradingPortal\lib\site-packages\borsh_construct\enum.py", line 19, in getitem return getattr(cls, cls._sumtype_constructor_names[_index]) IndexError: list index out of range `

slipshawn avatar Apr 17 '25 19:04 slipshawn

I get this error too. I ran a RCA. These were the permanent fixes the team needed to make:

Required SDK Modifications

For a permanent fix, the driftpy repository needs:

  1. Dynamic IDL Loading
# In drift_client.py
async def load_idl(self):
    idl_addr = Pubkey.find_program_address([], self.program_id)[0]
    idl_account = await self.connection.get_account_info(idl_addr)
    return IDL.parse(idl_account.data)
  1. Enum Deserialization Patch
# In borsh_construct/enum.py
def getitem(self, index: int):
    if index >= len(self._sumtype_constructor_names):
        return UnknownVariant  # New fallback type
    return getattr(self.enum, self._sumtype_constructor_names[index])

Verification Steps

  1. Confirm IDL version matches program:
curl -sS https://api.mainnet-beta.solana.com/account/dRiftyHA39MWEi3m9aunc5MzRF1JYuBsbn6VPcn33UH | jq .result.value.data[0]
  1. Validate RPC response format:
from solana.rpc.async_api import AsyncClient
conn = AsyncClient("YOUR_RPC_URL")
print(await conn.get_account_info(Pubkey.from_string("zDdAnA9jYe7GmeZ6Z5aHFpzZ3YtUWvJ9RR57h8Q8QBc")))  # Sample market account

This approach addresses the core deserialization mismatch while maintaining compatibility with recent protocol changes. The combination of IDL validation, safe market fetching, and enhanced enum handling provides robustness against future schema evolution.

witwiki avatar May 06 '25 03:05 witwiki

Which driftpy version are yall using?

crispheaney avatar May 07 '25 20:05 crispheaney

version 0.8.47

witwiki avatar May 09 '25 03:05 witwiki