soroban_cli/
fee.rs

1use std::io::stderr;
2
3use soroban_rpc::GetTransactionResponse;
4
5use crate::assembled::Assembled;
6use crate::commands::tx::fetch;
7use crate::commands::tx::fetch::fee::FeeTable;
8use crate::commands::HEADING_RPC;
9use crate::xdr;
10
11#[derive(Debug, clap::Args, Clone)]
12#[group(skip)]
13pub struct Args {
14    /// fee amount for transaction, in stroops. 1 stroop = 0.0000001 xlm
15    #[arg(long, default_value = "100", env = "STELLAR_FEE", help_heading = HEADING_RPC)]
16    pub fee: u32,
17    /// Output the cost execution to stderr
18    #[arg(long = "cost", help_heading = HEADING_RPC)]
19    pub cost: bool,
20    /// Number of instructions to simulate
21    #[arg(long, help_heading = HEADING_RPC)]
22    pub instructions: Option<u32>,
23    /// Allow this many extra instructions when budgeting resources during transaction simulation
24    #[arg(long, help_heading = HEADING_RPC)]
25    pub instruction_leeway: Option<u64>,
26    /// Build the transaction and only write the base64 xdr to stdout
27    #[arg(long, help_heading = HEADING_RPC)]
28    pub build_only: bool,
29}
30
31impl Args {
32    pub fn apply_to_assembled_txn(&self, txn: Assembled) -> Assembled {
33        if let Some(instructions) = self.instructions {
34            txn.set_max_instructions(instructions)
35        } else {
36            add_padding_to_instructions(txn)
37        }
38    }
39
40    pub fn resource_config(&self) -> Option<soroban_rpc::ResourceConfig> {
41        self.instruction_leeway
42            .map(|instruction_leeway| soroban_rpc::ResourceConfig { instruction_leeway })
43    }
44
45    pub fn print_cost_info(&self, res: &GetTransactionResponse) -> Result<(), fetch::Error> {
46        if !self.cost {
47            return Ok(());
48        }
49
50        let fee_table = FeeTable::new_from_transaction_response(res)?;
51
52        fee_table.table().print(&mut stderr())?;
53
54        Ok(())
55    }
56}
57
58pub fn add_padding_to_instructions(txn: Assembled) -> Assembled {
59    let xdr::TransactionExt::V1(xdr::SorobanTransactionData {
60        resources: xdr::SorobanResources { instructions, .. },
61        ..
62    }) = txn.transaction().ext
63    else {
64        return txn;
65    };
66    // Start with 150%
67    let instructions = (instructions.checked_mul(150 / 100)).unwrap_or(instructions);
68    txn.set_max_instructions(instructions)
69}
70
71impl Default for Args {
72    fn default() -> Self {
73        Self {
74            fee: 100,
75            cost: false,
76            instructions: None,
77            instruction_leeway: None,
78            build_only: false,
79        }
80    }
81}