1+ use std:: array:: TryFromSliceError ;
12use std:: fmt:: Debug ;
23
3- use clap:: { command, Parser } ;
4- use stellar_xdr:: curr:: { ContractDataDurability , Hash , LedgerKey , LedgerKeyAccount , LedgerKeyContractData , Limits , MuxedAccount , ReadXdr , ScAddress , ScVal } ;
54use crate :: commands:: config:: network;
5+ use crate :: commands:: contract:: Durability ;
6+ use crate :: commands:: ledger:: entry:: get:: Error :: {
7+ AccountRequired , ContractRequired , EmptyKeys , InvalidAsset , InvalidConfigId , InvalidDataName ,
8+ InvalidHash ,
9+ } ;
10+ use crate :: config:: locator;
11+ use crate :: rpc:: { self } ;
612use crate :: { config, xdr} ;
7- use crate :: config:: { locator} ;
8- use crate :: {
9- rpc:: { self } ,
13+ use clap:: { command, Parser } ;
14+ use hex:: FromHexError ;
15+ use soroban_spec_tools:: utils:: padded_hex_from_str;
16+ use stellar_strkey:: ed25519:: PublicKey as Ed25519PublicKey ;
17+ use stellar_xdr:: curr:: ClaimableBalanceId :: ClaimableBalanceIdTypeV0 ;
18+ use stellar_xdr:: curr:: {
19+ AccountId , AlphaNum12 , AlphaNum4 , AssetCode12 , AssetCode4 , ConfigSettingId ,
20+ ContractDataDurability , Hash , LedgerKey , LedgerKeyAccount , LedgerKeyClaimableBalance ,
21+ LedgerKeyConfigSetting , LedgerKeyContractCode , LedgerKeyContractData , LedgerKeyData ,
22+ LedgerKeyLiquidityPool , LedgerKeyOffer , LedgerKeyTrustLine , LedgerKeyTtl , Limits , MuxedAccount ,
23+ PoolId , PublicKey , ReadXdr , ScAddress , ScVal , String64 , TrustLineAsset , Uint256 ,
1024} ;
11- use crate :: commands:: contract:: Durability ;
12- use crate :: commands:: ledger:: entry:: get:: Error :: { ContractRequired , EmptyKeys } ;
1325
1426#[ derive( Parser , Debug , Clone ) ]
1527#[ group( skip) ]
1628pub struct Cmd {
1729 #[ command( flatten) ]
1830 pub network : network:: Args ,
19-
2031 #[ command( flatten) ]
2132 pub locator : locator:: Args ,
2233
2334 /// Name of identity to lookup, default is test identity
2435 #[ arg( long) ]
2536 pub account : Option < String > ,
26-
2737 /// If identity is a seed phrase use this hd path, default is 0
2838 #[ arg( long) ]
2939 pub hd_path : Option < usize > ,
3040
41+ /// Assets to get trustline info for
42+ #[ arg( long) ]
43+ pub asset : Option < Vec < String > > ,
44+ /// ID of an offer made on the Stellar DEX
45+ #[ arg( long) ]
46+ pub offer : Option < Vec < i64 > > ,
47+ /// Fetch key-value data entries attached to an account (see manageDataOp)
48+ #[ arg( long) ]
49+ pub data_name : Option < Vec < String > > ,
50+
51+ /// Claimable Balance id
52+ #[ arg( long) ]
53+ pub claimable_id : Option < Vec < String > > ,
3154
55+ /// Liquidity pool id
56+ #[ arg( long) ]
57+ pub pool_id : Option < Vec < String > > ,
58+
59+ /// Defines the currently active network configuration
60+ #[ arg( long) ]
61+ pub config_setting_id : Option < Vec < i32 > > ,
62+
63+ /// Get WASM bytecode by hash
64+ #[ arg( long) ]
65+ pub wasm_hash : Option < Vec < String > > ,
66+
67+ /// Get the time-to-live of an associated contract data or code entry
68+ #[ arg( long) ]
69+ pub ttl : Option < Vec < String > > ,
70+
71+ /// Contract id to fetch an info for
3272 #[ arg( long = "id" , env = "STELLAR_CONTRACT_ID" ) ]
3373 pub contract_id : Option < config:: UnresolvedContract > ,
34-
3574 /// Storage entry durability
3675 #[ arg( long, value_enum, default_value = "persistent" ) ]
3776 pub durability : Durability ,
38-
3977 /// Storage key (symbols only)
4078 #[ arg( long = "key" ) ]
4179 pub key : Option < Vec < String > > ,
@@ -64,10 +102,24 @@ pub enum Error {
64102 StellarXdr ( #[ from] stellar_xdr:: curr:: Error ) ,
65103 #[ error( transparent) ]
66104 Spec ( #[ from] soroban_spec_tools:: Error ) ,
105+ #[ error( transparent) ]
106+ TryFromSliceError ( #[ from] TryFromSliceError ) ,
107+ #[ error( transparent) ]
108+ FromHexError ( #[ from] FromHexError ) ,
67109 #[ error( "at least one key must be provided" ) ]
68110 EmptyKeys ,
69111 #[ error( "contract id is required but was not provided" ) ]
70112 ContractRequired ,
113+ #[ error( "account is required but was not provided" ) ]
114+ AccountRequired ,
115+ #[ error( "provided asset is invalid: {0}" ) ]
116+ InvalidAsset ( String ) ,
117+ #[ error( "provided data name is invalid: {0}" ) ]
118+ InvalidDataName ( String ) ,
119+ #[ error( "provided hash value is invalid: {0}" ) ]
120+ InvalidHash ( String ) ,
121+ #[ error( "provided config id is invalid: {0}" ) ]
122+ InvalidConfigId ( i32 ) ,
71123}
72124
73125#[ derive( Clone , Copy , Debug , Eq , Hash , PartialEq , clap:: ValueEnum , Default ) ]
@@ -81,15 +133,15 @@ pub enum OutputFormat {
81133 JsonFormatted ,
82134}
83135
84-
85136impl Cmd {
86137 pub async fn run ( & self ) -> Result < ( ) , Error > {
87138 let network = self . network . get ( & self . locator ) ?;
88139 let client = network. rpc_client ( ) ?;
89140 let mut ledger_keys = vec ! [ ] ;
90141
91142 if let Some ( contract_id) = & self . contract_id {
92- let contract_id = contract_id. resolve_contract_id ( & self . locator , & network. network_passphrase ) ?;
143+ let contract_id =
144+ contract_id. resolve_contract_id ( & self . locator , & network. network_passphrase ) ?;
93145
94146 let contract_address_arg = ScAddress :: Contract ( Hash ( contract_id. 0 ) ) ;
95147
@@ -120,15 +172,131 @@ impl Cmd {
120172 }
121173 }
122174 } else if self . key . is_some ( ) || self . key_xdr . is_some ( ) {
123- return Err ( ContractRequired )
175+ return Err ( ContractRequired ) ;
124176 }
125177
126178 if let Some ( acc) = & self . account {
127179 let acc = self . muxed_account ( acc) ?;
128- let key = LedgerKey :: Account ( LedgerKeyAccount { account_id : acc. account_id ( ) } ) ;
129- ledger_keys. push ( key) ;
180+
181+ if let Some ( asset) = & self . asset {
182+ for asset in asset {
183+ let asset = if asset. to_ascii_uppercase ( ) == "XLM" {
184+ TrustLineAsset :: Native
185+ } else if asset. contains ( ":" ) {
186+ let mut parts = asset. split ( ":" ) ;
187+ let code = parts. next ( ) . ok_or ( InvalidAsset ( asset. clone ( ) ) ) ?;
188+ let issuer = parts. next ( ) . ok_or ( InvalidAsset ( asset. clone ( ) ) ) ?;
189+ if !parts. next ( ) . is_none ( ) {
190+ Err ( InvalidAsset ( asset. clone ( ) ) ) ?
191+ }
192+ let source_bytes = Ed25519PublicKey :: from_string ( issuer) . unwrap ( ) . 0 ;
193+ let issuer =
194+ AccountId ( PublicKey :: PublicKeyTypeEd25519 ( Uint256 ( source_bytes) ) ) ;
195+
196+ match code. len ( ) {
197+ 4 => TrustLineAsset :: CreditAlphanum4 ( AlphaNum4 {
198+ asset_code : AssetCode4 ( code. as_bytes ( ) . try_into ( ) ?) ,
199+ issuer,
200+ } ) ,
201+ 12 => TrustLineAsset :: CreditAlphanum12 ( AlphaNum12 {
202+ asset_code : AssetCode12 ( code. as_bytes ( ) . try_into ( ) ?) ,
203+ issuer,
204+ } ) ,
205+ _ => Err ( InvalidAsset ( asset. clone ( ) ) ) ?,
206+ }
207+ } else {
208+ Err ( InvalidAsset ( asset. clone ( ) ) ) ?
209+ } ;
210+ let key = LedgerKey :: Trustline ( LedgerKeyTrustLine {
211+ account_id : acc. clone ( ) . account_id ( ) ,
212+ asset,
213+ } ) ;
214+ ledger_keys. push ( key) ;
215+ }
216+ }
217+
218+ if let Some ( offer) = & self . offer {
219+ for offer in offer {
220+ let key = LedgerKey :: Offer ( LedgerKeyOffer {
221+ seller_id : acc. clone ( ) . account_id ( ) ,
222+ offer_id : * offer,
223+ } ) ;
224+ ledger_keys. push ( key) ;
225+ }
226+ }
227+
228+ if let Some ( data_name) = & self . data_name {
229+ for data_name in data_name {
230+ let data_name: xdr:: StringM < 64 > = data_name
231+ . parse ( )
232+ . map_err ( |_| InvalidDataName ( data_name. clone ( ) ) ) ?;
233+ let data_name = String64 ( data_name) ;
234+ let key = LedgerKey :: Data ( LedgerKeyData {
235+ account_id : acc. clone ( ) . account_id ( ) ,
236+ data_name,
237+ } ) ;
238+ ledger_keys. push ( key) ;
239+ }
240+ }
241+
242+ if self . asset . is_none ( ) && self . offer . is_none ( ) && self . data_name . is_none ( ) {
243+ let key = LedgerKey :: Account ( LedgerKeyAccount {
244+ account_id : acc. account_id ( ) ,
245+ } ) ;
246+ ledger_keys. push ( key) ;
247+ }
248+ } else if self . asset . is_some ( ) || self . offer . is_some ( ) || self . data_name . is_some ( ) {
249+ return Err ( AccountRequired ) ;
130250 }
131251
252+ if let Some ( claimable_id) = & self . claimable_id {
253+ for x in claimable_id {
254+ let hash = Hash ( padded_hex_from_str ( x, 32 ) ?. try_into ( ) . unwrap ( ) ) ;
255+ let key = LedgerKey :: ClaimableBalance ( LedgerKeyClaimableBalance {
256+ balance_id : ClaimableBalanceIdTypeV0 ( hash) ,
257+ } ) ;
258+ ledger_keys. push ( key) ;
259+ }
260+ }
261+
262+ if let Some ( pool_id) = & self . pool_id {
263+ for x in pool_id {
264+ let hash = Hash ( padded_hex_from_str ( x, 32 ) ?. try_into ( ) . unwrap ( ) ) ;
265+ let key = LedgerKey :: LiquidityPool ( LedgerKeyLiquidityPool {
266+ liquidity_pool_id : PoolId ( hash) ,
267+ } ) ;
268+ ledger_keys. push ( key) ;
269+ }
270+ }
271+
272+ if let Some ( wasm_hash) = & self . wasm_hash {
273+ for wasm_hash in wasm_hash {
274+ let hash = Hash (
275+ soroban_spec_tools:: utils:: contract_id_from_str ( wasm_hash)
276+ . map_err ( |_| InvalidHash ( wasm_hash. clone ( ) ) ) ?,
277+ ) ;
278+ let key = LedgerKey :: ContractCode ( LedgerKeyContractCode { hash } ) ;
279+ ledger_keys. push ( key) ;
280+ }
281+ }
282+
283+ if let Some ( config_setting_id) = & self . config_setting_id {
284+ for x in config_setting_id {
285+ let key = LedgerKey :: ConfigSetting ( LedgerKeyConfigSetting {
286+ config_setting_id : ConfigSettingId :: try_from ( * x)
287+ . map_err ( |_| InvalidConfigId ( * x) ) ?,
288+ } ) ;
289+ ledger_keys. push ( key) ;
290+ }
291+ }
292+
293+ if let Some ( ttl) = & self . ttl {
294+ for x in ttl {
295+ let hash = Hash ( padded_hex_from_str ( x, 32 ) ?. try_into ( ) . unwrap ( ) ) ;
296+ let key = LedgerKey :: Ttl ( LedgerKeyTtl { key_hash : hash } ) ;
297+ ledger_keys. push ( key) ;
298+ }
299+ }
132300
133301 if ledger_keys. is_empty ( ) {
134302 return Err ( EmptyKeys ) ;
@@ -149,7 +317,6 @@ impl Cmd {
149317 }
150318 }
151319
152-
153320 return Ok ( ( ) ) ;
154321 }
155322
0 commit comments