Python bindings for Solana Rust tools providing high-performance blockchain development primitives, RPC functionality, and testing infrastructure.
—
Account data structures, encoding formats, and metadata handling for both raw and parsed account information. This includes account state management, commitment levels, data encoding options, and parsing utilities for program-specific account data.
Core account representations containing balance, data, ownership, and metadata information.
class Account:
"""
Solana account containing balance, data, owner, and metadata.
"""
def __init__(self, lamports: int, data: bytes, owner: Pubkey, executable: bool, rent_epoch: int):
"""
Create account with balance, data, and metadata.
Parameters:
- lamports: int, account balance in lamports (1 SOL = 1e9 lamports)
- data: bytes, account data (program-specific)
- owner: Pubkey, program that owns this account
- executable: bool, whether account contains executable program code
- rent_epoch: int, epoch when rent was last collected
"""
@classmethod
def default() -> 'Account':
"""
Create default empty account.
Returns:
Account with zero balance, empty data, system program owner
"""
@property
def lamports(self) -> int:
"""Account balance in lamports."""
@property
def data(self) -> bytes:
"""Account data bytes."""
@property
def owner(self) -> Pubkey:
"""Program that owns this account."""
@property
def executable(self) -> bool:
"""Whether account contains executable code."""
@property
def rent_epoch(self) -> int:
"""Epoch when rent was last collected."""
def serialize(self) -> bytes:
"""
Serialize account to bytes.
Returns:
bytes, serialized account data
"""
@classmethod
def deserialize(cls, data: bytes) -> 'Account':
"""
Deserialize account from bytes.
Parameters:
- data: bytes, serialized account data
Returns:
Account object
"""class AccountJSON:
"""
JSON-serializable account representation for RPC responses.
"""
def __init__(
self,
lamports: int,
data: Union[str, List[str]],
owner: str,
executable: bool,
rent_epoch: int
):
"""
Create JSON account representation.
Parameters:
- lamports: int, account balance
- data: Union[str, List[str]], encoded account data
- owner: str, base58 owner pubkey
- executable: bool, executable flag
- rent_epoch: int, rent epoch
"""
def to_json(self) -> dict:
"""
Convert to JSON dictionary.
Returns:
dict, JSON-compatible account data
"""
@classmethod
def from_json(cls, data: dict) -> 'AccountJSON':
"""
Create from JSON dictionary.
Parameters:
- data: dict, JSON account data
Returns:
AccountJSON object
"""Data encoding formats and parsing utilities for account data representation.
class UiAccountEncoding:
"""
Account data encoding format enumeration.
"""
Base64: 'UiAccountEncoding' # Base64 encoded data
JsonParsed: 'UiAccountEncoding' # Parsed JSON format (program-specific)
Base58: 'UiAccountEncoding' # Base58 encoded data
Base64Zstd: 'UiAccountEncoding' # Base64 + Zstandard compression
def __str__(self) -> str:
"""String representation of encoding type."""class ParsedAccount:
"""
Account with parsed/decoded program-specific data.
"""
def __init__(self, account: Account, parsed_data: Optional[dict]):
"""
Create parsed account with structured data.
Parameters:
- account: Account, base account information
- parsed_data: Optional[dict], program-specific parsed data
"""
@property
def account(self) -> Account:
"""Base account information."""
@property
def parsed_data(self) -> Optional[dict]:
"""Program-specific parsed data."""
def is_token_account(self) -> bool:
"""
Check if account contains SPL token data.
Returns:
bool, True if account is token account
"""
def is_mint_account(self) -> bool:
"""
Check if account contains SPL mint data.
Returns:
bool, True if account is mint account
"""class UiDataSliceConfig:
"""
Configuration for slicing account data in RPC requests.
"""
def __init__(self, offset: int, length: int):
"""
Create data slice configuration.
Parameters:
- offset: int, byte offset to start slice
- length: int, number of bytes to return
"""
@property
def offset(self) -> int:
"""Slice offset in bytes."""
@property
def length(self) -> int:
"""Slice length in bytes."""Specialized handling for token amounts with proper decimal representation.
class UiTokenAmount:
"""
Token amount with decimal precision handling.
"""
def __init__(self, ui_amount: Optional[float], decimals: int, amount: str, ui_amount_string: str):
"""
Create token amount with decimal handling.
Parameters:
- ui_amount: Optional[float], human-readable amount (may be None for large numbers)
- decimals: int, number of decimal places for token
- amount: str, raw amount as string (no decimal adjustment)
- ui_amount_string: str, human-readable amount as string
"""
@property
def ui_amount(self) -> Optional[float]:
"""Human-readable amount (float, may be None for large values)."""
@property
def decimals(self) -> int:
"""Number of decimal places for this token."""
@property
def amount(self) -> str:
"""Raw token amount as string."""
@property
def ui_amount_string(self) -> str:
"""Human-readable amount as string."""
def to_float(self) -> float:
"""
Convert to float value.
Returns:
float, token amount as floating point
Raises:
- ValueError: if amount cannot be represented as float
"""
def to_decimal(self) -> 'Decimal':
"""
Convert to decimal for precise arithmetic.
Returns:
Decimal, exact token amount
"""Transaction commitment levels and account query configuration.
class CommitmentLevel:
"""
Transaction confirmation levels.
"""
Processed: 'CommitmentLevel' # Transaction processed but not confirmed
Confirmed: 'CommitmentLevel' # Transaction confirmed by cluster
Finalized: 'CommitmentLevel' # Transaction finalized (cannot be rolled back)
def __str__(self) -> str:
"""String representation of commitment level."""class CommitmentConfig:
"""
Configuration for RPC request commitment level.
"""
def __init__(self, commitment: CommitmentLevel):
"""
Create commitment configuration.
Parameters:
- commitment: CommitmentLevel, desired confirmation level
"""
@classmethod
def processed() -> 'CommitmentConfig':
"""
Create processed commitment config.
Returns:
CommitmentConfig for processed transactions
"""
@classmethod
def confirmed() -> 'CommitmentConfig':
"""
Create confirmed commitment config.
Returns:
CommitmentConfig for confirmed transactions
"""
@classmethod
def finalized() -> 'CommitmentConfig':
"""
Create finalized commitment config.
Returns:
CommitmentConfig for finalized transactions
"""
@property
def commitment(self) -> CommitmentLevel:
"""Commitment level."""from solders.account import Account
from solders.pubkey import Pubkey
# Create account
owner = Pubkey.from_string("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA")
account_data = b"token_account_data_here"
account = Account(
lamports=2039280, # Rent-exempt minimum
data=account_data,
owner=owner,
executable=False,
rent_epoch=361
)
print(f"Account balance: {account.lamports / 1e9:.9f} SOL")
print(f"Data length: {len(account.data)} bytes")
print(f"Owner: {account.owner}")
print(f"Executable: {account.executable}")from solders.account_decoder import UiTokenAmount
from decimal import Decimal
# Token amount with 6 decimals (USDC-style)
token_amount = UiTokenAmount(
ui_amount=1000.50,
decimals=6,
amount="1000500000", # Raw amount: 1000.5 * 10^6
ui_amount_string="1000.5"
)
print(f"UI amount: {token_amount.ui_amount}")
print(f"Raw amount: {token_amount.amount}")
print(f"Decimals: {token_amount.decimals}")
# Precise decimal arithmetic
precise_amount = token_amount.to_decimal()
print(f"Precise amount: {precise_amount}")
# Large number handling (ui_amount may be None)
large_amount = UiTokenAmount(
ui_amount=None, # Too large for float
decimals=9,
amount="999999999999999999999",
ui_amount_string="999999999999.999999999"
)from solders.account_decoder import UiDataSliceConfig
# Get first 64 bytes of account data
slice_config = UiDataSliceConfig(offset=0, length=64)
# Get specific portion (e.g., skip mint info, get owner)
token_account_slice = UiDataSliceConfig(offset=32, length=32)
print(f"Slice offset: {slice_config.offset}")
print(f"Slice length: {slice_config.length}")from solders.commitment_config import CommitmentLevel, CommitmentConfig
# Different commitment levels
processed_config = CommitmentConfig.processed()
confirmed_config = CommitmentConfig.confirmed()
finalized_config = CommitmentConfig.finalized()
# Check commitment level
if confirmed_config.commitment == CommitmentLevel.Confirmed:
print("Using confirmed commitment level")
# Custom commitment
custom_config = CommitmentConfig(CommitmentLevel.Finalized)# Serialize account for storage or transmission
serialized = account.serialize()
print(f"Serialized size: {len(serialized)} bytes")
# Deserialize account
restored_account = Account.deserialize(serialized)
assert restored_account.lamports == account.lamports
assert restored_account.data == account.data
assert restored_account.owner == account.ownerfrom solders.account import AccountJSON
# Create JSON representation
json_account = AccountJSON(
lamports=2039280,
data="dGVzdF9kYXRh", # Base64 encoded data
owner="TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA",
executable=False,
rent_epoch=361
)
# Convert to dictionary for JSON serialization
json_dict = json_account.to_json()
# Restore from JSON
restored = AccountJSON.from_json(json_dict)from solders.account_decoder import ParsedAccount
# Parsed token account data
parsed_data = {
"type": "account",
"info": {
"mint": "So11111111111111111111111111111111111111112",
"owner": "7dHbWXmci3dT8UFYWYZweBLXgycu7Y3iL6trKn1Y7ARj",
"tokenAmount": {
"amount": "1000000000",
"decimals": 9,
"uiAmount": 1.0,
"uiAmountString": "1"
}
}
}
parsed_account = ParsedAccount(account, parsed_data)
# Check account type
if parsed_account.is_token_account():
print("This is a token account")
token_info = parsed_account.parsed_data["info"]
print(f"Token mint: {token_info['mint']}")
print(f"Owner: {token_info['owner']}")
if parsed_account.is_mint_account():
print("This is a mint account")# New account (empty, system-owned)
new_account = Account.default()
assert new_account.lamports == 0
assert new_account.owner == SYSTEM_PROGRAM_ID
assert not new_account.executable
# Funded account
funded_account = Account(
lamports=5000000, # 0.005 SOL
data=b"",
owner=SYSTEM_PROGRAM_ID,
executable=False,
rent_epoch=361
)
# Program account (executable)
program_account = Account(
lamports=10000000,
data=b"program_bytecode_here",
owner=SYSTEM_PROGRAM_ID,
executable=True,
rent_epoch=361
)from solders.rent import Rent
# Calculate rent exemption
rent = Rent.default()
data_size = 165 # Size of token account
minimum_balance = rent.minimum_balance(data_size)
# Check if account is rent exempt
def is_rent_exempt(account: Account) -> bool:
return account.lamports >= minimum_balance
if is_rent_exempt(account):
print("Account is rent exempt")
else:
print(f"Need {minimum_balance - account.lamports} more lamports for rent exemption")import base64
import base58
def encode_account_data(data: bytes, encoding: UiAccountEncoding) -> Union[str, List[str]]:
"""Encode account data in specified format."""
if encoding == UiAccountEncoding.Base64:
return base64.b64encode(data).decode()
elif encoding == UiAccountEncoding.Base58:
return base58.b58encode(data).decode()
elif encoding == UiAccountEncoding.JsonParsed:
# Would require program-specific parsing
return "parsed"
else:
return data.hex()
def decode_account_data(encoded_data: str, encoding: UiAccountEncoding) -> bytes:
"""Decode account data from specified format."""
if encoding == UiAccountEncoding.Base64:
return base64.b64decode(encoded_data)
elif encoding == UiAccountEncoding.Base58:
return base58.b58decode(encoded_data)
else:
return bytes.fromhex(encoded_data)# System Program ID (default owner for user accounts)
SYSTEM_PROGRAM_ID: Final[Pubkey] = Pubkey.from_string("11111111111111111111111111111112")
# Native SOL Token Mint
NATIVE_MINT: Final[Pubkey] = Pubkey.from_string("So11111111111111111111111111111111111111112")# Default commitment level for most operations
DEFAULT_COMMITMENT: Final[CommitmentLevel] = CommitmentLevel.Finalized
# Minimum account sizes
MINIMUM_ACCOUNT_SIZE: Final[int] = 0
TOKEN_ACCOUNT_SIZE: Final[int] = 165
MINT_ACCOUNT_SIZE: Final[int] = 82