Python Types
LUMOS generates Python dataclasses with borsh-construct for Borsh serialization.
Installation
Section titled “Installation”pip install borsh-constructType Mapping Reference
Section titled “Type Mapping Reference”| LUMOS Type | Python Type | Borsh Schema |
|---|---|---|
u8 | int | U8 |
u16 | int | U16 |
u32 | int | U32 |
u64 | int | U64 |
u128 | int | U128 |
i8 | int | I8 |
i16 | int | I16 |
i32 | int | I32 |
i64 | int | I64 |
i128 | int | I128 |
bool | bool | Bool |
String | str | String |
PublicKey | bytes | Bytes(32) |
Signature | bytes | Bytes(64) |
Vec<T> | List[T] | Vec(T) |
Option<T> | Optional[T] | Option(T) |
[T; N] | List[T] | Bytes(N) or Array(T, N) |
Generated Code Example
Section titled “Generated Code Example”LUMOS Schema
Section titled “LUMOS Schema”#[solana]struct PlayerAccount { wallet: PublicKey, level: u16, experience: u64, username: String, guild: Option<PublicKey>, inventory: [u8],}Generated Python
Section titled “Generated Python”"""Generated by LUMOS - Do not edit manuallySchema: player_account.lumos"""from dataclasses import dataclassfrom typing import Optional, Listfrom borsh_construct import CStruct, U8, U16, U64, String, Vec, Option, Bytes
@dataclassclass PlayerAccount: """PlayerAccount - Generated from LUMOS schema""" wallet: bytes # PublicKey (32 bytes) level: int # u16 experience: int # u64 username: str # String guild: Optional[bytes] # Option<PublicKey> inventory: List[int] # Vec<u8>
# Borsh schema for serializationPlayerAccountSchema = CStruct( "wallet" / Bytes(32), "level" / U16, "experience" / U64, "username" / String, "guild" / Option(Bytes(32)), "inventory" / Vec(U8),)Usage Examples
Section titled “Usage Examples”Serialization
Section titled “Serialization”from player_schema import PlayerAccount, PlayerAccountSchema
# Create an accountaccount = PlayerAccount( wallet=bytes.fromhex("11" * 32), # 32-byte public key level=42, experience=150000, username="CryptoGamer", guild=None, # No guild inventory=[1, 2, 3, 4, 5],)
# Serialize to bytesserialized = PlayerAccountSchema.build(account.__dict__)print(f"Serialized: {serialized.hex()}")Deserialization
Section titled “Deserialization”# Deserialize from bytesdata = bytes.fromhex("...") # Borsh-encoded dataparsed = PlayerAccountSchema.parse(data)
account = PlayerAccount( wallet=parsed.wallet, level=parsed.level, experience=parsed.experience, username=parsed.username, guild=parsed.guild, inventory=list(parsed.inventory),)
print(f"Level: {account.level}")print(f"XP: {account.experience}")Enum Support
Section titled “Enum Support”Unit Enums
Section titled “Unit Enums”from enum import IntEnum
class GameStatus(IntEnum): """GameStatus enum""" Active = 0 Paused = 1 Ended = 2
GameStatusSchema = U8 # Simple discriminantComplex Enums
Section titled “Complex Enums”from dataclasses import dataclassfrom typing import Union
@dataclassclass Transfer: """Transfer variant""" recipient: bytes amount: int
@dataclassclass Stake: """Stake variant""" validator: bytes amount: int
# Union type for enumInstruction = Union[Transfer, Stake]Best Practices
Section titled “Best Practices”1. PublicKey Handling
Section titled “1. PublicKey Handling”# Convert to/from base58import base58
def pubkey_to_base58(pubkey: bytes) -> str: return base58.b58encode(pubkey).decode()
def base58_to_pubkey(s: str) -> bytes: return base58.b58decode(s)2. Large Integer Safety
Section titled “2. Large Integer Safety”Python’s int handles arbitrary precision, so no overflow concerns:
# Safe in Pythonmax_u64 = 18446744073709551615max_u128 = 340282366920938463463374607431768211455
# Both work correctlyaccount.balance = max_u64account.total_supply = max_u1283. Optional Fields
Section titled “3. Optional Fields”# Check optional fields before useif account.guild is not None: print(f"Guild: {pubkey_to_base58(account.guild)}")else: print("No guild")Integration with Solana
Section titled “Integration with Solana”Reading Account Data
Section titled “Reading Account Data”from solana.rpc.api import Clientfrom solana.publickey import PublicKey
client = Client("https://api.devnet.solana.com")
# Fetch accountaccount_pubkey = PublicKey("...")response = client.get_account_info(account_pubkey)
if response["result"]["value"]: data = base64.b64decode(response["result"]["value"]["data"][0]) # Skip 8-byte discriminator for Anchor accounts account_data = data[8:] parsed = PlayerAccountSchema.parse(account_data)See Also
Section titled “See Also”- Type System - Full type reference
- Go Types - Go type mappings
- Ruby Types - Ruby type mappings