solders

repository·main·Indexed 19 days ago

https://github.com/kevinheavey/solders

A high-performance Python toolkit for Solana written in Rust. It provides core SDK functionality including keypairs, pubkeys, transactions, and RPC request/response parsing. It also includes litesvm, a fast lightweight testing environment. While complementary to solana-py, solders focuses on high-performance core tasks and serialization without handling networking or server interaction.

Tokens
49.6K
Snippets
202
Records
236
Agent score
65%

What's inside solders

  1. What is solders used for?

    main

    solders is a high-performance Python toolkit for Solana written in Rust. It is designed for:

    • Core SDK operations: Managing keypairs, pubkeys, signing, and serializing transactions.
    • RPC operations: Building RPC requests and parsing responses (note: it does not handle networking).
    • Integration testing: Using the solders.litesvm module, which is a much faster and more convenient alternative to solana-test-validator based on solana-program-test.
  2. Use LiteSVM for fast Solana program testing

    main

    solders.litesvm is a Python wrapper for LiteSVM, providing a high-performance, ergonomic alternative to solana-test-validator for testing Solana programs. It is designed to be faster and more convenient for standard testing workflows than the standard validator or the older solders.bankrun module.

    By default, a LiteSVM instance includes core programs like the System Program and SPL Token.

  3. Explore SPL Token modules in Solders

    main

    The solders library provides support for SPL Tokens through two primary modules:

    • associated: Handles logic related to Associated Token Accounts (ATA).
    • state: Contains the data structures and state representations for SPL Tokens.

    Use these modules to interact with token accounts, manage token state, and handle associated token account derivations within the Solana ecosystem.

  4. Understand the relationship between solders and solana-py

    main

    solders and solana-py are complementary libraries. solana-py uses solders extensively for its core and RPC APIs.

    Key differences:

    Featuresolderssolana-py
    RPC InteractionProvides request/response parsing, but no networking/server interactionProvides full RPC server interaction functions
    SPL ClientsNo SPL Token or SPL Memo clientsProvides SPL Token and SPL Memo clients
    TestingIncludes solders.litesvm (fast alternative to solana-test-validator)Does not include litesvm
    CoverageComprehensive RPC request/response definitionsMay not support all RPC requests/responses provided by solders

    Recommendation: Use solders for high-performance core SDK tasks (keypairs, pubkeys, signing, serialization) and RPC parsing. Use solana-py if you need to actually communicate with an RPC server or use SPL clients.

  5. Understand the Pubkey class and curve properties

    main

    The Pubkey class represents both standard Ed25519 public keys and addresses that lie off the curve, such as Program-Derived Addresses (PDAs).

    To distinguish between a standard user-owned public key and a PDA, use the is_on_curve() method. A public key that returns True for is_on_curve() is suitable for users (it has a corresponding private key), whereas an address that returns False is an off-curve address (like a PDA) and does not have a private key.

    from solders.pubkey import Pubkey
    
    # A standard public key (on-curve)
    key = Pubkey.from_string('5oNDL3swdJJF1g9DzJiZ4ynHXgszjAEpUkxVYejchzrY')
    assert key.is_on_curve()
    
    # A PDA or off-curve address (not on-curve)
    off_curve_address = Pubkey.from_string('4BJXYkfvg37zEmBbsacZjeQDpTNx91KppxFJxRqrz48e')
    assert not off_curve_address.is_on_curve()
  6. Compare LiteSVM and solana-test-validator

    main

    Choosing between LiteSVM and solana-test-validator depends on your testing requirements:

    FeatureLiteSVMsolana-test-validator
    SpeedVery FastSlower
    ErgonomicsHigh (Pythonic)Lower (Unwieldy)
    RPC SupportLimitedFull
    RealismProgram/Client focusFull validator behavior

    Recommendation: Use LiteSVM wherever possible for program and client code testing. Use solana-test-validator only when you specifically need to test against real-life validator behavior or require RPC methods not yet supported by LiteSVM.

  7. Write arbitrary account data

    main
    LiteSVM allows you to manually write any account data you want, even if that state would be impossible in a real environment. This is highly useful for testing scenarios where you want to simulate existing assets (like USDC) without needing the actual mint keypair or performing complex setup steps.
  8. Implement partial signing using NullSigner

    main

    When a transaction requires multiple signatures but one signer is not immediately available (or should not share their keypair), you can use the NullSigner class to create a partially signed transaction.

    Workflow:

    1. Create a transaction including a NullSigner for the missing account.
    2. Serialize the transaction and send it to the missing signer.
    3. The missing signer deserializes the transaction using VersionedTransaction.from_bytes.
    4. The signer identifies the index of their public key within the message's account_keys.
    5. The signer generates a signature for the message using to_bytes_versioned(message).
    6. The signer replaces the dummy signature in the signatures list with their real signature.
    7. The transaction is now fully signed and ready for broadcast.
    from solders.hash import Hash
    from solders.instruction import AccountMeta, Instruction
    from solders.keypair import Keypair
    from solders.message import MessageV0, to_bytes_versioned
    from solders.null_signer import NullSigner
    from solders.pubkey import Pubkey
    from solders.transaction import VersionedTransaction
    
    keypair0 = Keypair()
    keypair1 = Keypair()
    ix = Instruction(
        Pubkey.new_unique(), b"", [AccountMeta(keypair1.pubkey(), True, False)]
    )
    message = MessageV0.try_compile(keypair0.pubkey(), [ix], [], Hash.default())
    # sign with a real signer and a null signer
    signers = (keypair0, NullSigner(keypair1.pubkey()))
    partially_signed = VersionedTransaction(message, signers)
    serialized = bytes(partially_signed)
    deserialized = VersionedTransaction.from_bytes(serialized)
    assert deserialized == partially_signed
    deserialized_message = deserialized.message
    # find the null signer in the deserialized transaction
    keypair1_sig_index = next(
        i
        for i, key in enumerate(deserialized_message.account_keys)
        if key == keypair1.pubkey()
    )
    sigs = deserialized.signatures
    # replace the null signature with a real signature
    sigs[keypair1_sig_index] = keypair1.sign_message(
        to_bytes_versioned(deserialized_message)
    )
    deserialized.signatures = sigs
    fully_signed = VersionedTransaction(message, [keypair0, keypair1])
    assert deserialized.signatures == fully_signed.signatures
    assert deserialized == fully_signed
    assert bytes(deserialized) == bytes(fully_signed)
  9. Deploy programs to LiteSVM

    main

    To test your own compiled Solana programs within LiteSVM, use the add_program_from_file method.

    If you need to test a program that exists on mainnet or devnet, you can first use the Solana CLI to dump the program to a file:

    solana program dump <PROGRAM_ID> <OUTPUT_FILE>

    Then, load it into your LiteSVM instance.

    # Example of adding a program from a file
    svm.add_program_from_file(program_id, file_path)