@@ -379,20 +379,82 @@ pub fn build_and_sign_user_operation_for_payment(
379379 "call_data" : call_data,
380380 "use_paymaster" : use_paymaster,
381381 } ) ;
382-
382+
383383 if let Some ( v) = value {
384384 params[ "value" ] = serde_json:: Value :: String ( v. to_string ( ) ) ;
385385 }
386-
386+
387387 if let Some ( pwd) = password {
388388 params[ "password" ] = serde_json:: Value :: String ( pwd. to_string ( ) ) ;
389389 }
390-
390+
391391 // Pass metadata through to hyperwallet
392392 if let Some ( meta) = metadata {
393393 params[ "metadata" ] = serde_json:: Value :: Object ( meta) ;
394394 }
395+
396+ let request = build_request (
397+ our,
398+ session_info,
399+ Operation :: BuildAndSignUserOperationForPayment ,
400+ params,
401+ Some ( wallet_id. to_string ( ) ) ,
402+ chain_id,
403+ ) ;
404+ let response = execute_request ( request, our) ?;
405+ Ok ( response. data . unwrap_or_default ( ) )
406+ }
395407
408+ /// High-level convenience function for building and signing UserOperations with TBA support.
409+ /// This mirrors your current build_and_sign_user_operation function.
410+ pub fn build_and_sign_user_operation (
411+ our : & Address ,
412+ session_info : & SessionInfo ,
413+ wallet_id : & str ,
414+ target : & str ,
415+ call_data : & str ,
416+ value : Option < & str > ,
417+ use_paymaster : bool ,
418+ tba_address : Option < & str > ,
419+ password : Option < & str > ,
420+ chain_id : Option < u64 > ,
421+ ) -> Result < serde_json:: Value , HyperwalletClientError > {
422+ let mut params = serde_json:: json!( {
423+ "target" : target,
424+ "call_data" : call_data,
425+ "use_paymaster" : use_paymaster,
426+ } ) ;
427+
428+ if let Some ( v) = value {
429+ params[ "value" ] = serde_json:: Value :: String ( v. to_string ( ) ) ;
430+ }
431+
432+ if let Some ( pwd) = password {
433+ params[ "password" ] = serde_json:: Value :: String ( pwd. to_string ( ) ) ;
434+ }
435+
436+ // Create metadata with Circle paymaster configuration if using paymaster
437+ if use_paymaster {
438+ let mut metadata = serde_json:: Map :: new ( ) ;
439+
440+ // Always add Circle paymaster metadata for gasless transactions
441+ // These constants should be defined somewhere accessible
442+ metadata. insert ( "paymaster_address" . to_string ( ) ,
443+ serde_json:: json!( "0x2Ac3c1d3e24b45c6C310534Bc2Dd84B5ed576335" ) ) ; // Base Circle paymaster
444+ metadata. insert ( "is_circle_paymaster" . to_string ( ) , serde_json:: json!( true ) ) ;
445+ metadata. insert ( "paymaster_verification_gas" . to_string ( ) ,
446+ serde_json:: json!( "0x30000" ) ) ; // 196608
447+ metadata. insert ( "paymaster_post_op_gas" . to_string ( ) ,
448+ serde_json:: json!( "0x20000" ) ) ; // 131072
449+
450+ // Add TBA address if provided - tells hyperwallet to use TBA as sender
451+ if let Some ( tba) = tba_address {
452+ metadata. insert ( "tba_address" . to_string ( ) , serde_json:: json!( tba) ) ;
453+ }
454+
455+ params[ "metadata" ] = serde_json:: Value :: Object ( metadata) ;
456+ }
457+
396458 let request = build_request (
397459 our,
398460 session_info,
@@ -461,6 +523,142 @@ pub fn get_user_operation_receipt(
461523 Ok ( response. data . unwrap_or_default ( ) )
462524}
463525
526+ /// High-level convenience function that executes a complete payment flow.
527+ /// This function handles: session management, building UserOp, submitting, and waiting for receipt.
528+ pub fn execute_gasless_payment (
529+ our : & Address ,
530+ wallet_id : & str ,
531+ target : & str ,
532+ call_data : & str ,
533+ value : Option < & str > ,
534+ tba_address : Option < & str > ,
535+ password : Option < & str > ,
536+ chain_id : Option < u64 > ,
537+ ) -> Result < serde_json:: Value , HyperwalletClientError > {
538+ // Step 1: Initialize session if needed (you might want to cache this)
539+ let session = super :: initialize ( our, super :: HandshakeConfig :: new ( ) ) ?;
540+
541+ // Step 2: Build and sign UserOperation
542+ let signed_data = build_and_sign_user_operation (
543+ our,
544+ & session,
545+ wallet_id,
546+ target,
547+ call_data,
548+ value,
549+ true , // Always use paymaster for gasless
550+ tba_address,
551+ password,
552+ chain_id,
553+ ) ?;
554+
555+ // Step 3: Extract signed UserOperation and entry point
556+ let signed_user_op = signed_data. get ( "signed_user_operation" )
557+ . ok_or_else ( || HyperwalletClientError :: ServerError (
558+ super :: types:: OperationError :: internal_error ( "Missing signed_user_operation in response" )
559+ ) ) ?
560+ . clone ( ) ;
561+
562+ let entry_point = signed_data. get ( "entry_point" )
563+ . and_then ( |e| e. as_str ( ) )
564+ . ok_or_else ( || HyperwalletClientError :: ServerError (
565+ super :: types:: OperationError :: internal_error ( "Missing entry_point in response" )
566+ ) ) ?;
567+
568+ // Step 4: Submit UserOperation
569+ let user_op_hash = submit_user_operation (
570+ our,
571+ & session,
572+ signed_user_op,
573+ entry_point,
574+ None , // Use default bundler
575+ chain_id,
576+ ) ?;
577+
578+ // Step 5: Get receipt (you might want to add polling with timeout)
579+ let receipt = get_user_operation_receipt ( our, & session, & user_op_hash, chain_id) ?;
580+
581+ Ok ( receipt)
582+ }
583+
584+ /// Simplified gasless payment function - abstracts away all complexity.
585+ /// This is what the operator should actually use.
586+ pub fn build_and_sign_gasless_payment (
587+ our : & Address ,
588+ session_info : & SessionInfo ,
589+ signer_wallet_id : & str ,
590+ tba_address : & str ,
591+ call_data : & str ,
592+ chain_id : Option < u64 > ,
593+ ) -> Result < serde_json:: Value , HyperwalletClientError > {
594+ let params = serde_json:: json!( {
595+ "target" : tba_address,
596+ "call_data" : call_data,
597+ "use_paymaster" : true , // Always gasless
598+ "metadata" : {
599+ "tba_address" : tba_address,
600+ "is_circle_paymaster" : true ,
601+ "paymaster_address" : "0x0578cFB241215b77442a541325d6A4E6dFE700Ec" ,
602+ "paymaster_verification_gas" : "0x7a120" ,
603+ "paymaster_post_op_gas" : "0x493e0"
604+ }
605+ } ) ;
606+
607+ let request = build_request (
608+ our,
609+ session_info,
610+ Operation :: BuildAndSignUserOperationForPayment ,
611+ params,
612+ Some ( signer_wallet_id. to_string ( ) ) ,
613+ chain_id,
614+ ) ;
615+ let response = execute_request ( request, our) ?;
616+ Ok ( response. data . unwrap_or_default ( ) )
617+ }
618+
619+ /// Simplified submit that extracts entry point automatically from build response.
620+ pub fn submit_gasless_payment (
621+ our : & Address ,
622+ session_info : & SessionInfo ,
623+ signed_user_op_response : serde_json:: Value ,
624+ chain_id : Option < u64 > ,
625+ ) -> Result < String , HyperwalletClientError > {
626+ // Extract signed UserOperation and entry point from the build response
627+ let signed_user_op = signed_user_op_response. get ( "signed_user_operation" )
628+ . ok_or_else ( || HyperwalletClientError :: ServerError (
629+ super :: types:: OperationError :: internal_error ( "Missing signed_user_operation in response" )
630+ ) ) ?
631+ . clone ( ) ;
632+
633+ let entry_point = signed_user_op_response. get ( "entry_point" )
634+ . and_then ( |e| e. as_str ( ) )
635+ . ok_or_else ( || HyperwalletClientError :: ServerError (
636+ super :: types:: OperationError :: internal_error ( "Missing entry_point in response" )
637+ ) ) ?;
638+
639+ // Submit using the extracted data
640+ submit_user_operation ( our, session_info, signed_user_op, entry_point, None , chain_id)
641+ }
642+
643+ /// Get receipt with proper transaction hash extraction.
644+ pub fn get_payment_receipt (
645+ our : & Address ,
646+ session_info : & SessionInfo ,
647+ user_op_hash : & str ,
648+ chain_id : Option < u64 > ,
649+ ) -> Result < ( String , serde_json:: Value ) , HyperwalletClientError > {
650+ let receipt = get_user_operation_receipt ( our, session_info, user_op_hash, chain_id) ?;
651+
652+ // Extract transaction hash if available
653+ let tx_hash = receipt. get ( "receipt" )
654+ . and_then ( |r| r. get ( "transactionHash" ) )
655+ . and_then ( |h| h. as_str ( ) )
656+ . unwrap_or ( user_op_hash) // Fallback to user op hash
657+ . to_string ( ) ;
658+
659+ Ok ( ( tx_hash, receipt) )
660+ }
661+
464662/// Resolves an identity name to an address via Hypermap.
465663pub fn resolve_identity (
466664 our : & Address ,
0 commit comments