or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

account-management.mdcryptographic-primitives.mderror-handling.mdindex.mdnetwork-sysvars.mdrpc-functionality.mdsystem-programs.mdtesting-infrastructure.mdtoken-operations.mdtransaction-construction.mdtransaction-status.md

network-sysvars.mddocs/

0

# Network and Sysvars

1

2

Network configuration, system variables, and blockchain state including clock information, rent parameters, epoch scheduling, and validator information. These provide essential network parameters and real-time blockchain state for building robust Solana applications.

3

4

## Capabilities

5

6

### System Variables (Sysvars)

7

8

System accounts that contain network configuration and state information accessible to all programs.

9

10

```python { .api }

11

# Sysvar Account IDs - Well-known addresses for system variables

12

CLOCK: Final[Pubkey] = Pubkey.from_string("SysvarC1ock11111111111111111111111111111111")

13

RECENT_BLOCKHASHES: Final[Pubkey] = Pubkey.from_string("SysvarRecentB1ockHashes11111111111111111111")

14

RENT: Final[Pubkey] = Pubkey.from_string("SysvarRent111111111111111111111111111111111")

15

REWARDS: Final[Pubkey] = Pubkey.from_string("SysvarRewards111111111111111111111111111111")

16

STAKE_HISTORY: Final[Pubkey] = Pubkey.from_string("SysvarStakeHistory1111111111111111111111111")

17

EPOCH_SCHEDULE: Final[Pubkey] = Pubkey.from_string("SysvarEpochSchedu1e111111111111111111111111111")

18

INSTRUCTIONS: Final[Pubkey] = Pubkey.from_string("Sysvar1nstructions1111111111111111111111111")

19

SLOT_HASHES: Final[Pubkey] = Pubkey.from_string("SysvarS1otHashes111111111111111111111111111")

20

```

21

22

### Clock Information

23

24

Network time and slot information for transaction timing and epoch tracking.

25

26

```python { .api }

27

class Clock:

28

"""

29

Network time information including slot, epoch, and timestamp data.

30

"""

31

def __init__(

32

self,

33

slot: int,

34

epoch_start_timestamp: Optional[int],

35

epoch: int,

36

leader_schedule_epoch: int,

37

unix_timestamp: int

38

):

39

"""

40

Create clock information.

41

42

Parameters:

43

- slot: int, current slot number

44

- epoch_start_timestamp: Optional[int], Unix timestamp when current epoch started

45

- epoch: int, current epoch number

46

- leader_schedule_epoch: int, epoch for which leader schedule is valid

47

- unix_timestamp: int, estimated current Unix timestamp

48

"""

49

50

@classmethod

51

def deserialize(cls, data: bytes) -> 'Clock':

52

"""

53

Deserialize clock from sysvar account data.

54

55

Parameters:

56

- data: bytes, clock sysvar account data

57

58

Returns:

59

Clock object

60

"""

61

62

def serialize(self) -> bytes:

63

"""

64

Serialize clock to bytes.

65

66

Returns:

67

bytes, serialized clock data

68

"""

69

70

@property

71

def slot(self) -> int:

72

"""Current slot number."""

73

74

@property

75

def epoch_start_timestamp(self) -> Optional[int]:

76

"""Unix timestamp when current epoch started."""

77

78

@property

79

def epoch(self) -> int:

80

"""Current epoch number."""

81

82

@property

83

def leader_schedule_epoch(self) -> int:

84

"""Epoch for which leader schedule is valid."""

85

86

@property

87

def unix_timestamp(self) -> int:

88

"""Estimated current Unix timestamp."""

89

90

def slots_since_epoch_start(self) -> int:

91

"""

92

Calculate slots elapsed in current epoch.

93

94

Returns:

95

int, number of slots since epoch started

96

"""

97

98

def time_since_epoch_start(self) -> Optional[int]:

99

"""

100

Calculate time elapsed in current epoch.

101

102

Returns:

103

Optional[int], seconds since epoch started (None if no epoch start timestamp)

104

"""

105

```

