gmsol_solana_utils/utils/
transaction_size.rs1use std::{borrow::Borrow, collections::HashSet};
2
3use solana_sdk::{instruction::Instruction, pubkey::Pubkey};
4
5pub fn transaction_size<T: Borrow<Instruction>>(
10 ixs: &[T],
11 is_versioned_transaction: bool,
12 lookup_table: Option<&HashSet<Pubkey>>,
13 lookup_table_addresses: usize,
14) -> usize {
15 use std::collections::HashSet;
16
17 fn get_size_of_compressed_u16(size: usize) -> usize {
18 match size {
19 0..=127 => 1,
20 128..=16383 => 2,
21 _ => 3,
22 }
23 }
24
25 let mut programs = HashSet::<Pubkey>::default();
26 let mut accounts = HashSet::<Pubkey>::default();
27 let mut signers = HashSet::<Pubkey>::default();
28
29 let ixs_size = ixs.iter().fold(0, |size, ix| {
30 let ix = ix.borrow();
31 programs.insert(ix.program_id);
32 accounts.insert(ix.program_id);
33 ix.accounts.iter().for_each(|account| {
34 accounts.insert(account.pubkey);
35 if account.is_signer {
36 signers.insert(account.pubkey);
37 }
38 });
39 size + 1
40 + get_size_of_compressed_u16(ix.accounts.len())
41 + ix.accounts.len()
42 + get_size_of_compressed_u16(ix.data.len())
43 + ix.data.len()
44 });
45
46 let num_of_address_lookups = if let Some(lookup_table) = lookup_table {
47 let total_accounts = accounts.len();
48 accounts = accounts.difference(lookup_table).copied().collect();
49 accounts = accounts
50 .union(&signers)
51 .chain(programs.iter())
52 .copied()
53 .collect();
54 total_accounts - accounts.len()
55 } else {
56 0
57 };
58
59 let size = get_size_of_compressed_u16(signers.len())
60 + signers.len() * 64
61 + 3
62 + get_size_of_compressed_u16(accounts.len())
63 + accounts.len() * 32
64 + 32
65 + get_size_of_compressed_u16(ixs.len())
66 + ixs_size
67 + num_of_address_lookups;
68 if is_versioned_transaction {
69 size + 1 + get_size_of_compressed_u16(0) + lookup_table_addresses * (32 + 2)
70 } else {
71 size
72 }
73}