1-
21use std:: fmt:: Debug ;
32
43use clap:: { command, Parser } ;
5- use stellar_xdr:: curr:: { LedgerKey , LedgerKeyAccount , MuxedAccount } ;
4+ use stellar_xdr:: curr:: { ContractDataDurability , Hash , LedgerKey , LedgerKeyAccount , LedgerKeyContractData , Limits , MuxedAccount , ReadXdr , ScAddress , ScVal } ;
65use crate :: commands:: config:: network;
7- use crate :: config;
6+ use crate :: { config, xdr } ;
87use crate :: config:: { locator} ;
98use crate :: {
109 rpc:: { self } ,
1110} ;
12- use crate :: commands:: ledger:: entry:: get:: Error :: EmptyKeys ;
11+ use crate :: commands:: contract:: Durability ;
12+ use crate :: commands:: ledger:: entry:: get:: Error :: { ContractRequired , EmptyKeys } ;
1313
1414#[ derive( Parser , Debug , Clone ) ]
1515#[ group( skip) ]
@@ -28,6 +28,21 @@ pub struct Cmd {
2828 #[ arg( long) ]
2929 pub hd_path : Option < usize > ,
3030
31+
32+ #[ arg( long = "id" , env = "STELLAR_CONTRACT_ID" ) ]
33+ pub contract_id : Option < config:: UnresolvedContract > ,
34+
35+ /// Storage entry durability
36+ #[ arg( long, value_enum, default_value = "persistent" ) ]
37+ pub durability : Durability ,
38+
39+ /// Storage key (symbols only)
40+ #[ arg( long = "key" ) ]
41+ pub key : Option < Vec < String > > ,
42+ /// Storage key (base64-encoded XDR)
43+ #[ arg( long = "key-xdr" ) ]
44+ pub key_xdr : Option < Vec < String > > ,
45+
3146 /// Format of the output
3247 #[ arg( long, default_value = "original" ) ]
3348 pub output : OutputFormat ,
@@ -45,8 +60,14 @@ pub enum Error {
4560 Network ( #[ from] network:: Error ) ,
4661 #[ error( transparent) ]
4762 Serde ( #[ from] serde_json:: Error ) ,
63+ #[ error( transparent) ]
64+ StellarXdr ( #[ from] stellar_xdr:: curr:: Error ) ,
65+ #[ error( transparent) ]
66+ Spec ( #[ from] soroban_spec_tools:: Error ) ,
4867 #[ error( "at least one key must be provided" ) ]
4968 EmptyKeys ,
69+ #[ error( "contract id is required but was not provided" ) ]
70+ ContractRequired ,
5071}
5172
5273#[ derive( Clone , Copy , Debug , Eq , Hash , PartialEq , clap:: ValueEnum , Default ) ]
@@ -63,15 +84,52 @@ pub enum OutputFormat {
6384
6485impl Cmd {
6586 pub async fn run ( & self ) -> Result < ( ) , Error > {
66- let client = self . network . get ( & self . locator ) ?. rpc_client ( ) ?;
87+ let network = self . network . get ( & self . locator ) ?;
88+ let client = network. rpc_client ( ) ?;
6789 let mut ledger_keys = vec ! [ ] ;
6890
91+ if let Some ( contract_id) = & self . contract_id {
92+ let contract_id = contract_id. resolve_contract_id ( & self . locator , & network. network_passphrase ) ?;
93+
94+ let contract_address_arg = ScAddress :: Contract ( Hash ( contract_id. 0 ) ) ;
95+
96+ if let Some ( keys) = & self . key {
97+ for key in keys {
98+ let key = LedgerKey :: ContractData ( LedgerKeyContractData {
99+ contract : contract_address_arg. clone ( ) ,
100+ key : soroban_spec_tools:: from_string_primitive (
101+ key,
102+ & xdr:: ScSpecTypeDef :: Symbol ,
103+ ) ?,
104+ durability : ContractDataDurability :: Persistent ,
105+ } ) ;
106+
107+ ledger_keys. push ( key) ;
108+ }
109+ }
110+
111+ if let Some ( keys) = & self . key_xdr {
112+ for key in keys {
113+ let key = LedgerKey :: ContractData ( LedgerKeyContractData {
114+ contract : contract_address_arg. clone ( ) ,
115+ key : ScVal :: from_xdr_base64 ( key, Limits :: none ( ) ) ?,
116+ durability : ContractDataDurability :: Persistent ,
117+ } ) ;
118+
119+ ledger_keys. push ( key) ;
120+ }
121+ }
122+ } else if self . key . is_some ( ) || self . key_xdr . is_some ( ) {
123+ return Err ( ContractRequired )
124+ }
125+
69126 if let Some ( acc) = & self . account {
70127 let acc = self . muxed_account ( acc) ?;
71128 let key = LedgerKey :: Account ( LedgerKeyAccount { account_id : acc. account_id ( ) } ) ;
72129 ledger_keys. push ( key) ;
73130 }
74131
132+
75133 if ledger_keys. is_empty ( ) {
76134 return Err ( EmptyKeys ) ;
77135 }
0 commit comments