106

107

### Network Timing Constants

108

109

Fundamental timing parameters that define network behavior and performance characteristics.

110

111

```python { .api }

112

# Default timing configuration for mainnet

113

DEFAULT_DEV_SLOTS_PER_EPOCH: Final[int] = 8192 # Development/testnet epoch length

114

DEFAULT_SLOTS_PER_EPOCH: Final[int] = 432000 # Production epoch length (~2 days)

115

DEFAULT_MS_PER_SLOT: Final[int] = 400 # Target slot duration (400ms)

116

DEFAULT_S_PER_SLOT: Final[float] = 0.4 # Target slot duration (0.4s)

117

DEFAULT_TICKS_PER_SLOT: Final[int] = 64 # Ticks per slot

118

DEFAULT_TICKS_PER_SECOND: Final[int] = 160 # Target tick rate

119

DEFAULT_HASHES_PER_SECOND: Final[int] = 1000000 # Hash rate target

120

DEFAULT_HASHES_PER_TICK: Final[int] = 6250 # Hashes per tick

121

122

# Epoch and slot configuration

123

GENESIS_EPOCH: Final[int] = 0 # First epoch number

124

INITIAL_RENT_EPOCH: Final[int] = 0 # Initial rent collection epoch

125

126

# Transaction timing limits

127

MAX_HASH_AGE_IN_SECONDS: Final[int] = 120 # Maximum blockhash age (2 minutes)

128

MAX_PROCESSING_AGE: Final[int] = 150 # Maximum transaction processing age

129

MAX_RECENT_BLOCKHASHES: Final[int] = 300 # Maximum tracked recent blockhashes

130

131

# Leader scheduling

132

NUM_CONSECUTIVE_LEADER_SLOTS: Final[int] = 4 # Consecutive slots per leader

133

FORWARD_TRANSACTIONS_TO_LEADER_AT_SLOT_OFFSET: Final[int] = 2 # Transaction forwarding offset

134

HOLD_TRANSACTIONS_SLOT_OFFSET: Final[int] = 20 # Transaction hold duration

135

136

# GPU-specific timing

137

MAX_TRANSACTION_FORWARDING_DELAY: Final[int] = 6 # Max forwarding delay (slots)

138

MAX_TRANSACTION_FORWARDING_DELAY_GPU: Final[int] = 2 # Max GPU forwarding delay

139

140

# Time constants

141

MS_PER_TICK: Final[float] = 6.25 # Milliseconds per tick

142

SECONDS_PER_DAY: Final[int] = 86400 # Seconds per day

143

TICKS_PER_DAY: Final[int] = 13824000 # Ticks per day (86400 / 0.0625 * 1000)

144

```

145

146

### Rent Configuration

147

148

Account rent parameters and exemption thresholds for storage cost calculation.

149

150

