[Python] How to Correctly Decode a Jupiter Swap Event on Solana?

Discussão em 'Python' iniciado por Stack, Janeiro 31, 2025.

  1. Stack

    Stack Membro Participativo

    I am attempting to decode a Jupiter swap event on the Solana blockchain to extract token amounts and mint addresses from the transaction data. The expected output should look like this:

    {
    "amm": "whirLbMiicVdio4qvUfM5KAg6Ct8VwpYzGff3uctyCc",
    "inputMint": "So11111111111111111111111111111111111111112",
    "inputAmount": "14829998",
    "outputMint": "Hjw6bEcHtbHGpQr8onG3izfJY5DJiWdt7uk2BfdSpump",
    "outputAmount": "127849833"
    }


    Here is an exampleTransaction for reference.

    My Approach

    I am using construct to define the expected data structure and parse the event:

    from construct import Int64ul, Bytes
    from construct import Struct as cStruct
    import base58

    PUBLIC_KEY_LAYOUT = Bytes(32)

    JUP_SWAP = cStruct(
    "amm" / PUBLIC_KEY_LAYOUT,
    "inputMint" / PUBLIC_KEY_LAYOUT,
    "inputAmount" / Int64ul,
    "outputMint" / PUBLIC_KEY_LAYOUT,
    "outputAmount" / Int64ul,
    )

    # Raw transaction data (copied from Solscan in "raw" mode)
    hex_data = 'e445a52e51cb9a1d40c6cde8260871e20e03685f8e909053e458121c66f5a76aedc7706aa11c82f8aa952a8f2b7879a9069b8857feab8184fb687f634618c035dac439dc1aeb3b5598a0f00000000001ae49e20000000000f8ba8d41600d59ff5ede65103bfc142e5bc863e0e17ce50cc1155c425f02395f69d59e0700000000'

    # Convert hex to bytes and remove the first 8 bytes
    bytes_event = bytes.fromhex(hex_data)[8:]

    # Decode the event
    decoded_event = JUP_SWAP.parse(bytes_event)
    amm = base58.b58encode(decoded_event.amm).decode()
    input_mint = base58.b58encode(decoded_event.inputMint).decode()
    input_amount = decoded_event.inputAmount
    output_mint = base58.b58encode(decoded_event.outputMint).decode()
    output_amount = decoded_event.outputAmount

    print(f"amm: {amm}")
    print(f"inputMint: {input_mint}")
    print(f"inputAmount: {input_amount}")
    print(f"outputMint: {output_mint}")
    print(f"outputAmount: {output_amount}")


    Issue

    The output does not match the expected values:

    amm: 5Mrv98ERNPgDKHDFz8AjcebvXyf8dq9kp1yY1RAHSCJB
    inputMint: CUtETTsHosks4AUNtZuBZqb4Gn9k7JetykayaCyDcFq6
    inputAmount: 72057594053697688
    outputMint: CjMHLni4ZdtAi91Am1Vx63jCYL2bpEArkqzjzsBuaqMV
    outputAmount: 6861518115434141121


    I’ve tried multiple other decoding methods, including:

    Attempt 1: Using PublicKey and struct

    amm = PublicKey(buffer[0:32]).__str__()
    input_mint = PublicKey(buffer[32:64]).__str__()
    input_amount = struct.unpack("<Q", buffer[64:72])[0] # Little-endian u64
    output_mint = PublicKey(buffer[72:104]).__str__()
    output_amount = struct.unpack("<Q", buffer[104:112])[0] # Little-endian u64


    Attempt 2: Using base58 encoding

    amm = base58.b58encode(buffer[0:32]).decode()
    inputMint = base58.b58encode(buffer[32:64]).decode()
    inputAmount = int.from_bytes(buffer[64:72],'little')
    outputMint = base58.b58encode(buffer[72:104]).decode()
    outputAmount = int.from_bytes(buffer[104:112],'little')


    Attempt 3: Using struct.unpack

    unpacked = struct.unpack("=32s32sQ32sQ", buffer)
    amm = base58.b58encode(unpacked[0]).decode()
    inputMint = base58.b58encode(unpacked[2]).decode()
    inputAmount = unpacked[2]
    outputMint = base58.b58encode(unpacked[3]).decode()
    outputAmount = unpacked[4]


    Regardless of the method, the results remain incorrect.

    Question

    • What is the correct way to decode a Jupiter swap event on Solana? Am
    • I missing a step in parsing the transaction data?
    • Could there be an issue with endianness or byte alignment?

    I referenced the expected event structure from this IDL, but my results do not align.

    Any guidance or corrections would be greatly appreciated. Thanks in advance!

    Continue reading...

Compartilhe esta Página