Skip to main content

soroban_cli/commands/ledger/entry/fetch/
contract_data.rs

1use super::args::Args;
2use crate::{
3    commands::contract::Durability,
4    config::{self, locator},
5    utils::XDR_DEPTH_LIMIT,
6    xdr::{
7        self, ContractDataDurability, ContractId, Hash, LedgerKey, LedgerKeyContractData, Limits,
8        ReadXdr, ScAddress, ScVal,
9    },
10};
11use clap::Parser;
12
13#[derive(Parser, Debug, Clone)]
14#[group(skip)]
15pub struct Cmd {
16    /// Contract alias or address to fetch
17    #[arg(long)]
18    pub contract: config::UnresolvedContract,
19
20    #[command(flatten)]
21    pub args: Args,
22
23    /// Storage entry durability
24    #[arg(long, value_enum, default_value = "persistent")]
25    pub durability: Durability,
26
27    /// Storage key (symbols only)
28    #[arg(long = "key", required_unless_present_any = vec!("key_xdr", "instance"))]
29    pub key: Option<Vec<String>>,
30
31    /// Storage key (base64-encoded XDR)
32    #[arg(long = "key-xdr", required_unless_present_any = vec!("key", "instance"))]
33    pub key_xdr: Option<Vec<String>>,
34
35    /// If the contract instance ledger entry should be included in the output
36    #[arg(long = "instance", required_unless_present_any = vec!("key", "key_xdr"))]
37    pub instance: bool,
38}
39
40#[derive(thiserror::Error, Debug)]
41pub enum Error {
42    #[error(transparent)]
43    Run(#[from] super::args::Error),
44    #[error(transparent)]
45    Locator(#[from] locator::Error),
46    #[error(transparent)]
47    Spec(#[from] soroban_spec_tools::Error),
48    #[error(transparent)]
49    StellarXdr(#[from] stellar_xdr::Error),
50}
51
52impl Cmd {
53    pub async fn run(&self) -> Result<(), Error> {
54        let mut ledger_keys = vec![];
55        self.insert_keys(&mut ledger_keys)?;
56        Ok(self.args.run(ledger_keys).await?)
57    }
58
59    fn insert_keys(&self, ledger_keys: &mut Vec<LedgerKey>) -> Result<(), Error> {
60        let network = self.args.network()?;
61        let contract_id = self
62            .contract
63            .resolve_contract_id(&self.args.locator, &network.network_passphrase)?;
64        let contract_address_arg = ScAddress::Contract(ContractId(Hash(contract_id.0)));
65        if self.instance {
66            let contract_instance_key = LedgerKey::ContractData(LedgerKeyContractData {
67                contract: contract_address_arg.clone(),
68                key: ScVal::LedgerKeyContractInstance,
69                durability: ContractDataDurability::Persistent,
70            });
71
72            ledger_keys.push(contract_instance_key);
73        }
74
75        if let Some(keys) = &self.key {
76            for key in keys {
77                let key = LedgerKey::ContractData(LedgerKeyContractData {
78                    contract: contract_address_arg.clone(),
79                    key: soroban_spec_tools::from_string_primitive(
80                        key,
81                        &xdr::ScSpecTypeDef::Symbol,
82                    )?,
83                    durability: ContractDataDurability::Persistent,
84                });
85
86                ledger_keys.push(key);
87            }
88        }
89
90        if let Some(keys) = &self.key_xdr {
91            for key in keys {
92                let key = LedgerKey::ContractData(LedgerKeyContractData {
93                    contract: contract_address_arg.clone(),
94                    key: ScVal::from_xdr_base64(key, Limits::depth(XDR_DEPTH_LIMIT))?,
95                    durability: ContractDataDurability::Persistent,
96                });
97
98                ledger_keys.push(key);
99            }
100        }
101
102        Ok(())
103    }
104}