```python { .api }

151

class Rent:

152

"""

153

Rent calculation configuration and exemption parameters.

154

"""

155

def __init__(

156

self,

157

lamports_per_byte_year: int,

158

exemption_threshold: float,

159

burn_percent: int

160

):

161

"""

162

Create rent configuration.

163

164

Parameters:

165

- lamports_per_byte_year: int, cost per byte per year in lamports

166

- exemption_threshold: float, years worth of rent for exemption

167

- burn_percent: int, percentage of collected rent to burn

168

"""

169

170

@classmethod

171

def default() -> 'Rent':

172

"""

173

Create default rent configuration.

174

175

Returns:

176

Rent with mainnet default parameters

177

"""

178

179

@classmethod

180

def deserialize(cls, data: bytes) -> 'Rent':

181

"""

182

Deserialize rent from sysvar account data.

183

184

Parameters:

185

- data: bytes, rent sysvar account data

186

187

Returns:

188

Rent object

189

"""

190

191

def serialize(self) -> bytes:

192

"""

193

Serialize rent to bytes.

194

195

Returns:

196

bytes, serialized rent data

197

"""

198

199

@property

200

def lamports_per_byte_year(self) -> int:

201

"""Cost per byte per year in lamports."""

202

203

@property

204

def exemption_threshold(self) -> float:

205

"""Years worth of rent required for exemption."""

206

207

@property

208

def burn_percent(self) -> int:

209

"""Percentage of collected rent to burn (0-100)."""

210

211

def minimum_balance(self, data_len: int) -> int:

212

"""

213

Calculate minimum lamports for rent exemption.

214

215

Parameters:

216

- data_len: int, account data size in bytes

217

218

Returns:

219

int, minimum lamports needed for rent exemption

220

"""

221

222

def due(self, lamports: int, data_len: int, years_elapsed: float) -> int:

223

"""

224

Calculate rent due for account.

225

226

Parameters:

227

- lamports: int, current account balance

228

- data_len: int, account data size

229

- years_elapsed: float, time elapsed since last rent payment

230

231

Returns:

232

int, rent due in lamports (0 if rent exempt)

233

"""

234

235

def is_exempt(self, lamports: int, data_len: int) -> bool:

236

"""

237

Check if account is rent exempt.

238

239

Parameters:

240

- lamports: int, account balance

241

- data_len: int, account data size

242

243

Returns:

244

bool, True if account is rent exempt

245

"""

246

247

# Rent configuration constants

248

ACCOUNT_STORAGE_OVERHEAD: Final[int] = 128 # Additional bytes per account

249

DEFAULT_LAMPORTS_PER_BYTE_YEAR: Final[int] = 3480 # Default storage cost

250

DEFAULT_EXEMPTION_THRESHOLD: Final[float] = 2.0 # Default exemption threshold (2 years)

251

DEFAULT_BURN_PERCENT: Final[int] = 50 # Default burn percentage

252

```

253

254

### Epoch Information and Scheduling

255

256

Epoch timing, slot allocation, and validator scheduling parameters.

257

258

