kevinheavey / solders

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

Understanding how to handle RPC responses elegantly with this library #63

Closed raymondjacobson closed 1 year ago

raymondjacobson commented 1 year ago

Hi, feel free to close this issue if more appropriately handled elsewhere.

I'm trying to understand the best way to use solders w/ the solana-py library.

We have a very common pattern that looks like this

from solana.rpc.api import Client
from solders.signature import Signature
c = Client("https://api.mainnet-beta.solana.com")
c.get_transaction(
    Signature.from_string(
        '2DUH6nXnS4EXCqPdgxGvAiLyemZ8WkB69VyjhiGgE3HZxsbXWdk8SuZbGCkyV7oN6b7DHHVggaB8QSCKp5YNk7QJ'
    ),
    'json'
)

This gives us a GetTransactionResp object.

We often want the memo, err (if any), instructions, etc. from the response, but it seems like every step of the way we have potential None to deal with. And since python does not have null chaining/coalescing, we end up having a lot of code like this

        result = transaction_resp.value
        if not result:
            return None

        meta = result.transaction.meta
        if not meta:
            return None

        if meta.err:
            return None 

        tx_message = result.transaction.transaction.message # this will fail because only some of the types this could return have a message

Is there a different/more canonical way we should be using types from this library?

raymondjacobson commented 1 year ago

Perhaps there should be a typecast up front when we get something back from RPC?

raymondjacobson commented 1 year ago

Another similar example:

If I wanted to get the accounts in the first instruction, my best guess would be:

>>> t.value.transaction.transaction.message.instructions[0].accounts
b'\x00\x01\x02\x03\x04\x05\x06'

Which does not give us a List[AccountMeta] that I would have expected because this is a CompiledInstruction rather than just a vanilla Instruction

kevinheavey commented 1 year ago

As far as I can see all these types are just a reflection of what the RPC returns. Am I missing something that could be a narrower or more useful type?

raymondjacobson commented 1 year ago

As far as I can see all these types are just a reflection of what the RPC returns. Am I missing something that could be a narrower or more useful type?

Thanks @kevinheavey . Yes it is accurate... it is just not the most ergonomic. In my cases, I can guarantee that result.transaction.transaction.message exists on everything I am pulling in and having to deal with these Nones all across the codebase is a challenge. Maybe a custom wrapper we can write around types on our end with some basic assertions. I'll close this issue as I think it's a taller order, but something perhaps that should be considered in future iteration :)