Type System
LUMOS supports a rich type system that maps cleanly between Rust and TypeScript.
Type Mapping Overview
Section titled “Type Mapping Overview”| LUMOS Type | Rust Type | TypeScript Type | Borsh Schema |
|---|---|---|---|
u8 | u8 | number | borsh.u8() |
u16 | u16 | number | borsh.u16() |
u32 | u32 | number | borsh.u32() |
u64 | u64 | number | borsh.u64() |
u128 | u128 | bigint | borsh.u128() |
i8 | i8 | number | borsh.i8() |
i16 | i16 | number | borsh.i16() |
i32 | i32 | number | borsh.i32() |
i64 | i64 | number | borsh.i64() |
i128 | i128 | bigint | borsh.i128() |
bool | bool | boolean | borsh.bool() |
String | String | string | borsh.string() |
PublicKey | Pubkey | PublicKey | borsh.publicKey() |
Signature | Signature | Uint8Array | borsh.array(borsh.u8(), 64) |
[T] | Vec<T> | T[] | borsh.vec(...) |
Option<T> | Option<T> | T | undefined | borsh.option(...) |
Primitive Types
Section titled “Primitive Types”Unsigned Integers
Section titled “Unsigned Integers”#[solana]struct Numbers { tiny: u8, // 0 to 255 small: u16, // 0 to 65,535 medium: u32, // 0 to 4,294,967,295 large: u64, // 0 to 18,446,744,073,709,551,615 huge: u128, // 0 to 340,282,366,920,938,463,463,374,607,431,768,211,455}Rust output:
pub struct Numbers { pub tiny: u8, pub small: u16, pub medium: u32, pub large: u64, pub huge: u128,}TypeScript output:
export interface Numbers { tiny: number; small: number; medium: number; large: number; // May lose precision > Number.MAX_SAFE_INTEGER huge: bigint;}Signed Integers
Section titled “Signed Integers”#[solana]struct SignedNumbers { tiny: i8, // -128 to 127 small: i16, // -32,768 to 32,767 medium: i32, // -2,147,483,648 to 2,147,483,647 large: i64, // Large signed range huge: i128, // Massive signed range}TypeScript mapping:
i8,i16,i32,i64→numberi128→bigint
Boolean
Section titled “Boolean”#[solana]struct Flags { is_active: bool, has_permission: bool,}Borsh encoding:
true→0x01false→0x00
String
Section titled “String”#[solana]struct Metadata { name: String, description: String, symbol: String,}Borsh encoding:
- Length prefix (4 bytes, little-endian)
- UTF-8 bytes
Example:
"hello"→0x05000000+0x68656c6c6f
Solana-Specific Types
Section titled “Solana-Specific Types”PublicKey
Section titled “PublicKey”Represents a Solana public key (32 bytes).
#[solana]struct Account { owner: PublicKey, authority: PublicKey,}Rust mapping:
use anchor_lang::prelude::*;
pub struct Account { pub owner: Pubkey, pub authority: Pubkey,}TypeScript mapping:
import { PublicKey } from '@solana/web3.js';
export interface Account { owner: PublicKey; authority: PublicKey;}
export const AccountBorshSchema = borsh.struct([ borsh.publicKey('owner'), borsh.publicKey('authority'),]);Borsh encoding:
- 32 bytes (fixed size)
Signature
Section titled “Signature”Represents a Solana signature (64 bytes).
#[solana]struct Transaction { signature: Signature,}Rust mapping:
pub struct Transaction { pub signature: Signature, // From solana_program}TypeScript mapping:
export interface Transaction { signature: Uint8Array; // 64 bytes}
export const TransactionBorshSchema = borsh.struct([ borsh.array(borsh.u8(), 64, 'signature'),]);Complex Types
Section titled “Complex Types”Vec (Arrays/Lists)
Section titled “Vec (Arrays/Lists)”Dynamic-length arrays.
#[solana]struct Inventory { items: [PublicKey], scores: [u64],}Rust output:
pub struct Inventory { pub items: Vec<Pubkey>, pub scores: Vec<u64>,}TypeScript output:
export interface Inventory { items: PublicKey[]; scores: number[];}
export const InventoryBorshSchema = borsh.struct([ borsh.vec(borsh.publicKey(), 'items'), borsh.vec(borsh.u64(), 'scores'),]);Borsh encoding:
- Length prefix (4 bytes, little-endian)
- Elements sequentially
Example:
[1, 2, 3]→0x03000000+0x01+0x02+0x03
Option (Optional Values)
Section titled “Option (Optional Values)”Nullable fields.
#[solana]struct Profile { username: String, email: Option<String>, avatar: Option<PublicKey>,}Rust output:
pub struct Profile { pub username: String, pub email: Option<String>, pub avatar: Option<Pubkey>,}TypeScript output:
export interface Profile { username: string; email: string | undefined; avatar: PublicKey | undefined;}
export const ProfileBorshSchema = borsh.struct([ borsh.string('username'), borsh.option(borsh.string(), 'email'), borsh.option(borsh.publicKey(), 'avatar'),]);Borsh encoding:
None→0x00Some(value)→0x01+ value bytes
Example:
None→0x00Some(42)→0x01+0x2a
Enum Types
Section titled “Enum Types”Rust-style enums with three variant types.
Unit Variants
Section titled “Unit Variants”#[solana]enum Status { Active, Paused, Terminated,}Rust output:
pub enum Status { Active, Paused, Terminated,}TypeScript output:
export type Status = | { kind: 'Active' } | { kind: 'Paused' } | { kind: 'Terminated' };
export const StatusBorshSchema = borsh.rustEnum([ borsh.unit('Active'), borsh.unit('Paused'), borsh.unit('Terminated'),]);Borsh encoding:
- Discriminant (1 byte) + variant data
Active→0x00Paused→0x01Terminated→0x02
Tuple Variants
Section titled “Tuple Variants”#[solana]enum Event { UserJoined(PublicKey), ScoreUpdated(PublicKey, u64), GameEnded(PublicKey, u64, i64),}Rust output:
pub enum Event { UserJoined(Pubkey), ScoreUpdated(Pubkey, u64), GameEnded(Pubkey, u64, i64),}TypeScript output:
export type Event = | { kind: 'UserJoined'; fields: [PublicKey] } | { kind: 'ScoreUpdated'; fields: [PublicKey, number] } | { kind: 'GameEnded'; fields: [PublicKey, number, number] };
export const EventBorshSchema = borsh.rustEnum([ borsh.tuple([borsh.publicKey()], 'UserJoined'), borsh.tuple([borsh.publicKey(), borsh.u64()], 'ScoreUpdated'), borsh.tuple([borsh.publicKey(), borsh.u64(), borsh.i64()], 'GameEnded'),]);Struct Variants
Section titled “Struct Variants”#[solana]enum Instruction { Initialize { authority: PublicKey, max_users: u32, }, UpdateConfig { new_authority: PublicKey, }, Terminate,}Rust output:
pub enum Instruction { Initialize { authority: Pubkey, max_users: u32, }, UpdateConfig { new_authority: Pubkey, }, Terminate,}TypeScript output:
export type Instruction = | { kind: 'Initialize'; authority: PublicKey; max_users: number } | { kind: 'UpdateConfig'; new_authority: PublicKey } | { kind: 'Terminate' };
export const InstructionBorshSchema = borsh.rustEnum([ borsh.struct([ borsh.publicKey('authority'), borsh.u32('max_users'), ], 'Initialize'), borsh.struct([ borsh.publicKey('new_authority'), ], 'UpdateConfig'), borsh.unit('Terminate'),]);Type Constraints
Section titled “Type Constraints”Not Supported
Section titled “Not Supported”The following types are NOT supported:
❌ Floating point (f32, f64)
❌ Fixed-size arrays ([u8; 32]) - use Vec or PublicKey
❌ Tuples ((u64, String)) - use structs instead
❌ References (&str, &[u8])
❌ Raw pointers (*const, *mut)
❌ Function pointers
Workarounds
Section titled “Workarounds”Fixed-size arrays → Vec:
// ❌ Not supportedstruct Data { buffer: [u8; 1024],}
// ✅ Use Vec insteadstruct Data { buffer: [u8], // Vec<u8>}Tuples → Struct:
// ❌ Not supportedstruct Pair { data: (u64, String),}
// ✅ Use struct insteadstruct Pair { first: u64, second: String,}Best Practices
Section titled “Best Practices”See Also
Section titled “See Also”- Attributes -
#[solana],#[account] - Generated Code - See actual output
- Examples - Real-world schemas