```python { .api }

259

class EpochInfo:

260

"""

261

Current epoch information including progress and timing.

262

"""

263

def __init__(

264

self,

265

epoch: int,

266

slot_index: int,

267

slots_in_epoch: int,

268

absolute_slot: int,

269

block_height: int,

270

transaction_count: Optional[int]

271

):

272

"""

273

Create epoch information.

274

275

Parameters:

276

- epoch: int, current epoch number

277

- slot_index: int, slot index within current epoch

278

- slots_in_epoch: int, total slots in current epoch

279

- absolute_slot: int, absolute slot number since genesis

280

- block_height: int, current block height

281

- transaction_count: Optional[int], total transaction count

282

"""

283

284

@property

285

def epoch(self) -> int:

286

"""Current epoch number."""

287

288

@property

289

def slot_index(self) -> int:

290

"""Slot index within current epoch."""

291

292

@property

293

def slots_in_epoch(self) -> int:

294

"""Total slots in current epoch."""

295

296

@property

297

def absolute_slot(self) -> int:

298

"""Absolute slot number since genesis."""

299

300

@property

301

def block_height(self) -> int:

302

"""Current block height."""

303

304

@property

305

def transaction_count(self) -> Optional[int]:

306

"""Total transaction count (if available)."""

307

308

def progress(self) -> float:

309

"""

310

Calculate epoch completion percentage.

311

312

Returns:

313

float, completion percentage (0.0 to 1.0)

314

"""

315

316

def slots_remaining(self) -> int:

317

"""

318

Calculate slots remaining in epoch.

319

320

Returns:

321

int, number of slots until epoch end

322

"""

323

324

class EpochSchedule:

325

"""

326

Epoch scheduling configuration and timing parameters.

327

"""

328

def __init__(

329

self,

330

slots_per_epoch: int,

331

leader_schedule_slot_offset: int,

332

warmup: bool,

333

first_normal_epoch: int,

334

first_normal_slot: int

335

):

336

"""

337

Create epoch schedule configuration.

338

339

Parameters:

340

- slots_per_epoch: int, slots per epoch after warmup

341

- leader_schedule_slot_offset: int, offset for leader schedule calculation

342

- warmup: bool, whether network is in warmup period

343

- first_normal_epoch: int, first epoch with normal slot count

344

- first_normal_slot: int, first slot of first normal epoch

345

"""

346

347

@classmethod

348

def default() -> 'EpochSchedule':

349

"""

350

Create default epoch schedule.

351

352

Returns:

353

EpochSchedule with mainnet parameters

354

"""

355

356

@classmethod

357

def deserialize(cls, data: bytes) -> 'EpochSchedule':

358

"""

359

Deserialize epoch schedule from sysvar account data.

360

361

Parameters:

362

- data: bytes, epoch schedule sysvar data

363

364

Returns:

365

EpochSchedule object

366

"""

367

368

def serialize(self) -> bytes:

369

"""

370

Serialize epoch schedule to bytes.

371

372

Returns:

373

bytes, serialized schedule data

374

"""

375

376

@property

377

def slots_per_epoch(self) -> int:

378

"""Slots per epoch after warmup."""

379

380

@property

381

def leader_schedule_slot_offset(self) -> int:

382

"""Offset for leader schedule calculation."""

383

384

@property

385

def warmup(self) -> bool:

386

"""Whether network is in warmup period."""

387

388

@property

389

def first_normal_epoch(self) -> int:

390

"""First epoch with normal slot count."""

391

392

@property

393

def first_normal_slot(self) -> int:

394

"""First slot of first normal epoch."""

395

396

def get_epoch(self, slot: int) -> int:

397

"""

398

Calculate epoch number for given slot.

399

400

Parameters:

401

- slot: int, slot number

402

403

Returns:

404

int, epoch containing the slot

405

"""

406

407

def get_epoch_and_slot_index(self, slot: int) -> tuple[int, int]:

408

"""

409

Calculate epoch and slot index for given slot.

410

411

Parameters:

412

- slot: int, slot number

413

414

Returns:

415

tuple[int, int], (epoch, slot_index_in_epoch)

416

"""

417

418

def get_first_slot_in_epoch(self, epoch: int) -> int:

419

"""

420

Calculate first slot of given epoch.

421

422

Parameters:

423

- epoch: int, epoch number

424

425

Returns:

426

int, first slot in epoch

427

"""

428

429

def get_last_slot_in_epoch(self, epoch: int) -> int:

430

"""

431

Calculate last slot of given epoch.

432

433

Parameters:

434

- epoch: int, epoch number

435

436

Returns:

437

int, last slot in epoch

438

"""

439

440

def get_slots_in_epoch(self, epoch: int) -> int:

441

"""

442

Calculate number of slots in given epoch.

443

444

Parameters:

445

- epoch: int, epoch number

446

447

Returns:

448

int, slots in epoch

449

"""

450

```

451

452

### Stake and Validator Information

453

454

Historical stake information and validator performance tracking.

455

456

