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

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