@@ -3,8 +3,9 @@ use lit_rust_sdk::{
33 types:: {
44 AccessControlCondition , DecryptRequest , EncryptRequest , LitAbility ,
55 LitResourceAbilityRequest , LitResourceAbilityRequestResource , ReturnValueTest ,
6+ ReturnValueTestV2 ,
67 } ,
7- LitNetwork , LitNodeClient , LitNodeClientConfig ,
8+ EvmContractCondition , LitNetwork , LitNodeClient , LitNodeClientConfig ,
89} ;
910use std:: time:: Duration ;
1011
@@ -62,7 +63,7 @@ async fn test_client_side_decryption_with_session_sigs() {
6263 parameters : vec ! [ ":userAddress" . to_string( ) , "latest" . to_string( ) ] ,
6364 return_value_test : ReturnValueTest {
6465 comparator : ">=" . to_string ( ) ,
65- value : serde_json :: json! ( "0" ) ,
66+ value : "0" . to_string ( ) ,
6667 } ,
6768 } ;
6869
@@ -154,3 +155,166 @@ async fn test_client_side_decryption_with_session_sigs() {
154155
155156 println ! ( "✅ Full encrypt/decrypt test with client-side decryption completed successfully!" ) ;
156157}
158+
159+ #[ tokio:: test]
160+ async fn test_client_side_decryption_with_session_sigs_and_evm_contract_conditions ( ) {
161+ // Initialize tracing for debugging (honors RUST_LOG)
162+ let _ = tracing_subscriber:: fmt ( )
163+ . with_env_filter ( tracing_subscriber:: EnvFilter :: from_default_env ( ) )
164+ . try_init ( ) ;
165+
166+ // Load wallet from environment
167+ let wallet = match load_wallet_from_env ( ) {
168+ Ok ( w) => w,
169+ Err ( e) => {
170+ println ! (
171+ "❌ Failed to load wallet from environment: {}. Make sure ETHEREUM_PRIVATE_KEY is set in .env" ,
172+ e
173+ ) ;
174+ println ! ( "Skipping test - required environment variables not set" ) ;
175+ return ;
176+ }
177+ } ;
178+
179+ println ! ( "🔑 Using wallet address: {}" , wallet. address( ) ) ;
180+
181+ // Create client configuration
182+ let config = LitNodeClientConfig {
183+ lit_network : LitNetwork :: DatilDev ,
184+ alert_when_unauthorized : true ,
185+ debug : true ,
186+ connect_timeout : Duration :: from_secs ( 30 ) ,
187+ check_node_attestation : false ,
188+ } ;
189+
190+ // Create and connect client
191+ let mut client = LitNodeClient :: new ( config)
192+ . await
193+ . expect ( "Failed to create client" ) ;
194+
195+ match client. connect ( ) . await {
196+ Ok ( ( ) ) => {
197+ println ! ( "✅ Connected to Lit Network" ) ;
198+ }
199+ Err ( e) => {
200+ panic ! ( "❌ Failed to connect to Lit Network: {}" , e) ;
201+ }
202+ }
203+
204+ let usdc_address_on_eth = "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48" ;
205+ // Create EVM contract condition with simple whitelist check
206+ let evm_contract_condition = EvmContractCondition {
207+ contract_address : usdc_address_on_eth. to_string ( ) ,
208+ function_name : "balanceOf" . to_string ( ) ,
209+ function_params : vec ! [ ":userAddress" . to_string( ) ] ,
210+ function_abi : ethabi:: Function {
211+ inputs : vec ! [ ethabi:: Param {
212+ internal_type: None ,
213+ name: "account" . to_string( ) ,
214+ kind: ethabi:: ParamType :: Address ,
215+ } ] ,
216+ name : "balanceOf" . to_string ( ) ,
217+ outputs : vec ! [ ethabi:: Param {
218+ internal_type: None ,
219+ name: "" . to_string( ) ,
220+ kind: ethabi:: ParamType :: Uint ( 256 ) ,
221+ } ] ,
222+ state_mutability : ethabi:: StateMutability :: View ,
223+ #[ allow( deprecated) ] // this is needed for compatibility with the version of ethabi running on the lit nodes which expects this param, and is an older version where this is not deprecated
224+ constant : Some ( false ) ,
225+ } ,
226+ chain : "ethereum" . to_string ( ) ,
227+ return_value_test : ReturnValueTestV2 {
228+ key : "" . to_string ( ) ,
229+ comparator : ">=" . to_string ( ) ,
230+ value : "0" . to_string ( ) ,
231+ } ,
232+ } ;
233+ let evm_contract_conditions = vec ! [ evm_contract_condition] ;
234+
235+ // Create test data to encrypt
236+ let test_data =
237+ b"Secret message that requires wallet ownership to decrypt using client-side decryption!" ;
238+
239+ // Create encrypt request using basic access control conditions
240+ let encrypt_request = EncryptRequest {
241+ data_to_encrypt : test_data. to_vec ( ) ,
242+ access_control_conditions : None ,
243+ evm_contract_conditions : Some ( evm_contract_conditions. clone ( ) ) ,
244+ sol_rpc_conditions : None ,
245+ unified_access_control_conditions : None ,
246+ } ;
247+
248+ // Encrypt the data
249+ println ! ( "🔒 Encrypting data with access control conditions..." ) ;
250+ let encrypt_response = match client. encrypt ( encrypt_request) . await {
251+ Ok ( response) => {
252+ println ! ( "✅ Data encrypted successfully!" ) ;
253+ println ! ( "📦 Ciphertext length: {} bytes" , response. ciphertext. len( ) ) ;
254+ println ! ( "🔗 Data hash: {}" , response. data_to_encrypt_hash) ;
255+ response
256+ }
257+ Err ( e) => {
258+ panic ! ( "❌ Encryption failed: {}" , e) ;
259+ }
260+ } ;
261+
262+ // Now let's prepare to decrypt by getting session signatures
263+ let resource_ability_requests = vec ! [ LitResourceAbilityRequest {
264+ resource: LitResourceAbilityRequestResource {
265+ resource: "*" . to_string( ) ,
266+ resource_prefix: "lit-accesscontrolcondition" . to_string( ) ,
267+ } ,
268+ ability: LitAbility :: AccessControlConditionDecryption . to_string( ) ,
269+ } ] ;
270+
271+ let expiration = ( chrono:: Utc :: now ( ) + chrono:: Duration :: minutes ( 10 ) ) . to_rfc3339 ( ) ;
272+
273+ println ! ( "🔄 Getting session signatures for decryption..." ) ;
274+ let session_sigs = client
275+ . get_local_session_sigs ( & wallet, resource_ability_requests, & expiration)
276+ . await
277+ . expect ( "Failed to create local session signatures" ) ;
278+
279+ println ! (
280+ "✅ Got session signatures from {} nodes" ,
281+ session_sigs. len( )
282+ ) ;
283+
284+ // Now decrypt using client-side decryption
285+ println ! ( "🔓 Decrypting data using client-side decryption..." ) ;
286+
287+ let decrypt_request = DecryptRequest {
288+ ciphertext : encrypt_response. ciphertext ,
289+ data_to_encrypt_hash : encrypt_response. data_to_encrypt_hash ,
290+ access_control_conditions : None ,
291+ evm_contract_conditions : Some ( evm_contract_conditions) ,
292+ sol_rpc_conditions : None ,
293+ unified_access_control_conditions : None ,
294+ chain : Some ( "ethereum" . to_string ( ) ) ,
295+ session_sigs,
296+ } ;
297+
298+ match client. decrypt ( decrypt_request) . await {
299+ Ok ( response) => {
300+ println ! ( "✅ Client-side decryption successful!" ) ;
301+
302+ // Convert decrypted bytes to string
303+ let decrypted_str = String :: from_utf8_lossy ( & response. decrypted_data ) ;
304+ println ! ( "🔓 Decrypted content: {}" , decrypted_str) ;
305+
306+ // Verify it matches our original data
307+ let original = String :: from_utf8_lossy ( test_data) ;
308+ assert_eq ! (
309+ decrypted_str, original,
310+ "Decrypted data should match original data"
311+ ) ;
312+ println ! ( "✅ Decryption successful - data matches original!" ) ;
313+ }
314+ Err ( e) => {
315+ panic ! ( "❌ Failed to decrypt using client-side decryption: {}" , e) ;
316+ }
317+ }
318+
319+ println ! ( "✅ Full encrypt/decrypt test with client-side decryption completed successfully!" ) ;
320+ }
0 commit comments