```python { .api }

457

class StakeHistory:

458

"""

459

Historical stake activation information across epochs.

460

"""

461

def __init__(self, entries: List['StakeHistoryEntry']):

462

"""

463

Create stake history with epoch entries.

464

465

Parameters:

466

- entries: List[StakeHistoryEntry], historical stake data

467

"""

468

469

@classmethod

470

def deserialize(cls, data: bytes) -> 'StakeHistory':

471

"""

472

Deserialize stake history from sysvar account data.

473

474

Parameters:

475

- data: bytes, stake history sysvar data

476

477

Returns:

478

StakeHistory object

479

"""

480

481

def serialize(self) -> bytes:

482

"""

483

Serialize stake history to bytes.

484

485

Returns:

486

bytes, serialized stake history

487

"""

488

489

@property

490

def entries(self) -> List['StakeHistoryEntry']:

491

"""Historical stake entries by epoch."""

492

493

def get_stake_history_entry(self, epoch: int) -> Optional['StakeHistoryEntry']:

494

"""

495

Get stake information for specific epoch.

496

497

Parameters:

498

- epoch: int, epoch number to query

499

500

Returns:

501

Optional[StakeHistoryEntry], stake info for epoch (None if not found)

502

"""

503

504

class StakeHistoryEntry:

505

"""

506

Stake information for a single epoch.

507

"""

508

def __init__(self, effective: int, activating: int, deactivating: int):

509

"""

510

Create stake history entry.

511

512

Parameters:

513

- effective: int, effective stake amount in lamports

514

- activating: int, stake being activated in lamports

515

- deactivating: int, stake being deactivated in lamports

516

"""

517

518

@property

519

def effective(self) -> int:

520

"""Effective stake amount in lamports."""

521

522

@property

523

def activating(self) -> int:

524

"""Stake being activated in lamports."""

525

526

@property

527

def deactivating(self) -> int:

528

"""Stake being deactivated in lamports."""

529

530

def total_stake(self) -> int:

531

"""

532

Calculate total stake (effective + activating).

533

534

Returns:

535

int, total stake amount

536

"""

537

538

class SlotHistory:

539

"""

540

Historical slot information and confirmation bitmap.

541

"""

542

def __init__(self, bits: bytes, next_slot: int):

543

"""

544

Create slot history with confirmation bitmap.

545

546

Parameters:

547

- bits: bytes, bitmap of confirmed slots

548

- next_slot: int, next slot to be recorded

549

"""

550

551

@classmethod

552

def deserialize(cls, data: bytes) -> 'SlotHistory':

553

"""

554

Deserialize slot history from sysvar account data.

555

556

Returns:

557

SlotHistory object

558

"""

559

560

def serialize(self) -> bytes:

561

"""Serialize slot history to bytes."""

562

563

@property

564

def bits(self) -> bytes:

565

"""Bitmap of confirmed slots."""

566

567

@property

568

def next_slot(self) -> int:

569

"""Next slot to be recorded."""

570

571

def check_slot(self, slot: int) -> 'SlotHistoryCheck':

572

"""

573

Check if slot is in history and confirmed.

574

575

Parameters:

576

- slot: int, slot number to check

577

578

Returns:

579

SlotHistoryCheck, validation result

580

"""

581

582

class SlotHistoryCheck:

583

"""Result of slot history validation."""

584

Found: 'SlotHistoryCheck' # Slot found and confirmed

585

NotFound: 'SlotHistoryCheck' # Slot not in history

586

TooOld: 'SlotHistoryCheck' # Slot too old (outside history window)

587

TooNew: 'SlotHistoryCheck' # Slot too new (future slot)

588

```

589

590

### Reward Information

591

592

Epoch reward distribution and inflation parameters.

593

594

