soroban_cli/
fee.rs

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