light_client/
fee.rs

1use solana_keypair::Keypair;
2use solana_pubkey::Pubkey;
3
4use crate::rpc::{Rpc, RpcError};
5
6#[derive(Debug, Clone, PartialEq)]
7pub struct FeeConfig {
8    pub state_merkle_tree_rollover: u64,
9    pub address_queue_rollover: u64,
10    // TODO: refactor to allow multiple state and address tree configs
11    // pub state_tree_configs: Vec<StateMerkleTreeConfig>,
12    // pub address_tree_configs: Vec<AddressMerkleTreeConfig>,
13    pub network_fee: u64,
14    pub address_network_fee: u64,
15    pub solana_network_fee: i64,
16}
17
18impl Default for FeeConfig {
19    fn default() -> Self {
20        Self {
21            // rollover fee plus additional lamports for the cpi account
22            state_merkle_tree_rollover: 300,
23            address_queue_rollover: 392,
24            // TODO: refactor to allow multiple state and address tree configs
25            // state_tree_configs: vec![StateMerkleTreeConfig::default()],
26            // address_tree_configs: vec![AddressMerkleTreeConfig::default()],
27            network_fee: 5000,
28            address_network_fee: 5000,
29            solana_network_fee: 5000,
30        }
31    }
32}
33
34impl FeeConfig {
35    pub fn test_batched() -> Self {
36        Self {
37            // rollover fee plus additional lamports for the cpi account
38            state_merkle_tree_rollover: 1,
39            address_queue_rollover: 392, // not batched
40            network_fee: 5000,
41            address_network_fee: 10000,
42            solana_network_fee: 5000,
43        }
44    }
45}
46
47#[derive(Debug, Clone, PartialEq)]
48pub struct TransactionParams {
49    pub v1_input_compressed_accounts: u8,
50    pub v2_input_compressed_accounts: bool,
51    pub num_output_compressed_accounts: u8,
52    pub num_new_addresses: u8,
53    pub compress: i64,
54    pub fee_config: FeeConfig,
55}
56
57pub async fn assert_transaction_params(
58    rpc: &mut impl Rpc,
59    payer: &Pubkey,
60    signers: &[&Keypair],
61    pre_balance: u64,
62    params: Option<TransactionParams>,
63) -> Result<(), RpcError> {
64    if let Some(transaction_params) = params {
65        let mut deduped_signers = signers.to_vec();
66        deduped_signers.dedup();
67        let post_balance = rpc.get_account(*payer).await?.unwrap().lamports;
68
69        // Network fee is charged per input and per address
70        let mut network_fee: i64 = 0;
71
72        // Charge per input compressed account
73        if transaction_params.v1_input_compressed_accounts != 0 {
74            network_fee += transaction_params.fee_config.network_fee as i64
75                * transaction_params.v1_input_compressed_accounts as i64;
76        } else if transaction_params.v2_input_compressed_accounts {
77            network_fee += transaction_params.fee_config.network_fee as i64;
78        }
79        // Charge per address created
80        if transaction_params.num_new_addresses != 0 {
81            network_fee += transaction_params.fee_config.address_network_fee as i64
82                * transaction_params.num_new_addresses as i64;
83        }
84        let expected_post_balance = pre_balance as i64
85            - i64::from(transaction_params.num_new_addresses)
86                * transaction_params.fee_config.address_queue_rollover as i64
87            - i64::from(transaction_params.num_output_compressed_accounts)
88                * transaction_params.fee_config.state_merkle_tree_rollover as i64
89            - transaction_params.compress
90            - transaction_params.fee_config.solana_network_fee * deduped_signers.len() as i64
91            - network_fee;
92
93        if post_balance as i64 != expected_post_balance {
94            println!("transaction_params: {:?}", transaction_params);
95            println!("pre_balance: {}", pre_balance);
96            println!("post_balance: {}", post_balance);
97            println!("expected post_balance: {}", expected_post_balance);
98            println!(
99                "diff post_balance: {}",
100                post_balance as i64 - expected_post_balance
101            );
102            println!(
103                "rollover fee: {}",
104                transaction_params.fee_config.state_merkle_tree_rollover
105            );
106            println!(
107                "address_network_fee: {}",
108                transaction_params.fee_config.address_network_fee
109            );
110            println!("network_fee: {}", network_fee);
111            println!("num signers {}", deduped_signers.len());
112            println!(
113                "transaction_params.fee_config {:?}",
114                transaction_params.fee_config
115            );
116            return Err(RpcError::CustomError("Transaction fee error.".to_string()));
117        }
118    }
119    Ok(())
120}