```python { .api }

595

class EpochRewards:

596

"""

597

Epoch reward distribution information.

598

"""

599

def __init__(

600

self,

601

distribution_starting_block_height: int,

602

num_partitions: int,

603

parent_blockhash: Hash,

604

total_reward: int,

605

distributed_rewards: int,

606

active: bool

607

):

608

"""

609

Create epoch rewards information.

610

611

Parameters:

612

- distribution_starting_block_height: int, block height when distribution started

613

- num_partitions: int, number of reward distribution partitions

614

- parent_blockhash: Hash, parent blockhash for reward calculation

615

- total_reward: int, total rewards for epoch in lamports

616

- distributed_rewards: int, rewards distributed so far in lamports

617

- active: bool, whether reward distribution is active

618

"""

619

620

@property

621

def distribution_starting_block_height(self) -> int:

622

"""Block height when distribution started."""

623

624

@property

625

def num_partitions(self) -> int:

626

"""Number of reward distribution partitions."""

627

628

@property

629

def parent_blockhash(self) -> Hash:

630

"""Parent blockhash for reward calculation."""

631

632

@property

633

def total_reward(self) -> int:

634

"""Total rewards for epoch in lamports."""

635

636

@property

637

def distributed_rewards(self) -> int:

638

"""Rewards distributed so far in lamports."""

639

640

@property

641

def active(self) -> bool:

642

"""Whether reward distribution is active."""

643

644

def remaining_rewards(self) -> int:

645

"""

646

Calculate remaining rewards to distribute.

647

648

Returns:

649

int, undistributed rewards in lamports

650

"""

651

652

def distribution_progress(self) -> float:

653

"""

654

Calculate reward distribution progress.

655

656

Returns:

657

float, distribution completion (0.0 to 1.0)

658

"""

659

```

660

661

## Usage Examples

662

663

### Reading System Variables

664

665

```python

666

from solders.clock import Clock

667

from solders.rent import Rent

668

from solders.epoch_schedule import EpochSchedule

669

from solders.sysvar import CLOCK, RENT, EPOCH_SCHEDULE

670

from solders.rpc.requests import GetAccountInfo

671

672

# Read clock sysvar

673

clock_request = GetAccountInfo(CLOCK)

674

# After RPC call, deserialize the account data:

675

# clock = Clock.deserialize(account.data)

676

677

# Read rent sysvar

678

rent_request = GetAccountInfo(RENT)

679

# rent = Rent.deserialize(account.data)

680

681

# Read epoch schedule

682

schedule_request = GetAccountInfo(EPOCH_SCHEDULE)

683

# epoch_schedule = EpochSchedule.deserialize(account.data)

684

```

685

686

### Working with Clock Information

687

688

```python

689

# Assuming clock data was retrieved from RPC

690

clock_data = bytes(40) # Clock sysvar data from RPC response

691

clock = Clock.deserialize(clock_data)

692

693

print(f"Current slot: {clock.slot}")

694

print(f"Current epoch: {clock.epoch}")

695

print(f"Unix timestamp: {clock.unix_timestamp}")

696

697

# Calculate elapsed time in epoch

698

slots_elapsed = clock.slots_since_epoch_start()

699

print(f"Slots since epoch start: {slots_elapsed}")

700

701

# Estimate time since epoch start

702

if clock.epoch_start_timestamp:

703

time_elapsed = clock.time_since_epoch_start()

704

print(f"Seconds since epoch start: {time_elapsed}")

705

706

# Calculate slot timing

707

slot_duration_ms = DEFAULT_MS_PER_SLOT

708

estimated_next_slot_time = clock.unix_timestamp + (slot_duration_ms / 1000)

709

print(f"Estimated next slot at: {estimated_next_slot_time}")

710

```

711

712

### Rent Calculations

713

714

```python

715

# Example rent calculations

716

rent = Rent.default()

717

718

# Calculate rent exemption for different account types

719

token_account_size = 165

720

minimum_for_token = rent.minimum_balance(token_account_size)

721

print(f"Minimum for token account: {minimum_for_token} lamports ({minimum_for_token / 1e9:.9f} SOL)")

722

723

mint_account_size = 82

724

minimum_for_mint = rent.minimum_balance(mint_account_size)

725

print(f"Minimum for mint account: {minimum_for_mint} lamports ({minimum_for_mint / 1e9:.9f} SOL)")

726

727

# Check if account is rent exempt

728

account_balance = 2500000 # 0.0025 SOL

729

account_size = 100

730

731

if rent.is_exempt(account_balance, account_size):

732

print("Account is rent exempt")

733

else:

734

needed = rent.minimum_balance(account_size) - account_balance

735

print(f"Need {needed} more lamports for rent exemption")

736

737

# Calculate rent due (for non-exempt accounts)

738

years_elapsed = 0.1 # ~36 days

739

rent_due = rent.due(account_balance, account_size, years_elapsed)

740

print(f"Rent due: {rent_due} lamports")

741

```

