kevinheavey / solders

A high-performance Python toolkit for Solana, written in Rust
https://kevinheavey.github.io/solders/
Apache License 2.0
232 stars 26 forks source link

JSON parsing error on websocket_api.program_subscribe() #69

Closed Phylante closed 10 months ago

Phylante commented 10 months ago

Hello, I am reporting this while using solana-py==0.30.2 and solders==0.18.1 The reason I report this in solders and not solana-py is that the issue seem related directly to the JSON parsing, hence, solders.

I've taken the canonical example given on the documentation, and changed the log_subscribe call with program_subscribe.

Before any further investigation, you should check that the ID I provided is indeed supposed to be taken as a parameter for the program_subscribe method, as I am still a newbie with solana, and I may have taken it for a program address while it is not (but I believe it is, according to solscan).

Here is a full working example to reproduce :

import asyncio
from solders.pubkey import Pubkey
from solana.rpc.websocket_api import connect

LIQUIDITY_POOL_PROGRAM_ID_V4 = '675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8'

async def main():
    program_id = Pubkey.from_string(LIQUIDITY_POOL_PROGRAM_ID_V4)

    async with connect("wss://api.mainnet-beta.solana.com") as websocket:

        await websocket.program_subscribe(program_id)
        first_resp = await websocket.recv()
        subscription_id = first_resp[0].result
        print("First rep is : ")
        print(first_resp)
        print()
        response = await websocket.recv()
        print(response)

        await websocket.program_unsubscribe(subscription_id)

asyncio.run(main())

When running this, I get a stacktrace. In order to provide something that may help, I put a few print in _process_rpc_response, basically printing the raw parameter The output of the program looks like that, stacktrace included :

Print in websocket_api, by phylante, for debug : 
{"jsonrpc":"2.0","result":230891,"id":1}

First rep is : 
[SubscriptionResult {
    jsonrpc: TwoPointOh,
    id: 1,
    result: 230891,
}]

Print in websocket_api, by phylante, for debug : 
{"jsonrpc":"2.0","method":"programNotification","params":{"result":{"context":{"slot":236633032},"value":{"pubkey":"7wZpAKYM1uygtosoF42V4a5tVLsrzpSN6Uedaxc6vGrQ","account":{"lamports":16258560,"data":"error: data too large for bs58 encoding","owner":"675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8","executable":false,"rentEpoch":0,"space":2208}}},"subscription":230891}}

Traceback (most recent call last):
  File "/home/phylante/code/solana_new_listings/src/listen_for_account.py", line 23, in <module>
    asyncio.run(main())
  File "/usr/lib/python3.10/asyncio/runners.py", line 44, in run
    return loop.run_until_complete(main)
  File "/usr/lib/python3.10/asyncio/base_events.py", line 649, in run_until_complete
    return future.result()
  File "/home/phylante/code/solana_new_listings/src/listen_for_account.py", line 18, in main
    response = await websocket.recv()
  File "/home/phylante/code/solana_new_listings/venv/lib/python3.10/site-packages/solana/rpc/websocket_api.py", line 108, in recv
    return self._process_rpc_response(cast(str, data))
  File "/home/phylante/code/solana_new_listings/venv/lib/python3.10/site-packages/solana/rpc/websocket_api.py", line 350, in _process_rpc_response
    parsed = parse_websocket_message(raw)
solders.SerdeJSONError: a list or single element

Running this code with the program ID "11111111111111111111111111111111" gives me some notifications, so I assume this is a bug with this particular message.

Thanks in advance for looking into this.

kevinheavey commented 10 months ago

Looks like the account encoding is defaulting to base58, which is bad. Hence why the response says "data":"error: data too large for bs58 encoding".

I'll fix the default in solana-py, but in the meantime you should be able to avoid this issue with await websocket.program_subscribe(program_id, encoding="base64")

Phylante commented 8 months ago

It's been a while, but just tested this, and it does the trick. Thank you very much