742

743

### Epoch Information and Scheduling

744

745

```python

746

# Working with epoch schedule

747

epoch_schedule = EpochSchedule.default()

748

749

current_slot = 100000000

750

current_epoch = epoch_schedule.get_epoch(current_slot)

751

epoch_info = epoch_schedule.get_epoch_and_slot_index(current_slot)

752

753

print(f"Slot {current_slot} is in epoch {current_epoch}")

754

print(f"Epoch: {epoch_info[0]}, Slot index: {epoch_info[1]}")

755

756

# Calculate epoch boundaries

757

first_slot = epoch_schedule.get_first_slot_in_epoch(current_epoch)

758

last_slot = epoch_schedule.get_last_slot_in_epoch(current_epoch)

759

slots_in_epoch = epoch_schedule.get_slots_in_epoch(current_epoch)

760

761

print(f"Epoch {current_epoch}: slots {first_slot} to {last_slot} ({slots_in_epoch} total)")

762

763

# Calculate progress through epoch

764

slot_index = current_slot - first_slot

765

progress = slot_index / slots_in_epoch

766

print(f"Epoch progress: {progress:.2%}")

767

768

# Estimate time remaining in epoch

769

slots_remaining = last_slot - current_slot

770

time_remaining_ms = slots_remaining * DEFAULT_MS_PER_SLOT

771

hours_remaining = (time_remaining_ms / 1000) / 3600

772

print(f"Estimated time remaining in epoch: {hours_remaining:.1f} hours")

773

```

774

775

### Validator and Stake Information

776

777

```python

778

# Working with stake history (example)

779

# stake_history = StakeHistory.deserialize(stake_history_sysvar_data)

780

781

def analyze_stake_trend(stake_history: StakeHistory, epochs_back: int = 10):

782

"""Analyze stake trend over recent epochs."""

783

current_epoch = 500 # Would get from clock or epoch info

784

785

stake_values = []

786

for i in range(epochs_back):

787

epoch = current_epoch - i

788

entry = stake_history.get_stake_history_entry(epoch)

789

if entry:

790

total_stake = entry.total_stake()

791

stake_values.append((epoch, total_stake))

792

793

if len(stake_values) >= 2:

794

recent = stake_values[0][1]

795

older = stake_values[-1][1]

796

change = ((recent - older) / older) * 100

797

print(f"Stake change over {epochs_back} epochs: {change:+.2f}%")

798

799

return stake_values

800

801

# Check slot confirmation

802

# slot_history = SlotHistory.deserialize(slot_history_sysvar_data)

803

def check_slot_confirmation(slot_history: SlotHistory, slot: int):

804

"""Check if a slot was confirmed."""

805

result = slot_history.check_slot(slot)

806

807

if result == SlotHistoryCheck.Found:

808

print(f"Slot {slot} was confirmed")

809

elif result == SlotHistoryCheck.NotFound:

810

print(f"Slot {slot} was not confirmed")

811

elif result == SlotHistoryCheck.TooOld:

812

print(f"Slot {slot} is too old (outside history window)")

813

elif result == SlotHistoryCheck.TooNew:

814

print(f"Slot {slot} is too new (future slot)")

815

```

816

817

### Network Timing Calculations

818

819

```python

820

# Calculate network timing metrics

821

def calculate_network_metrics(current_slot: int, target_slot: int):

822

"""Calculate timing for reaching target slot."""

823

slots_to_wait = target_slot - current_slot

824

825

if slots_to_wait <= 0:

826

print("Target slot already passed")

827

return

828

829

# Time estimates

830

ms_to_wait = slots_to_wait * DEFAULT_MS_PER_SLOT

831

seconds_to_wait = ms_to_wait / 1000

832

minutes_to_wait = seconds_to_wait / 60

833

834

print(f"Slots to wait: {slots_to_wait}")

835

print(f"Estimated time: {minutes_to_wait:.1f} minutes")

836

837

# Account for network variability

838

min_time = seconds_to_wait * 0.8 # Slots can be faster

839

max_time = seconds_to_wait * 1.2 # Slots can be slower

840

841

print(f"Time range: {min_time/60:.1f} - {max_time/60:.1f} minutes")

842

843

# Transaction timing validation

844

def validate_transaction_timing(blockhash_age_slots: int) -> bool:

845

"""Validate if blockhash is still valid for transactions."""

846

max_age_slots = MAX_HASH_AGE_IN_SECONDS / DEFAULT_S_PER_SLOT

847

848

if blockhash_age_slots > max_age_slots:

849

print(f"Blockhash too old: {blockhash_age_slots} slots (max {max_age_slots})")

850

return False

851

852

slots_remaining = max_age_slots - blockhash_age_slots

853

time_remaining = slots_remaining * DEFAULT_S_PER_SLOT

854

855

print(f"Blockhash valid for {slots_remaining:.0f} more slots ({time_remaining:.0f}s)")

856

return True

857

858

# Usage

859

current_slot = 100000000

860

target_slot = 100000100

861

calculate_network_metrics(current_slot, target_slot)

862

863

# Check blockhash validity

864

blockhash_slot = 99999900 # Slot when blockhash was created

865

age_in_slots = current_slot - blockhash_slot

866

is_valid = validate_transaction_timing(age_in_slots)

867

```

868

869

### Epoch Reward Tracking

870

871

```python

872

# Working with epoch rewards (example)

873

def track_reward_distribution(epoch_rewards: EpochRewards):

874

"""Track epoch reward distribution progress."""

875

print(f"Total rewards: {epoch_rewards.total_reward / 1e9:.6f} SOL")

876

print(f"Distributed: {epoch_rewards.distributed_rewards / 1e9:.6f} SOL")

877

878

remaining = epoch_rewards.remaining_rewards()

879

print(f"Remaining: {remaining / 1e9:.6f} SOL")

880

881

progress = epoch_rewards.distribution_progress()

882

print(f"Distribution progress: {progress:.1%}")

883

884

if epoch_rewards.active:

885

print("Distribution is currently active")

886

887

# Estimate completion time based on distribution rate

888

if progress > 0:

889

# This would require historical data to calculate rate

890

print("Estimating completion time...")

891

else:

892

print("Distribution completed or not started")

893

```

894

895

## Constants and Network Parameters

896

897

### Network Identifiers

898

899

```python { .api }

900

# Network-specific parameters (examples for different networks)

901

class NetworkParams:

902

# Mainnet parameters

903

MAINNET_GENESIS_HASH = "5eykt4UsFv8P8NJdTREpY1vzqKqZKvdpKuc147dw2N9d"

904

905

# Devnet parameters

906

DEVNET_SLOTS_PER_EPOCH = DEFAULT_DEV_SLOTS_PER_EPOCH

907

908

# Testnet parameters

909

TESTNET_SLOTS_PER_EPOCH = DEFAULT_SLOTS_PER_EPOCH

910

```

911

912

### Performance Benchmarks

913

914

```python { .api }

915

# Network performance targets

916

TARGET_TRANSACTIONS_PER_SECOND = 65000 # Peak TPS target

917

TARGET_CONFIRMATION_TIME_MS = 400 # Target confirmation time

918

TARGET_FINALIZATION_TIME_MS = 12800 # Target finalization time (32 slots)

919

920

# Practical limits

921

MAX_TRANSACTIONS_PER_BLOCK = 512 # Current block limit

922

AVERAGE_TRANSACTION_SIZE = 200 # Average transaction size in bytes

923

```