Bug: [FEAT] add a wrapper for encryption and decryption




diff --git a/crates/common_utils/src/macros.rs b/crates/common_utils/src/macros.rs
index abd24ac8679..06554ee9b51 100644
--- a/crates/common_utils/src/macros.rs
+++ b/crates/common_utils/src/macros.rs
@@ -301,3 +301,14 @@ mod id_type {
         };
     }
 }
+
+/// Get the type name for a type
+#[macro_export]
+macro_rules! type_name {
+    ($type:ty) => {
+        std::any::type_name::<$type>()
+            .rsplit("::")
+            .nth(1)
+            .unwrap_or_default();
+    };
+}
diff --git a/crates/hyperswitch_domain_models/src/business_profile.rs b/crates/hyperswitch_domain_models/src/business_profile.rs
index 779dcdb2fbb..08903748c01 100644
--- a/crates/hyperswitch_domain_models/src/business_profile.rs
+++ b/crates/hyperswitch_domain_models/src/business_profile.rs
@@ -5,7 +5,7 @@ use common_utils::{
     date_time,
     encryption::Encryption,
     errors::{CustomResult, ValidationError},
-    pii,
+    pii, type_name,
     types::keymanager,
 };
 use diesel_models::business_profile::{
@@ -15,7 +15,7 @@ use diesel_models::business_profile::{
 use error_stack::ResultExt;
 use masking::{PeekInterface, Secret};
 
-use crate::type_encryption::{decrypt_optional, AsyncLift};
+use crate::type_encryption::{crypto_operation, AsyncLift, CryptoOperation};
 
 #[cfg(all(
     any(feature = "v1", feature = "v2"),
@@ -348,8 +348,16 @@ impl super::behaviour::Conversion for BusinessProfile {
                     .collect_billing_details_from_wallet_connector,
                 outgoing_webhook_custom_http_headers: item
                     .outgoing_webhook_custom_http_headers
-                    .async_lift(|inner| {
-                        decrypt_optional(state, inner, key_manager_identifier.clone(), key.peek())
+                    .async_lift(|inner| async {
+                        crypto_operation(
+                            state,
+                            type_name!(Self::DstType),
+                            CryptoOperation::DecryptOptional(inner),
+                            key_manager_identifier.clone(),
+                            key.peek(),
+                        )
+                        .await
+                        .and_then(|val| val.try_into_optionaloperation())
                     })
                     .await?,
             })
@@ -725,8 +733,16 @@ impl super::behaviour::Conversion for BusinessProfile {
                     .collect_billing_details_from_wallet_connector,
                 outgoing_webhook_custom_http_headers: item
                     .outgoing_webhook_custom_http_headers
-                    .async_lift(|inner| {
-                        decrypt_optional(state, inner, key_manager_identifier.clone(), key.peek())
+                    .async_lift(|inner| async {
+                        crypto_operation(
+                            state,
+                            type_name!(Self::DstType),
+                            CryptoOperation::DecryptOptional(inner),
+                            key_manager_identifier.clone(),
+                            key.peek(),
+                        )
+                        .await
+                        .and_then(|val| val.try_into_optionaloperation())
                     })
                     .await?,
                 routing_algorithm_id: item.routing_algorithm_id,
diff --git a/crates/hyperswitch_domain_models/src/customer.rs b/crates/hyperswitch_domain_models/src/customer.rs
index 6b08e30d33f..42c66b74c01 100644
--- a/crates/hyperswitch_domain_models/src/customer.rs
+++ b/crates/hyperswitch_domain_models/src/customer.rs
@@ -110,17 +110,21 @@ impl super::behaviour::Conversion for Customer {
     where
         Self: Sized,
     {
-        let decrypted = types::batch_decrypt(
+        let decrypted = types::crypto_operation(
             state,
-            CustomerRequestWithEncryption::to_encryptable(CustomerRequestWithEncryption {
-                name: item.name.clone(),
-                phone: item.phone.clone(),
-                email: item.email.clone(),
-            }),
+            common_utils::type_name!(Self::DstType),
+            types::CryptoOperation::BatchDecrypt(CustomerRequestWithEncryption::to_encryptable(
+                CustomerRequestWithEncryption {
+                    name: item.name.clone(),
+                    phone: item.phone.clone(),
+                    email: item.email.clone(),
+                },
+            )),
             keymanager::Identifier::Merchant(item.merchant_id.clone()),
             key.peek(),
         )
         .await
+        .and_then(|val| val.try_into_batchoperation())
         .change_context(ValidationError::InvalidValue {
             message: "Failed while decrypting customer data".to_string(),
         })?;
@@ -206,17 +210,21 @@ impl super::behaviour::Conversion for Customer {
     where
         Self: Sized,
     {
-        let decrypted = types::batch_decrypt(
+        let decrypted = types::crypto_operation(
             state,
-            CustomerRequestWithEncryption::to_encryptable(CustomerRequestWithEncryption {
-                name: item.name.clone(),
-                phone: item.phone.clone(),
-                email: item.email.clone(),
-            }),
+            type_name!(Self::DstType),
+            types::CryptoOperation::BatchDecrypt(CustomerRequestWithEncryption::to_encryptable(
+                CustomerRequestWithEncryption {
+                    name: item.name.clone(),
+                    phone: item.phone.clone(),
+                    email: item.email.clone(),
+                },
+            )),
             keymanager::Identifier::Merchant(item.merchant_id.clone()),
             key.peek(),
         )
         .await
+        .and_then(|val| val.try_into_batchoperation())
         .change_context(ValidationError::InvalidValue {
             message: "Failed while decrypting customer data".to_string(),
         })?;
diff --git a/crates/hyperswitch_domain_models/src/merchant_account.rs b/crates/hyperswitch_domain_models/src/merchant_account.rs
index 1697b78275c..8ce0b3a5e43 100644
--- a/crates/hyperswitch_domain_models/src/merchant_account.rs
+++ b/crates/hyperswitch_domain_models/src/merchant_account.rs
@@ -4,7 +4,7 @@ use common_utils::{
     encryption::Encryption,
     errors::{CustomResult, ValidationError},
     ext_traits::ValueExt,
-    pii,
+    pii, type_name,
     types::keymanager::{self},
 };
 use diesel_models::{
@@ -15,7 +15,7 @@ use error_stack::ResultExt;
 use masking::{PeekInterface, Secret};
 use router_env::logger;
 
-use crate::type_encryption::{decrypt_optional, AsyncLift};
+use crate::type_encryption::{crypto_operation, AsyncLift, CryptoOperation};
 
 #[cfg(all(
     any(feature = "v1", feature = "v2"),
@@ -565,14 +565,30 @@ impl super::behaviour::Conversion for MerchantAccount {
                 id,
                 merchant_name: item
                     .merchant_name
-                    .async_lift(|inner| {
-                        decrypt_optional(state, inner, key_manager_identifier.clone(), key.peek())
+                    .async_lift(|inner| async {
+                        crypto_operation(
+                            state,
+                            type_name!(Self::DstType),
+                            CryptoOperation::DecryptOptional(inner),
+                            key_manager_identifier.clone(),
+                            key.peek(),
+                        )
+                        .await
+                        .and_then(|val| val.try_into_optionaloperation())
                     })
                     .await?,
                 merchant_details: item
                     .merchant_details
-                    .async_lift(|inner| {
-                        decrypt_optional(state, inner, key_manager_identifier.clone(), key.peek())
+                    .async_lift(|inner| async {
+                        crypto_operation(
+                            state,
+                            type_name!(Self::DstType),
+                            CryptoOperation::DecryptOptional(inner),
+                            key_manager_identifier.clone(),
+                            key.peek(),
+                        )
+                        .await
+                        .and_then(|val| val.try_into_optionaloperation())
                     })
                     .await?,
                 publishable_key,
@@ -679,14 +695,30 @@ impl super::behaviour::Conversion for MerchantAccount {
                 redirect_to_merchant_with_http_post: item.redirect_to_merchant_with_http_post,
                 merchant_name: item
                     .merchant_name
-                    .async_lift(|inner| {
-                        decrypt_optional(state, inner, key_manager_identifier.clone(), key.peek())
+                    .async_lift(|inner| async {
+                        crypto_operation(
+                            state,
+                            type_name!(Self::DstType),
+                            CryptoOperation::DecryptOptional(inner),
+                            key_manager_identifier.clone(),
+                            key.peek(),
+                        )
+                        .await
+                        .and_then(|val| val.try_into_optionaloperation())
                     })
                     .await?,
                 merchant_details: item
                     .merchant_details
-                    .async_lift(|inner| {
-                        decrypt_optional(state, inner, key_manager_identifier.clone(), key.peek())
+                    .async_lift(|inner| async {
+                        crypto_operation(
+                            state,
+                            type_name!(Self::DstType),
+                            CryptoOperation::DecryptOptional(inner),
+                            key_manager_identifier.clone(),
+                            key.peek(),
+                        )
+                        .await
+                        .and_then(|val| val.try_into_optionaloperation())
                     })
                     .await?,
                 webhook_details: item.webhook_details,
diff --git a/crates/hyperswitch_domain_models/src/merchant_connector_account.rs b/crates/hyperswitch_domain_models/src/merchant_connector_account.rs
index cea595aed64..006fd5d7755 100644
--- a/crates/hyperswitch_domain_models/src/merchant_connector_account.rs
+++ b/crates/hyperswitch_domain_models/src/merchant_connector_account.rs
@@ -3,7 +3,7 @@ use common_utils::{
     date_time,
     encryption::Encryption,
     errors::{CustomResult, ValidationError},
-    pii,
+    pii, type_name,
     types::keymanager::{Identifier, KeyManagerState},
 };
 use diesel_models::{enums, merchant_connector_account::MerchantConnectorAccountUpdateInternal};
@@ -11,7 +11,7 @@ use error_stack::ResultExt;
 use masking::{PeekInterface, Secret};
 
 use super::behaviour;
-use crate::type_encryption::{decrypt, decrypt_optional, AsyncLift};
+use crate::type_encryption::{crypto_operation, AsyncLift, CryptoOperation};
 
 #[cfg(all(
     any(feature = "v1", feature = "v2"),
@@ -185,13 +185,15 @@ impl behaviour::Conversion for MerchantConnectorAccount {
         Ok(Self {
             merchant_id: other.merchant_id,
             connector_name: other.connector_name,
-            connector_account_details: decrypt(
+            connector_account_details: crypto_operation(
                 state,
-                other.connector_account_details,
+                type_name!(Self::DstType),
+                CryptoOperation::Decrypt(other.connector_account_details),
                 identifier.clone(),
                 key.peek(),
             )
             .await
+            .and_then(|val| val.try_into_operation())
             .change_context(ValidationError::InvalidValue {
                 message: "Failed while decrypting connector account details".to_string(),
             })?,
@@ -216,18 +218,35 @@ impl behaviour::Conversion for MerchantConnectorAccount {
             status: other.status,
             connector_wallets_details: other
                 .connector_wallets_details
-                .async_lift(|inner| decrypt_optional(state, inner, identifier.clone(), key.peek()))
+                .async_lift(|inner| async {
+                    crypto_operation(
+                        state,
+                        type_name!(Self::DstType),
+                        CryptoOperation::DecryptOptional(inner),
+                        identifier.clone(),
+                        key.peek(),
+                    )
+                    .await
+                    .and_then(|val| val.try_into_optionaloperation())
+                })
                 .await
                 .change_context(ValidationError::InvalidValue {
                     message: "Failed while decrypting connector wallets details".to_string(),
                 })?,
             additional_merchant_data: if let Some(data) = other.additional_merchant_data {
                 Some(
-                    decrypt(state, data, identifier, key.peek())
-                        .await
-                        .change_context(ValidationError::InvalidValue {
-                            message: "Failed while decrypting additional_merchant_data".to_string(),
-                        })?,
+                    crypto_operation(
+                        state,
+                        type_name!(Self::DstType),
+                        CryptoOperation::Decrypt(data),
+                        identifier,
+                        key.peek(),
+                    )
+                    .await
+                    .and_then(|val| val.try_into_operation())
+                    .change_context(ValidationError::InvalidValue {
+                        message: "Failed while decrypting additional_merchant_data".to_string(),
+                    })?,
                 )
             } else {
                 None
@@ -309,13 +328,15 @@ impl behaviour::Conversion for MerchantConnectorAccount {
             id: other.id,
             merchant_id: other.merchant_id,
             connector_name: other.connector_name,
-            connector_account_details: decrypt(
+            connector_account_details: crypto_operation(
                 state,
-                other.connector_account_details,
+                type_name!(Self::DstType),
+                CryptoOperation::Decrypt(other.connector_account_details),
                 identifier.clone(),
                 key.peek(),
             )
             .await
+            .and_then(|val| val.try_into_operation())
             .change_context(ValidationError::InvalidValue {
                 message: "Failed while decrypting connector account details".to_string(),
             })?,
@@ -335,18 +356,35 @@ impl behaviour::Conversion for MerchantConnectorAccount {
             status: other.status,
             connector_wallets_details: other
                 .connector_wallets_details
-                .async_lift(|inner| decrypt_optional(state, inner, identifier.clone(), key.peek()))
+                .async_lift(|inner| async {
+                    crypto_operation(
+                        state,
+                        type_name!(Self::DstType),
+                        CryptoOperation::DecryptOptional(inner),
+                        identifier.clone(),
+                        key.peek(),
+                    )
+                    .await
+                    .and_then(|val| val.try_into_optionaloperation())
+                })
                 .await
                 .change_context(ValidationError::InvalidValue {
                     message: "Failed while decrypting connector wallets details".to_string(),
                 })?,
             additional_merchant_data: if let Some(data) = other.additional_merchant_data {
                 Some(
-                    decrypt(state, data, identifier, key.peek())
-                        .await
-                        .change_context(ValidationError::InvalidValue {
-                            message: "Failed while decrypting additional_merchant_data".to_string(),
-                        })?,
+                    crypto_operation(
+                        state,
+                        type_name!(Self::DstType),
+                        CryptoOperation::Decrypt(data),
+                        identifier,
+                        key.peek(),
+                    )
+                    .await
+                    .and_then(|val| val.try_into_operation())
+                    .change_context(ValidationError::InvalidValue {
+                        message: "Failed while decrypting additional_merchant_data".to_string(),
+                    })?,
                 )
             } else {
                 None
diff --git a/crates/hyperswitch_domain_models/src/merchant_key_store.rs b/crates/hyperswitch_domain_models/src/merchant_key_store.rs
index bfd75a08fa3..d24e23c5792 100644
--- a/crates/hyperswitch_domain_models/src/merchant_key_store.rs
+++ b/crates/hyperswitch_domain_models/src/merchant_key_store.rs
@@ -2,13 +2,14 @@ use common_utils::{
     crypto::Encryptable,
     custom_serde, date_time,
     errors::{CustomResult, ValidationError},
+    type_name,
     types::keymanager::{self, KeyManagerState},
 };
 use error_stack::ResultExt;
 use masking::{PeekInterface, Secret};
 use time::PrimitiveDateTime;
 
-use crate::type_encryption::decrypt;
+use crate::type_encryption::{crypto_operation, CryptoOperation};
 
 #[derive(Clone, Debug, serde::Serialize)]
 pub struct MerchantKeyStore {
@@ -40,12 +41,20 @@ impl super::behaviour::Conversion for MerchantKeyStore {
         Self: Sized,
     {
         let identifier = keymanager::Identifier::Merchant(item.merchant_id.clone());
+
         Ok(Self {
-            key: decrypt(state, item.key, identifier, key.peek())
-                .await
-                .change_context(ValidationError::InvalidValue {
-                    message: "Failed while decrypting customer data".to_string(),
-                })?,
+            key: crypto_operation(
+                state,
+                type_name!(Self::DstType),
+                CryptoOperation::Decrypt(item.key),
+                identifier,
+                key.peek(),
+            )
+            .await
+            .and_then(|val| val.try_into_operation())
+            .change_context(ValidationError::InvalidValue {
+                message: "Failed while decrypting customer data".to_string(),
+            })?,
             merchant_id: item.merchant_id,
             created_at: item.created_at,
         })
diff --git a/crates/hyperswitch_domain_models/src/payments/payment_attempt.rs b/crates/hyperswitch_domain_models/src/payments/payment_attempt.rs
index 15c5aded500..79818d5b157 100644
--- a/crates/hyperswitch_domain_models/src/payments/payment_attempt.rs
+++ b/crates/hyperswitch_domain_models/src/payments/payment_attempt.rs
@@ -3,7 +3,7 @@ use common_enums as storage_enums;
 use common_utils::{
     encryption::Encryption,
     errors::{CustomResult, ValidationError},
-    id_type, pii,
+    id_type, pii, type_name,
     types::{
         keymanager::{self, KeyManagerState},
         MinorUnit,
@@ -18,7 +18,7 @@ use super::PaymentIntent;
 use crate::{
     behaviour, errors,
     mandates::{MandateDataType, MandateDetails},
-    type_encryption::{decrypt_optional, AsyncLift},
+    type_encryption::{crypto_operation, AsyncLift, CryptoOperation},
     ForeignIDRef, RemoteStorageObject,
 };
 
@@ -553,8 +553,17 @@ impl behaviour::Conversion for PaymentIntent {
         Self: Sized,
     {
         async {
-            let inner_decrypt =
-                |inner| decrypt_optional(state, inner, key_manager_identifier.clone(), key.peek());
+            let inner_decrypt = |inner| async {
+                crypto_operation(
+                    state,
+                    type_name!(Self::DstType),
+                    CryptoOperation::DecryptOptional(inner),
+                    key_manager_identifier.clone(),
+                    key.peek(),
+                )
+                .await
+                .and_then(|val| val.try_into_optionaloperation())
+            };
             Ok::<Self, error_stack::Report<common_utils::errors::CryptoError>>(Self {
                 payment_id: storage_model.payment_id,
                 merchant_id: storage_model.merchant_id,
@@ -742,8 +751,17 @@ impl behaviour::Conversion for PaymentIntent {
         Self: Sized,
     {
         async {
-            let inner_decrypt =
-                |inner| decrypt_optional(state, inner, key_manager_identifier.clone(), key.peek());
+            let inner_decrypt = |inner| async {
+                crypto_operation(
+                    state,
+                    type_name!(Self::DstType),
+                    CryptoOperation::DecryptOptional(inner),
+                    key_manager_identifier.clone(),
+                    key.peek(),
+                )
+                .await
+                .and_then(|val| val.try_into_optionaloperation())
+            };
             Ok::<Self, error_stack::Report<common_utils::errors::CryptoError>>(Self {
                 payment_id: storage_model.payment_id,
                 merchant_id: storage_model.merchant_id,
diff --git a/crates/hyperswitch_domain_models/src/type_encryption.rs b/crates/hyperswitch_domain_models/src/type_encryption.rs
index a36969478d1..0ff37b0bc29 100644
--- a/crates/hyperswitch_domain_models/src/type_encryption.rs
+++ b/crates/hyperswitch_domain_models/src/type_encryption.rs
@@ -9,6 +9,7 @@ use common_utils::{
 };
 use encrypt::TypeEncryption;
 use masking::Secret;
+use router_env::{instrument, tracing};
 use rustc_hash::FxHashMap;
 
 mod encrypt {
@@ -831,12 +832,12 @@ impl<U, V: Lift<U> + Lift<U, SelfWrapper<U> = V> + Send> AsyncLift<U> for V {
 }
 
 #[inline]
-pub async fn encrypt<E: Clone, S>(
+async fn encrypt<E: Clone, S>(
     state: &KeyManagerState,
     inner: Secret<E, S>,
     identifier: Identifier,
     key: &[u8],
-) -> CustomResult<crypto::Encryptable<Secret<E, S>>, errors::CryptoError>
+) -> CustomResult<crypto::Encryptable<Secret<E, S>>, CryptoError>
 where
     S: masking::Strategy<E>,
     crypto::Encryptable<Secret<E, S>>: TypeEncryption<E, crypto::GcmAes256, S>,
@@ -851,12 +852,12 @@ where
 }
 
 #[inline]
-pub async fn batch_encrypt<E: Clone, S>(
+async fn batch_encrypt<E: Clone, S>(
     state: &KeyManagerState,
     inner: FxHashMap<String, Secret<E, S>>,
     identifier: Identifier,
     key: &[u8],
-) -> CustomResult<FxHashMap<String, crypto::Encryptable<Secret<E, S>>>, errors::CryptoError>
+) -> CustomResult<FxHashMap<String, crypto::Encryptable<Secret<E, S>>>, CryptoError>
 where
     S: masking::Strategy<E>,
     crypto::Encryptable<Secret<E, S>>: TypeEncryption<E, crypto::GcmAes256, S>,
@@ -881,12 +882,12 @@ where
 }
 
 #[inline]
-pub async fn encrypt_optional<E: Clone, S>(
+async fn encrypt_optional<E: Clone, S>(
     state: &KeyManagerState,
     inner: Option<Secret<E, S>>,
     identifier: Identifier,
     key: &[u8],
-) -> CustomResult<Option<crypto::Encryptable<Secret<E, S>>>, errors::CryptoError>
+) -> CustomResult<Option<crypto::Encryptable<Secret<E, S>>>, CryptoError>
 where
     Secret<E, S>: Send,
     S: masking::Strategy<E>,
@@ -899,12 +900,12 @@ where
 }
 
 #[inline]
-pub async fn decrypt_optional<T: Clone, S: masking::Strategy<T>>(
+async fn decrypt_optional<T: Clone, S: masking::Strategy<T>>(
     state: &KeyManagerState,
     inner: Option<Encryption>,
     identifier: Identifier,
     key: &[u8],
-) -> CustomResult<Option<crypto::Encryptable<Secret<T, S>>>, errors::CryptoError>
+) -> CustomResult<Option<crypto::Encryptable<Secret<T, S>>>, CryptoError>
 where
     crypto::Encryptable<Secret<T, S>>: TypeEncryption<T, crypto::GcmAes256, S>,
 {
@@ -915,12 +916,12 @@ where
 }
 
 #[inline]
-pub async fn decrypt<T: Clone, S: masking::Strategy<T>>(
+async fn decrypt<T: Clone, S: masking::Strategy<T>>(
     state: &KeyManagerState,
     inner: Encryption,
     identifier: Identifier,
     key: &[u8],
-) -> CustomResult<crypto::Encryptable<Secret<T, S>>, errors::CryptoError>
+) -> CustomResult<crypto::Encryptable<Secret<T, S>>, CryptoError>
 where
     crypto::Encryptable<Secret<T, S>>: TypeEncryption<T, crypto::GcmAes256, S>,
 {
@@ -934,12 +935,12 @@ where
 }
 
 #[inline]
-pub async fn batch_decrypt<E: Clone, S>(
+async fn batch_decrypt<E: Clone, S>(
     state: &KeyManagerState,
     inner: FxHashMap<String, Encryption>,
     identifier: Identifier,
     key: &[u8],
-) -> CustomResult<FxHashMap<String, crypto::Encryptable<Secret<E, S>>>, errors::CryptoError>
+) -> CustomResult<FxHashMap<String, crypto::Encryptable<Secret<E, S>>>, CryptoError>
 where
     S: masking::Strategy<E>,
     crypto::Encryptable<Secret<E, S>>: TypeEncryption<E, crypto::GcmAes256, S>,
@@ -963,6 +964,65 @@ where
     }
 }
 
+pub enum CryptoOperation<T: Clone, S: masking::Strategy<T>> {
+    Encrypt(Secret<T, S>),
+    EncryptOptional(Option<Secret<T, S>>),
+    Decrypt(Encryption),
+    DecryptOptional(Option<Encryption>),
+    BatchEncrypt(FxHashMap<String, Secret<T, S>>),
+    BatchDecrypt(FxHashMap<String, Encryption>),
+}
+
+use errors::CryptoError;
+
+#[derive(router_derive::TryGetEnumVariant)]
+#[error(CryptoError::EncodingFailed)]
+pub enum CryptoOutput<T: Clone, S: masking::Strategy<T>> {
+    Operation(crypto::Encryptable<Secret<T, S>>),
+    OptionalOperation(Option<crypto::Encryptable<Secret<T, S>>>),
+    BatchOperation(FxHashMap<String, crypto::Encryptable<Secret<T, S>>>),
+}
+
+#[instrument(skip_all, fields(table = table_name))]
+pub async fn crypto_operation<T: Clone + Send, S: masking::Strategy<T>>(
+    state: &KeyManagerState,
+    table_name: &str,
+    operation: CryptoOperation<T, S>,
+    identifier: Identifier,
+    key: &[u8],
+) -> CustomResult<CryptoOutput<T, S>, CryptoError>
+where
+    Secret<T, S>: Send,
+    crypto::Encryptable<Secret<T, S>>: TypeEncryption<T, crypto::GcmAes256, S>,
+{
+    match operation {
+        CryptoOperation::Encrypt(data) => {
+            let data = encrypt(state, data, identifier, key).await?;
+            Ok(CryptoOutput::Operation(data))
+        }
+        CryptoOperation::EncryptOptional(data) => {
+            let data = encrypt_optional(state, data, identifier, key).await?;
+            Ok(CryptoOutput::OptionalOperation(data))
+        }
+        CryptoOperation::Decrypt(data) => {
+            let data = decrypt(state, data, identifier, key).await?;
+            Ok(CryptoOutput::Operation(data))
+        }
+        CryptoOperation::DecryptOptional(data) => {
+            let data = decrypt_optional(state, data, identifier, key).await?;
+            Ok(CryptoOutput::OptionalOperation(data))
+        }
+        CryptoOperation::BatchEncrypt(data) => {
+            let data = batch_encrypt(state, data, identifier, key).await?;
+            Ok(CryptoOutput::BatchOperation(data))
+        }
+        CryptoOperation::BatchDecrypt(data) => {
+            let data = batch_decrypt(state, data, identifier, key).await?;
+            Ok(CryptoOutput::BatchOperation(data))
+        }
+    }
+}
+
 pub(crate) mod metrics {
     use router_env::{counter_metric, global_meter, histogram_metric, metrics_context, once_cell};
 
diff --git a/crates/router/src/core/admin.rs b/crates/router/src/core/admin.rs
index 820a0a965c6..0761f2b0ad5 100644
--- a/crates/router/src/core/admin.rs
+++ b/crates/router/src/core/admin.rs
@@ -8,7 +8,7 @@ use base64::Engine;
 use common_utils::{
     date_time,
     ext_traits::{AsyncExt, Encode, ValueExt},
-    id_type, pii,
+    id_type, pii, type_name,
     types::keymanager::{self as km_types, KeyManagerState},
 };
 use diesel_models::configs;
@@ -216,13 +216,15 @@ pub async fn create_merchant_account(
 
     let key_store = domain::MerchantKeyStore {
         merchant_id: merchant_id.clone(),
-        key: domain_types::encrypt(
+        key: domain_types::crypto_operation(
             key_manager_state,
-            key.to_vec().into(),
+            type_name!(domain::MerchantKeyStore),
+            domain_types::CryptoOperation::Encrypt(key.to_vec().into()),
             identifier.clone(),
             master_key,
         )
         .await
+        .and_then(|val| val.try_into_operation())
         .change_context(errors::ApiErrorResponse::InternalServerError)
         .attach_printable("Failed to decrypt data from key store")?,
         created_at: date_time::now(),
@@ -341,23 +343,29 @@ impl MerchantAccountCreateBridge for api::MerchantAccountCreate {
                     merchant_id: identifier.clone(),
                     merchant_name: self
                         .merchant_name
-                        .async_lift(|inner| {
-                            domain_types::encrypt_optional(
+                        .async_lift(|inner| async {
+                            domain_types::crypto_operation(
                                 &key_manager_state,
-                                inner,
+                                type_name!(domain::MerchantAccount),
+                                domain_types::CryptoOperation::EncryptOptional(inner),
                                 km_types::Identifier::Merchant(key_store.merchant_id.clone()),
                                 key.peek(),
                             )
+                            .await
+                            .and_then(|val| val.try_into_optionaloperation())
                         })
                         .await?,
                     merchant_details: merchant_details
-                        .async_lift(|inner| {
-                            domain_types::encrypt_optional(
+                        .async_lift(|inner| async {
+                            domain_types::crypto_operation(
                                 &key_manager_state,
-                                inner,
+                                type_name!(domain::MerchantAccount),
+                                domain_types::CryptoOperation::EncryptOptional(inner),
                                 km_types::Identifier::Merchant(key_store.merchant_id.clone()),
                                 key.peek(),
                             )
+                            .await
+                            .and_then(|val| val.try_into_optionaloperation())
                         })
                         .await?,
                     return_url: self.return_url.map(|a| a.to_string()),
@@ -646,23 +654,30 @@ impl MerchantAccountCreateBridge for api::MerchantAccountCreate {
                 domain::MerchantAccount::from(domain::MerchantAccountSetter {
                     id,
                     merchant_name: Some(
-                        domain_types::encrypt(
+                        domain_types::crypto_operation(
                             &key_manager_state,
-                            self.merchant_name
-                                .map(|merchant_name| merchant_name.into_inner()),
+                            type_name!(domain::MerchantAccount),
+                            domain_types::CryptoOperation::Encrypt(
+                                self.merchant_name
+                                    .map(|merchant_name| merchant_name.into_inner()),
+                            ),
                             identifier.clone(),
                             key.peek(),
                         )
-                        .await?,
+                        .await
+                        .and_then(|val| val.try_into_operation())?,
                     ),
                     merchant_details: merchant_details
-                        .async_lift(|inner| {
-                            domain_types::encrypt_optional(
+                        .async_lift(|inner| async {
+                            domain_types::crypto_operation(
                                 &key_manager_state,
-                                inner,
+                                type_name!(domain::MerchantAccount),
+                                domain_types::CryptoOperation::EncryptOptional(inner),
                                 identifier.clone(),
                                 key.peek(),
                             )
+                            .await
+                            .and_then(|val| val.try_into_optionaloperation())
                         })
                         .await?,
                     routing_algorithm: Some(serde_json::json!({
@@ -918,25 +933,31 @@ impl MerchantAccountUpdateBridge for api::MerchantAccountUpdate {
             merchant_name: self
                 .merchant_name
                 .map(Secret::new)
-                .async_lift(|inner| {
-                    domain_types::encrypt_optional(
+                .async_lift(|inner| async {
+                    domain_types::crypto_operation(
                         key_manager_state,
-                        inner,
+                        type_name!(storage::MerchantAccount),
+                        domain_types::CryptoOperation::EncryptOptional(inner),
                         identifier.clone(),
                         key,
                     )
+                    .await
+                    .and_then(|val| val.try_into_optionaloperation())
                 })
                 .await
                 .change_context(errors::ApiErrorResponse::InternalServerError)
                 .attach_printable("Unable to encrypt merchant name")?,
             merchant_details: merchant_details
-                .async_lift(|inner| {
-                    domain_types::encrypt_optional(
+                .async_lift(|inner| async {
+                    domain_types::crypto_operation(
                         key_manager_state,
-                        inner,
+                        type_name!(storage::MerchantAccount),
+                        domain_types::CryptoOperation::EncryptOptional(inner),
                         km_types::Identifier::Merchant(key_store.merchant_id.clone()),
                         key,
                     )
+                    .await
+                    .and_then(|val| val.try_into_optionaloperation())
                 })
                 .await
                 .change_context(errors::ApiErrorResponse::InternalServerError)
@@ -2006,13 +2027,16 @@ impl MerchantConnectorAccountUpdateBridge for api_models::admin::MerchantConnect
             connector_label: self.connector_label.clone(),
             connector_account_details: self
                 .connector_account_details
-                .async_lift(|inner| {
-                    domain_types::encrypt_optional(
+                .async_lift(|inner| async {
+                    domain_types::crypto_operation(
                         key_manager_state,
-                        inner,
+                        type_name!(storage::MerchantConnectorAccount),
+                        domai_types::CryptoOperation::EncryptOptional(inner),
                         km_types::Identifier::Merchant(key_store.merchant_id.clone()),
                         key_store.key.get_inner().peek(),
                     )
+                    .await
+                    .and_then(|val| val.try_into_optionaloperation())
                 })
                 .await
                 .change_context(errors::ApiErrorResponse::InternalServerError)
@@ -2141,13 +2165,16 @@ impl MerchantConnectorAccountUpdateBridge for api_models::admin::MerchantConnect
             connector_label: self.connector_label.clone(),
             connector_account_details: self
                 .connector_account_details
-                .async_lift(|inner| {
-                    domain_types::encrypt_optional(
+                .async_lift(|inner| async {
+                    domain_types::crypto_operation(
                         key_manager_state,
-                        inner,
+                        type_name!(storage::MerchantConnectorAccount),
+                        domain_types::CryptoOperation::EncryptOptional(inner),
                         km_types::Identifier::Merchant(key_store.merchant_id.clone()),
                         key_store.key.get_inner().peek(),
                     )
+                    .await
+                    .and_then(|val| val.try_into_optionaloperation())
                 })
                 .await
                 .change_context(errors::ApiErrorResponse::InternalServerError)
@@ -2268,17 +2295,19 @@ impl MerchantConnectorAccountCreateBridge for api::MerchantConnectorCreate {
             merchant_id: business_profile.merchant_id.clone(),
             connector_type: self.connector_type,
             connector_name: self.connector_name.to_string(),
-            connector_account_details: domain_types::encrypt(
+            connector_account_details: domain_types::crypto_operation(
                 key_manager_state,
-                self.connector_account_details.ok_or(
+                type_name!(domain::MerchantConnectorAccount),
+                domain_types::CryptoOperation::Encrypt(self.connector_account_details.ok_or(
                     errors::ApiErrorResponse::MissingRequiredField {
                         field_name: "connector_account_details",
                     },
-                )?,
+                )?),
                 identifier.clone(),
                 key_store.key.peek(),
             )
             .await
+            .and_then(|val| val.try_into_operation())
             .change_context(errors::ApiErrorResponse::InternalServerError)
             .attach_printable("Unable to encrypt connector account details")?,
             payment_methods_enabled,
@@ -2306,13 +2335,15 @@ impl MerchantConnectorAccountCreateBridge for api::MerchantConnectorCreate {
             status: connector_status,
             connector_wallets_details: helpers::get_encrypted_apple_pay_connector_wallets_details(state, &key_store, &self.metadata).await?,
             additional_merchant_data: if let Some(mcd) =  merchant_recipient_data {
-                Some(domain_types::encrypt(
+                Some(domain_types::crypto_operation(
                     key_manager_state,
-                    Secret::new(mcd),
+                    type_name!(domain::MerchantConnectorAccount),
+                    domain_types::CryptoOperation::Encrypt(Secret::new(mcd)),
                     identifier,
                     key_store.key.peek(),
                 )
                 .await
+                .and_then(|val| val.try_into_operation())
                 .change_context(errors::ApiErrorResponse::InternalServerError)
                 .attach_printable("Unable to encrypt additional_merchant_data")?)
             } else {
@@ -2434,17 +2465,19 @@ impl MerchantConnectorAccountCreateBridge for api::MerchantConnectorCreate {
             connector_type: self.connector_type,
             connector_name: self.connector_name.to_string(),
             merchant_connector_id: utils::generate_id(consts::ID_LENGTH, "mca"),
-            connector_account_details: domain_types::encrypt(
+            connector_account_details: domain_types::crypto_operation(
                 key_manager_state,
-                self.connector_account_details.ok_or(
+                type_name!(domain::MerchantConnectorAccount),
+                domain_types::CryptoOperation::Encrypt(self.connector_account_details.ok_or(
                     errors::ApiErrorResponse::MissingRequiredField {
                         field_name: "connector_account_details",
                     },
-                )?,
+                )?),
                 identifier.clone(),
                 key_store.key.peek(),
             )
             .await
+            .and_then(|val| val.try_into_operation())
             .change_context(errors::ApiErrorResponse::InternalServerError)
             .attach_printable("Unable to encrypt connector account details")?,
             payment_methods_enabled,
@@ -2475,13 +2508,15 @@ impl MerchantConnectorAccountCreateBridge for api::MerchantConnectorCreate {
             business_label: self.business_label.clone(),
             business_sub_label: self.business_sub_label.clone(),
             additional_merchant_data: if let Some(mcd) =  merchant_recipient_data {
-                Some(domain_types::encrypt(
+                Some(domain_types::crypto_operation(
                     key_manager_state,
-                    Secret::new(mcd),
+                    type_name!(domain::MerchantConnectorAccount),
+                    domain_types::CryptoOperation::Encrypt(Secret::new(mcd)),
                     identifier,
                     key_store.key.peek(),
                 )
                 .await
+                .and_then(|val| val.try_into_operation())
                 .change_context(errors::ApiErrorResponse::InternalServerError)
                 .attach_printable("Unable to encrypt additional_merchant_data")?)
             } else {
diff --git a/crates/router/src/core/apple_pay_certificates_migration.rs b/crates/router/src/core/apple_pay_certificates_migration.rs
index 8fe61f75ca2..44be8f33bbe 100644
--- a/crates/router/src/core/apple_pay_certificates_migration.rs
+++ b/crates/router/src/core/apple_pay_certificates_migration.rs
@@ -1,5 +1,5 @@
 use api_models::apple_pay_certificates_migration;
-use common_utils::{errors::CustomResult, types::keymanager::Identifier};
+use common_utils::{errors::CustomResult, type_name, types::keymanager::Identifier};
 use error_stack::ResultExt;
 use masking::{PeekInterface, Secret};
 
@@ -64,17 +64,19 @@ pub async fn apple_pay_certificates_migration(
                     })
                     .ok();
             if let Some(apple_pay_metadata) = connector_apple_pay_metadata {
-                let encrypted_apple_pay_metadata = domain_types::encrypt(
+                let encrypted_apple_pay_metadata = domain_types::crypto_operation(
                     &(&state).into(),
-                    Secret::new(
+                    type_name!(storage::MerchantConnectorAccount),
+                    domain_types::CryptoOperation::Encrypt(Secret::new(
                         serde_json::to_value(apple_pay_metadata)
                             .change_context(errors::ApiErrorResponse::InternalServerError)
                             .attach_printable("Failed to serialize apple pay metadata as JSON")?,
-                    ),
+                    )),
                     Identifier::Merchant(merchant_id.clone()),
                     key_store.key.get_inner().peek(),
                 )
                 .await
+                .and_then(|val| val.try_into_operation())
                 .change_context(errors::ApiErrorResponse::InternalServerError)
                 .attach_printable("Unable to encrypt connector apple pay metadata")?;
 
diff --git a/crates/router/src/core/customers.rs b/crates/router/src/core/customers.rs
index 73368cba0e4..69bf4052d70 100644
--- a/crates/router/src/core/customers.rs
+++ b/crates/router/src/core/customers.rs
@@ -4,13 +4,11 @@ use common_utils::{crypto::Encryptable, ext_traits::OptionExt, types::Descriptio
 use common_utils::{
     errors::ReportSwitchExt,
     ext_traits::AsyncExt,
-    id_type,
+    id_type, type_name,
     types::keymanager::{Identifier, KeyManagerState, ToEncryptable},
 };
 use error_stack::{report, ResultExt};
 #[cfg(all(any(feature = "v1", feature = "v2"), not(feature = "customer_v2")))]
-use hyperswitch_domain_models::type_encryption::encrypt;
-#[cfg(all(any(feature = "v1", feature = "v2"), not(feature = "customer_v2")))]
 use masking::{Secret, SwitchStrategy};
 use router_env::{instrument, tracing};
 
@@ -145,17 +143,21 @@ impl CustomerCreateBridge for customers::CustomerRequest {
             .encrypt_customer_address_and_set_to_db(db)
             .await?;
 
-        let encrypted_data = types::batch_encrypt(
+        let encrypted_data = types::crypto_operation(
             key_manager_state,
-            CustomerRequestWithEmail::to_encryptable(CustomerRequestWithEmail {
-                name: self.name.clone(),
-                email: self.email.clone(),
-                phone: self.phone.clone(),
-            }),
+            type_name!(domain::Customer),
+            types::CryptoOperation::BatchEncrypt(CustomerRequestWithEmail::to_encryptable(
+                CustomerRequestWithEmail {
+                    name: self.name.clone(),
+                    email: self.email.clone(),
+                    phone: self.phone.clone(),
+                },
+            )),
             Identifier::Merchant(key_store.merchant_id.clone()),
             key,
         )
         .await
+        .and_then(|val| val.try_into_batchoperation())
         .switch()
         .attach_printable("Failed while encrypting Customer")?;
 
@@ -227,17 +229,21 @@ impl CustomerCreateBridge for customers::CustomerRequest {
         let merchant_id = merchant_account.get_id().clone();
         let key = key_store.key.get_inner().peek();
 
-        let encrypted_data = types::batch_encrypt(
+        let encrypted_data = types::crypto_operation(
             key_state,
-            CustomerRequestWithEmail::to_encryptable(CustomerRequestWithEmail {
-                name: Some(self.name.clone()),
-                email: Some(self.email.clone()),
-                phone: self.phone.clone(),
-            }),
+            type_name!(domain::Customer),
+            types::CryptoOperation::BatchEncrypt(CustomerRequestWithEmail::to_encryptable(
+                CustomerRequestWithEmail {
+                    name: Some(self.name.clone()),
+                    email: Some(self.email.clone()),
+                    phone: self.phone.clone(),
+                },
+            )),
             Identifier::Merchant(key_store.merchant_id.clone()),
             key,
         )
         .await
+        .and_then(|val| val.try_into_batchoperation())
         .switch()
         .attach_printable("Failed while encrypting Customer")?;
 
@@ -508,13 +514,15 @@ pub async fn delete_customer(
 
     let key = key_store.key.get_inner().peek();
     let identifier = Identifier::Merchant(key_store.merchant_id.clone());
-    let redacted_encrypted_value: Encryptable<Secret<_>> = encrypt(
+    let redacted_encrypted_value: Encryptable<Secret<_>> = types::crypto_operation(
         key_manager_state,
-        REDACTED.to_string().into(),
+        type_name!(storage::Address),
+        types::CryptoOperation::Encrypt(REDACTED.to_string().into()),
         identifier.clone(),
         key,
     )
     .await
+    .and_then(|val| val.try_into_operation())
     .switch()?;
 
     let redacted_encrypted_email = Encryptable::new(
@@ -566,13 +574,15 @@ pub async fn delete_customer(
     let updated_customer = storage::CustomerUpdate::Update {
         name: Some(redacted_encrypted_value.clone()),
         email: Some(
-            encrypt(
+            types::crypto_operation(
                 key_manager_state,
-                REDACTED.to_string().into(),
+                type_name!(storage::Customer),
+                types::CryptoOperation::Encrypt(REDACTED.to_string().into()),
                 identifier,
                 key,
             )
             .await
+            .and_then(|val| val.try_into_operation())
             .switch()?,
         ),
         phone: Box::new(Some(redacted_encrypted_value.clone())),
@@ -697,17 +707,21 @@ pub async fn update_customer(
             None => None,
         }
     };
-    let encrypted_data = types::batch_encrypt(
+    let encrypted_data = types::crypto_operation(
         &(&state).into(),
-        CustomerRequestWithEmail::to_encryptable(CustomerRequestWithEmail {
-            name: update_customer.name.clone(),
-            email: update_customer.email.clone(),
-            phone: update_customer.phone.clone(),
-        }),
+        type_name!(domain::Customer),
+        types::CryptoOperation::BatchEncrypt(CustomerRequestWithEmail::to_encryptable(
+            CustomerRequestWithEmail {
+                name: update_customer.name.clone(),
+                email: update_customer.email.clone(),
+                phone: update_customer.phone.clone(),
+            },
+        )),
         Identifier::Merchant(key_store.merchant_id.clone()),
         key,
     )
     .await
+    .and_then(|val| val.try_into_batchoperation())
     .switch()?;
     let encryptable_customer = CustomerRequestWithEmail::from_encryptable(encrypted_data)
         .change_context(errors::CustomersErrorResponse::InternalServerError)?;
diff --git a/crates/router/src/core/payment_methods/cards.rs b/crates/router/src/core/payment_methods/cards.rs
index a7a240339ee..9f13530fbd5 100644
--- a/crates/router/src/core/payment_methods/cards.rs
+++ b/crates/router/src/core/payment_methods/cards.rs
@@ -25,7 +25,7 @@ use common_utils::{
     crypto::Encryptable,
     encryption::Encryption,
     ext_traits::{AsyncExt, Encode, StringExt, ValueExt},
-    generate_id, id_type,
+    generate_id, id_type, type_name,
     types::{
         keymanager::{Identifier, KeyManagerState},
         MinorUnit,
@@ -76,7 +76,7 @@ use crate::{
     services,
     types::{
         api::{self, routing as routing_types, PaymentMethodCreateExt},
-        domain::{self, types::decrypt_optional},
+        domain,
         storage::{self, enums, PaymentMethodListContext, PaymentTokenData},
         transformers::{ForeignFrom, ForeignTryFrom},
     },
@@ -1219,13 +1219,18 @@ pub async fn update_customer_payment_method(
         }
 
         // Fetch the existing payment method data from db
-        let existing_card_data = decrypt_optional::<serde_json::Value, masking::WithType>(
+        let existing_card_data = domain::types::crypto_operation::<
+            serde_json::Value,
+            masking::WithType,
+        >(
             &(&state).into(),
-            pm.payment_method_data.clone(),
+            type_name!(payment_method::PaymentMethod),
+            domain::types::CryptoOperation::DecryptOptional(pm.payment_method_data.clone()),
             Identifier::Merchant(key_store.merchant_id.clone()),
             key_store.key.get_inner().peek(),
         )
         .await
+        .and_then(|val| val.try_into_optionaloperation())
         .change_context(errors::ApiErrorResponse::InternalServerError)
         .attach_printable("Failed to decrypt card details")?
         .map(|x| x.into_inner().expose())
@@ -1479,13 +1484,16 @@ pub async fn add_bank_to_locker(
                 let secret: Secret<String> = Secret::new(v.to_string());
                 secret
             })
-            .async_lift(|inner| {
-                domain::types::encrypt_optional(
+            .async_lift(|inner| async {
+                domain::types::crypto_operation(
                     &key_manager_state,
-                    inner,
+                    type_name!(payment_method::PaymentMethod),
+                    domain::types::CryptoOperation::EncryptOptional(inner),
                     Identifier::Merchant(key_store.merchant_id.clone()),
                     key,
                 )
+                .await
+                .and_then(|val| val.try_into_optionaloperation())
             })
             .await
     }
@@ -1693,13 +1701,17 @@ pub async fn decode_and_decrypt_locker_data(
         .change_context(errors::VaultError::ResponseDeserializationFailed)
         .attach_printable("Failed to decode hex string into bytes")?;
     // Decrypt
-    decrypt_optional(
+    domain::types::crypto_operation(
         &state.into(),
-        Some(Encryption::new(decoded_bytes.into())),
+        type_name!(payment_method::PaymentMethod),
+        domain::types::CryptoOperation::DecryptOptional(Some(Encryption::new(
+            decoded_bytes.into(),
+        ))),
         Identifier::Merchant(key_store.merchant_id.clone()),
         key,
     )
     .await
+    .and_then(|val| val.try_into_optionaloperation())
     .change_context(errors::VaultError::FetchPaymentMethodFailed)?
     .map_or(
         Err(report!(errors::VaultError::FetchPaymentMethodFailed)),
@@ -4505,13 +4517,15 @@ where
 {
     let key = key_store.key.get_inner().peek();
     let identifier = Identifier::Merchant(key_store.merchant_id.clone());
-    let decrypted_data = decrypt_optional::<serde_json::Value, masking::WithType>(
+    let decrypted_data = domain::types::crypto_operation::<serde_json::Value, masking::WithType>(
         &state.into(),
-        data,
+        type_name!(T),
+        domain::types::CryptoOperation::DecryptOptional(data),
         identifier,
         key,
     )
     .await
+    .and_then(|val| val.try_into_optionaloperation())
     .change_context(errors::StorageError::DecryptionError)
     .change_context(errors::ApiErrorResponse::InternalServerError)
     .attach_printable("unable to decrypt data")?;
@@ -4531,13 +4545,15 @@ pub async fn get_card_details_with_locker_fallback(
 ) -> errors::RouterResult<Option<api::CardDetailFromLocker>> {
     let key = key_store.key.get_inner().peek();
     let identifier = Identifier::Merchant(key_store.merchant_id.clone());
-    let card_decrypted = decrypt_optional::<serde_json::Value, masking::WithType>(
+    let card_decrypted = domain::types::crypto_operation::<serde_json::Value, masking::WithType>(
         &state.into(),
-        pm.payment_method_data.clone(),
+        type_name!(payment_method::PaymentMethod),
+        domain::types::CryptoOperation::DecryptOptional(pm.payment_method_data.clone()),
         identifier,
         key,
     )
     .await
+    .and_then(|val| val.try_into_optionaloperation())
     .change_context(errors::StorageError::DecryptionError)
     .attach_printable("unable to decrypt card details")
     .ok()
@@ -4567,13 +4583,15 @@ pub async fn get_card_details_without_locker_fallback(
 ) -> errors::RouterResult<api::CardDetailFromLocker> {
     let key = key_store.key.get_inner().peek();
     let identifier = Identifier::Merchant(key_store.merchant_id.clone());
-    let card_decrypted = decrypt_optional::<serde_json::Value, masking::WithType>(
+    let card_decrypted = domain::types::crypto_operation::<serde_json::Value, masking::WithType>(
         &state.into(),
-        pm.payment_method_data.clone(),
+        type_name!(payment_method::PaymentMethod),
+        domain::types::CryptoOperation::DecryptOptional(pm.payment_method_data.clone()),
         identifier,
         key,
     )
     .await
+    .and_then(|val| val.try_into_optionaloperation())
     .change_context(errors::StorageError::DecryptionError)
     .attach_printable("unable to decrypt card details")
     .ok()
@@ -4642,26 +4660,29 @@ async fn get_masked_bank_details(
 ) -> errors::RouterResult<Option<MaskedBankDetails>> {
     let key = key_store.key.get_inner().peek();
     let identifier = Identifier::Merchant(key_store.merchant_id.clone());
-    let payment_method_data = decrypt_optional::<serde_json::Value, masking::WithType>(
-        &state.into(),
-        pm.payment_method_data.clone(),
-        identifier,
-        key,
-    )
-    .await
-    .change_context(errors::StorageError::DecryptionError)
-    .change_context(errors::ApiErrorResponse::InternalServerError)
-    .attach_printable("unable to decrypt bank details")?
-    .map(|x| x.into_inner().expose())
-    .map(
-        |v| -> Result<PaymentMethodsData, error_stack::Report<errors::ApiErrorResponse>> {
-            v.parse_value::<PaymentMethodsData>("PaymentMethodsData")
-                .change_context(errors::StorageError::DeserializationFailed)
-                .change_context(errors::ApiErrorResponse::InternalServerError)
-                .attach_printable("Failed to deserialize Payment Method Auth config")
-        },
-    )
-    .transpose()?;
+    let payment_method_data =
+        domain::types::crypto_operation::<serde_json::Value, masking::WithType>(
+            &state.into(),
+            type_name!(payment_method::PaymentMethod),
+            domain::types::CryptoOperation::DecryptOptional(pm.payment_method_data.clone()),
+            identifier,
+            key,
+        )
+        .await
+        .and_then(|val| val.try_into_optionaloperation())
+        .change_context(errors::StorageError::DecryptionError)
+        .change_context(errors::ApiErrorResponse::InternalServerError)
+        .attach_printable("unable to decrypt bank details")?
+        .map(|x| x.into_inner().expose())
+        .map(
+            |v| -> Result<PaymentMethodsData, error_stack::Report<errors::ApiErrorResponse>> {
+                v.parse_value::<PaymentMethodsData>("PaymentMethodsData")
+                    .change_context(errors::StorageError::DeserializationFailed)
+                    .change_context(errors::ApiErrorResponse::InternalServerError)
+                    .attach_printable("Failed to deserialize Payment Method Auth config")
+            },
+        )
+        .transpose()?;
 
     match payment_method_data {
         Some(pmd) => match pmd {
@@ -4682,26 +4703,29 @@ async fn get_bank_account_connector_details(
 ) -> errors::RouterResult<Option<BankAccountTokenData>> {
     let key = key_store.key.get_inner().peek();
     let identifier = Identifier::Merchant(key_store.merchant_id.clone());
-    let payment_method_data = decrypt_optional::<serde_json::Value, masking::WithType>(
-        &state.into(),
-        pm.payment_method_data.clone(),
-        identifier,
-        key,
-    )
-    .await
-    .change_context(errors::StorageError::DecryptionError)
-    .change_context(errors::ApiErrorResponse::InternalServerError)
-    .attach_printable("unable to decrypt bank details")?
-    .map(|x| x.into_inner().expose())
-    .map(
-        |v| -> Result<PaymentMethodsData, error_stack::Report<errors::ApiErrorResponse>> {
-            v.parse_value::<PaymentMethodsData>("PaymentMethodsData")
-                .change_context(errors::StorageError::DeserializationFailed)
-                .change_context(errors::ApiErrorResponse::InternalServerError)
-                .attach_printable("Failed to deserialize Payment Method Auth config")
-        },
-    )
-    .transpose()?;
+    let payment_method_data =
+        domain::types::crypto_operation::<serde_json::Value, masking::WithType>(
+            &state.into(),
+            type_name!(payment_method::PaymentMethod),
+            domain::types::CryptoOperation::DecryptOptional(pm.payment_method_data.clone()),
+            identifier,
+            key,
+        )
+        .await
+        .and_then(|val| val.try_into_optionaloperation())
+        .change_context(errors::StorageError::DecryptionError)
+        .change_context(errors::ApiErrorResponse::InternalServerError)
+        .attach_printable("unable to decrypt bank details")?
+        .map(|x| x.into_inner().expose())
+        .map(
+            |v| -> Result<PaymentMethodsData, error_stack::Report<errors::ApiErrorResponse>> {
+                v.parse_value::<PaymentMethodsData>("PaymentMethodsData")
+                    .change_context(errors::StorageError::DeserializationFailed)
+                    .change_context(errors::ApiErrorResponse::InternalServerError)
+                    .attach_printable("Failed to deserialize Payment Method Auth config")
+            },
+        )
+        .transpose()?;
 
     match payment_method_data {
         Some(pmd) => match pmd {
@@ -5125,11 +5149,17 @@ where
 
     let secret_data = Secret::<_, masking::WithType>::new(encoded_data);
 
-    let encrypted_data =
-        domain::types::encrypt(&key_manager_state, secret_data, identifier.clone(), key)
-            .await
-            .change_context(errors::StorageError::EncryptionError)
-            .attach_printable("Unable to encrypt data")?;
+    let encrypted_data = domain::types::crypto_operation(
+        &key_manager_state,
+        type_name!(payment_method::PaymentMethod),
+        domain::types::CryptoOperation::Encrypt(secret_data),
+        identifier.clone(),
+        key,
+    )
+    .await
+    .and_then(|val| val.try_into_operation())
+    .change_context(errors::StorageError::EncryptionError)
+    .attach_printable("Unable to encrypt data")?;
 
     Ok(encrypted_data)
 }
diff --git a/crates/router/src/core/payments/helpers.rs b/crates/router/src/core/payments/helpers.rs
index 6b39ec672e4..c3f7b25b0c9 100644
--- a/crates/router/src/core/payments/helpers.rs
+++ b/crates/router/src/core/payments/helpers.rs
@@ -11,7 +11,7 @@ use common_enums::ConnectorType;
 use common_utils::{
     crypto::Encryptable,
     ext_traits::{AsyncExt, ByteSliceExt, Encode, ValueExt},
-    fp_utils, generate_id, id_type, pii,
+    fp_utils, generate_id, id_type, pii, type_name,
     types::{
         keymanager::{Identifier, KeyManagerState, ToEncryptable},
         MinorUnit,
@@ -166,20 +166,24 @@ pub async fn create_or_update_address_for_payment_by_request(
     Ok(match address_id {
         Some(id) => match req_address {
             Some(address) => {
-                let encrypted_data = types::batch_encrypt(
+                let encrypted_data = types::crypto_operation(
                     &session_state.into(),
-                    AddressDetailsWithPhone::to_encryptable(AddressDetailsWithPhone {
-                        address: address.address.clone(),
-                        phone_number: address
-                            .phone
-                            .as_ref()
-                            .and_then(|phone| phone.number.clone()),
-                        email: address.email.clone(),
-                    }),
+                    type_name!(domain::Address),
+                    types::CryptoOperation::BatchEncrypt(AddressDetailsWithPhone::to_encryptable(
+                        AddressDetailsWithPhone {
+                            address: address.address.clone(),
+                            phone_number: address
+                                .phone
+                                .as_ref()
+                                .and_then(|phone| phone.number.clone()),
+                            email: address.email.clone(),
+                        },
+                    )),
                     Identifier::Merchant(merchant_key_store.merchant_id.clone()),
                     key,
                 )
                 .await
+                .and_then(|val| val.try_into_batchoperation())
                 .change_context(errors::ApiErrorResponse::InternalServerError)
                 .attach_printable("Failed while encrypting address")?;
                 let encryptable_address = AddressDetailsWithPhone::from_encryptable(encrypted_data)
@@ -353,20 +357,24 @@ pub async fn get_domain_address(
 ) -> CustomResult<domain::Address, common_utils::errors::CryptoError> {
     async {
         let address_details = &address.address.as_ref();
-        let encrypted_data = types::batch_encrypt(
+        let encrypted_data = types::crypto_operation(
             &session_state.into(),
-            AddressDetailsWithPhone::to_encryptable(AddressDetailsWithPhone {
-                address: address_details.cloned(),
-                phone_number: address
-                    .phone
-                    .as_ref()
-                    .and_then(|phone| phone.number.clone()),
-                email: address.email.clone(),
-            }),
+            type_name!(domain::Address),
+            types::CryptoOperation::BatchEncrypt(AddressDetailsWithPhone::to_encryptable(
+                AddressDetailsWithPhone {
+                    address: address_details.cloned(),
+                    phone_number: address
+                        .phone
+                        .as_ref()
+                        .and_then(|phone| phone.number.clone()),
+                    email: address.email.clone(),
+                },
+            )),
             Identifier::Merchant(merchant_id.to_owned()),
             key,
         )
-        .await?;
+        .await
+        .and_then(|val| val.try_into_batchoperation())?;
         let encryptable_address = AddressDetailsWithPhone::from_encryptable(encrypted_data)
             .change_context(common_utils::errors::CryptoError::EncodingFailed)?;
         Ok(domain::Address {
@@ -1645,17 +1653,21 @@ pub async fn create_customer_if_not_exist<'a, F: Clone, R>(
                 )
                 .await?;
             let key = key_store.key.get_inner().peek();
-            let encrypted_data = types::batch_encrypt(
+            let encrypted_data = types::crypto_operation(
                 key_manager_state,
-                CustomerRequestWithEmail::to_encryptable(CustomerRequestWithEmail {
-                    name: request_customer_details.name.clone(),
-                    email: request_customer_details.email.clone(),
-                    phone: request_customer_details.phone.clone(),
-                }),
+                type_name!(domain::Customer),
+                types::CryptoOperation::BatchEncrypt(CustomerRequestWithEmail::to_encryptable(
+                    CustomerRequestWithEmail {
+                        name: request_customer_details.name.clone(),
+                        email: request_customer_details.email.clone(),
+                        phone: request_customer_details.phone.clone(),
+                    },
+                )),
                 Identifier::Merchant(key_store.merchant_id.clone()),
                 key,
             )
             .await
+            .and_then(|val| val.try_into_batchoperation())
             .change_context(errors::StorageError::SerializationFailed)
             .attach_printable("Failed while encrypting Customer while Update")?;
             let encryptable_customer = CustomerRequestWithEmail::from_encryptable(encrypted_data)
@@ -4186,13 +4198,16 @@ pub async fn get_encrypted_apple_pay_connector_wallets_details(
         .map(masking::Secret::new);
     let key_manager_state: KeyManagerState = state.into();
     let encrypted_connector_apple_pay_details = connector_apple_pay_details
-        .async_lift(|wallets_details| {
-            types::encrypt_optional(
+        .async_lift(|wallets_details| async {
+            types::crypto_operation(
                 &key_manager_state,
-                wallets_details,
+                type_name!(domain::MerchantConnectorAccount),
+                types::CryptoOperation::EncryptOptional(wallets_details),
                 Identifier::Merchant(key_store.merchant_id.clone()),
                 key_store.key.get_inner().peek(),
             )
+            .await
+            .and_then(|val| val.try_into_optionaloperation())
         })
         .await
         .change_context(errors::ApiErrorResponse::InternalServerError)
diff --git a/crates/router/src/core/payments/operations/payment_confirm.rs b/crates/router/src/core/payments/operations/payment_confirm.rs
index 318a2e0373b..ed3e4b2c235 100644
--- a/crates/router/src/core/payments/operations/payment_confirm.rs
+++ b/crates/router/src/core/payments/operations/payment_confirm.rs
@@ -9,6 +9,7 @@ use api_models::{
 use async_trait::async_trait;
 use common_utils::{
     ext_traits::{AsyncExt, Encode, StringExt, ValueExt},
+    type_name,
     types::keymanager::Identifier,
 };
 use error_stack::{report, ResultExt};
@@ -39,7 +40,10 @@ use crate::{
     types::{
         self,
         api::{self, ConnectorCallType, PaymentIdTypeExt},
-        domain::{self, types::decrypt_optional},
+        domain::{
+            self,
+            types::{crypto_operation, CryptoOperation},
+        },
         storage::{self, enums as storage_enums},
     },
     utils::{self, OptionExt},
@@ -1084,13 +1088,15 @@ impl<F: Clone> UpdateTracker<F, PaymentData<F>, api::PaymentsRequest> for Paymen
             let key = key_store.key.get_inner().peek();
 
             let card_detail_from_locker: Option<api::CardDetailFromLocker> =
-                decrypt_optional::<serde_json::Value, masking::WithType>(
+                crypto_operation::<serde_json::Value, masking::WithType>(
                     key_manager_state,
-                    pm.payment_method_data.clone(),
+                    type_name!(storage::PaymentMethod),
+                    CryptoOperation::DecryptOptional(pm.payment_method_data.clone()),
                     Identifier::Merchant(key_store.merchant_id.clone()),
                     key,
                 )
                 .await
+                .and_then(|val| val.try_into_optionaloperation())
                 .change_context(errors::StorageError::DecryptionError)
                 .attach_printable("unable to decrypt card details")
                 .ok()
diff --git a/crates/router/src/core/payments/operations/payment_create.rs b/crates/router/src/core/payments/operations/payment_create.rs
index 94eddff25d4..4e45b184ed0 100644
--- a/crates/router/src/core/payments/operations/payment_create.rs
+++ b/crates/router/src/core/payments/operations/payment_create.rs
@@ -6,6 +6,7 @@ use api_models::{
 use async_trait::async_trait;
 use common_utils::{
     ext_traits::{AsyncExt, Encode, ValueExt},
+    type_name,
     types::{keymanager::Identifier, MinorUnit},
 };
 use diesel_models::{ephemeral_key, PaymentMethod};
@@ -13,7 +14,7 @@ use error_stack::{self, ResultExt};
 use hyperswitch_domain_models::{
     mandates::{MandateData, MandateDetails},
     payments::{payment_attempt::PaymentAttempt, payment_intent::CustomerData},
-    type_encryption::decrypt_optional,
+    type_encryption::{crypto_operation, CryptoOperation},
 };
 use masking::{ExposeInterface, PeekInterface, Secret};
 use router_derive::PaymentOperation;
@@ -865,13 +866,15 @@ impl PaymentCreate {
             additional_pm_data = payment_method_info
                 .as_ref()
                 .async_map(|pm_info| async {
-                    decrypt_optional::<serde_json::Value, masking::WithType>(
+                    crypto_operation::<serde_json::Value, masking::WithType>(
                         &state.into(),
-                        pm_info.payment_method_data.clone(),
+                        type_name!(PaymentMethod),
+                        CryptoOperation::DecryptOptional(pm_info.payment_method_data.clone()),
                         Identifier::Merchant(key_store.merchant_id.clone()),
                         key_store.key.get_inner().peek(),
                     )
                     .await
+                    .and_then(|val| val.try_into_optionaloperation())
                     .map_err(|err| logger::error!("Failed to decrypt card details: {:?}", err))
                     .ok()
                     .flatten()
diff --git a/crates/router/src/core/payouts/helpers.rs b/crates/router/src/core/payouts/helpers.rs
index c4010490c20..6b0f2026472 100644
--- a/crates/router/src/core/payouts/helpers.rs
+++ b/crates/router/src/core/payouts/helpers.rs
@@ -5,7 +5,7 @@ use common_utils::{
     encryption::Encryption,
     errors::CustomResult,
     ext_traits::{AsyncExt, StringExt},
-    fp_utils, id_type,
+    fp_utils, id_type, type_name,
     types::{
         keymanager::{Identifier, KeyManagerState},
         MinorUnit,
@@ -15,7 +15,7 @@ use common_utils::{
 use common_utils::{generate_customer_id_of_default_length, types::keymanager::ToEncryptable};
 use error_stack::{report, ResultExt};
 #[cfg(all(any(feature = "v1", feature = "v2"), not(feature = "customer_v2")))]
-use hyperswitch_domain_models::type_encryption::batch_encrypt;
+use hyperswitch_domain_models::type_encryption::{crypto_operation, CryptoOperation};
 use masking::{PeekInterface, Secret};
 use router_env::logger;
 
@@ -39,10 +39,7 @@ use crate::{
     services,
     types::{
         api::{self, enums as api_enums},
-        domain::{
-            self,
-            types::{self as domain_types, AsyncLift},
-        },
+        domain::{self, types::AsyncLift},
         storage,
         transformers::ForeignFrom,
     },
@@ -252,13 +249,16 @@ pub async fn save_payout_data_to_locker(
                             let secret: Secret<String> = Secret::new(v.to_string());
                             secret
                         })
-                        .async_lift(|inner| {
-                            domain_types::encrypt_optional(
+                        .async_lift(|inner| async {
+                            crypto_operation(
                                 &key_manager_state,
-                                inner,
+                                type_name!(storage::PaymentMethod),
+                                CryptoOperation::EncryptOptional(inner),
                                 Identifier::Merchant(key_store.merchant_id.clone()),
                                 key,
                             )
+                            .await
+                            .and_then(|val| val.try_into_optionaloperation())
                         })
                         .await
                 }
@@ -644,17 +644,21 @@ pub async fn get_or_create_customer_details(
     {
         Some(customer) => Ok(Some(customer)),
         None => {
-            let encrypted_data = batch_encrypt(
+            let encrypted_data = crypto_operation(
                 &state.into(),
-                CustomerRequestWithEmail::to_encryptable(CustomerRequestWithEmail {
-                    name: customer_details.name.clone(),
-                    email: customer_details.email.clone(),
-                    phone: customer_details.phone.clone(),
-                }),
+                type_name!(domain::Customer),
+                CryptoOperation::BatchEncrypt(CustomerRequestWithEmail::to_encryptable(
+                    CustomerRequestWithEmail {
+                        name: customer_details.name.clone(),
+                        email: customer_details.email.clone(),
+                        phone: customer_details.phone.clone(),
+                    },
+                )),
                 Identifier::Merchant(key_store.merchant_id.clone()),
                 key,
             )
             .await
+            .and_then(|val| val.try_into_batchoperation())
             .change_context(errors::ApiErrorResponse::InternalServerError)?;
             let encryptable_customer =
                 CustomerRequestWithEmail::from_encryptable(encrypted_data)
diff --git a/crates/router/src/core/pm_auth.rs b/crates/router/src/core/pm_auth.rs
index 8d237da5ed5..fae690732e0 100644
--- a/crates/router/src/core/pm_auth.rs
+++ b/crates/router/src/core/pm_auth.rs
@@ -14,7 +14,7 @@ use common_utils::{
     consts,
     crypto::{HmacSha256, SignMessage},
     ext_traits::AsyncExt,
-    generate_id,
+    generate_id, type_name,
     types::{self as util_types, keymanager::Identifier, AmountConvertor},
 };
 use error_stack::ResultExt;
@@ -45,7 +45,7 @@ use crate::{
     services::{pm_auth as pm_auth_services, ApplicationResponse},
     types::{
         self,
-        domain::{self, types::decrypt_optional},
+        domain::{self, types::crypto_operation},
         storage,
         transformers::ForeignTryFrom,
     },
@@ -349,13 +349,15 @@ async fn store_bank_details_in_payment_methods(
 
     for pm in payment_methods {
         if pm.payment_method == Some(enums::PaymentMethod::BankDebit) {
-            let bank_details_pm_data = decrypt_optional::<serde_json::Value, masking::WithType>(
+            let bank_details_pm_data = crypto_operation::<serde_json::Value, masking::WithType>(
                 &(&state).into(),
-                pm.payment_method_data.clone(),
+                type_name!(storage::PaymentMethod),
+                domain::types::CryptoOperation::DecryptOptional(pm.payment_method_data.clone()),
                 Identifier::Merchant(key_store.merchant_id.clone()),
                 key,
             )
             .await
+            .and_then(|val| val.try_into_optionaloperation())
             .change_context(ApiErrorResponse::InternalServerError)
             .attach_printable("unable to decrypt bank account details")?
             .map(|x| x.into_inner().expose())
diff --git a/crates/router/src/core/user.rs b/crates/router/src/core/user.rs
index 457a71dff8b..042e2c19e7c 100644
--- a/crates/router/src/core/user.rs
+++ b/crates/router/src/core/user.rs
@@ -4,7 +4,7 @@ use api_models::{
     payments::RedirectionResponse,
     user::{self as user_api, InviteMultipleUserResponse},
 };
-use common_utils::types::keymanager::Identifier;
+use common_utils::{type_name, types::keymanager::Identifier};
 #[cfg(feature = "email")]
 use diesel_models::user_role::UserRoleUpdate;
 use diesel_models::{
@@ -1929,13 +1929,15 @@ pub async fn update_totp(
                 totp_status: None,
                 totp_secret: Some(
                     // TODO: Impl conversion trait for User and move this there
-                    domain::types::encrypt::<String, masking::WithType>(
+                    domain::types::crypto_operation::<String, masking::WithType>(
                         &(&state).into(),
-                        totp.get_secret_base32().into(),
+                        type_name!(storage_user::User),
+                        domain::types::CryptoOperation::Encrypt(totp.get_secret_base32().into()),
                         Identifier::User(key_store.user_id.clone()),
                         key_store.key.peek(),
                     )
                     .await
+                    .and_then(|val| val.try_into_operation())
                     .change_context(UserErrors::InternalServerError)?
                     .into(),
                 ),
diff --git a/crates/router/src/core/webhooks/outgoing.rs b/crates/router/src/core/webhooks/outgoing.rs
index 416075050b3..25c93f8465e 100644
--- a/crates/router/src/core/webhooks/outgoing.rs
+++ b/crates/router/src/core/webhooks/outgoing.rs
@@ -4,10 +4,12 @@ use api_models::{
     webhook_events::{OutgoingWebhookRequestContent, OutgoingWebhookResponseContent},
     webhooks,
 };
-use common_utils::{ext_traits::Encode, request::RequestContent, types::keymanager::Identifier};
+use common_utils::{
+    ext_traits::Encode, request::RequestContent, type_name, types::keymanager::Identifier,
+};
 use diesel_models::process_tracker::business_status;
 use error_stack::{report, ResultExt};
-use hyperswitch_domain_models::type_encryption::decrypt_optional;
+use hyperswitch_domain_models::type_encryption::{crypto_operation, CryptoOperation};
 use masking::{ExposeInterface, Mask, PeekInterface, Secret};
 use router_env::{
     instrument,
@@ -31,8 +33,7 @@ use crate::{
     routes::{app::SessionStateInfo, SessionState},
     services,
     types::{
-        api,
-        domain::{self, types as domain_types},
+        api, domain,
         storage::{self, enums},
         transformers::ForeignFrom,
     },
@@ -113,17 +114,21 @@ pub(crate) async fn create_event_and_trigger_outgoing_webhook(
         idempotent_event_id: Some(idempotent_event_id.clone()),
         initial_attempt_id: Some(event_id.clone()),
         request: Some(
-            domain_types::encrypt(
+            crypto_operation(
                 key_manager_state,
-                request_content
-                    .encode_to_string_of_json()
-                    .change_context(errors::ApiErrorResponse::WebhookProcessingFailure)
-                    .attach_printable("Failed to encode outgoing webhook request content")
-                    .map(Secret::new)?,
+                type_name!(domain::Event),
+                CryptoOperation::Encrypt(
+                    request_content
+                        .encode_to_string_of_json()
+                        .change_context(errors::ApiErrorResponse::WebhookProcessingFailure)
+                        .attach_printable("Failed to encode outgoing webhook request content")
+                        .map(Secret::new)?,
+                ),
                 Identifier::Merchant(merchant_key_store.merchant_id.clone()),
                 merchant_key_store.key.get_inner().peek(),
             )
             .await
+            .and_then(|val| val.try_into_operation())
             .change_context(errors::ApiErrorResponse::WebhookProcessingFailure)
             .attach_printable("Failed to encrypt outgoing webhook request content")?,
         ),
@@ -570,15 +575,19 @@ pub(crate) async fn get_outgoing_webhook_request(
 
         let transformed_outgoing_webhook = WebhookType::from(outgoing_webhook);
         let payment_response_hash_key = business_profile.payment_response_hash_key.clone();
-        let custom_headers = decrypt_optional::<serde_json::Value, masking::WithType>(
+        let custom_headers = crypto_operation::<serde_json::Value, masking::WithType>(
             &state.into(),
-            business_profile
-                .outgoing_webhook_custom_http_headers
-                .clone(),
+            type_name!(domain::Event),
+            CryptoOperation::DecryptOptional(
+                business_profile
+                    .outgoing_webhook_custom_http_headers
+                    .clone(),
+            ),
             Identifier::Merchant(key_store.merchant_id.clone()),
             key_store.key.get_inner().peek(),
         )
         .await
+        .and_then(|val| val.try_into_optionaloperation())
         .change_context(errors::WebhooksFlowError::OutgoingWebhookEncodingFailed)
         .attach_printable("Failed to decrypt outgoing webhook custom HTTP headers")?
         .map(|decrypted_value| {
@@ -660,18 +669,22 @@ async fn update_event_if_client_error(
     let event_update = domain::EventUpdate::UpdateResponse {
         is_webhook_notified,
         response: Some(
-            domain_types::encrypt(
+            crypto_operation(
                 key_manager_state,
-                response_to_store
-                    .encode_to_string_of_json()
-                    .change_context(
-                        errors::WebhooksFlowError::OutgoingWebhookResponseEncodingFailed,
-                    )
-                    .map(Secret::new)?,
+                type_name!(domain::Event),
+                CryptoOperation::Encrypt(
+                    response_to_store
+                        .encode_to_string_of_json()
+                        .change_context(
+                            errors::WebhooksFlowError::OutgoingWebhookResponseEncodingFailed,
+                        )
+                        .map(Secret::new)?,
+                ),
                 Identifier::Merchant(merchant_key_store.merchant_id.clone()),
                 merchant_key_store.key.get_inner().peek(),
             )
             .await
+            .and_then(|val| val.try_into_operation())
             .change_context(errors::WebhooksFlowError::WebhookEventUpdationFailed)
             .attach_printable("Failed to encrypt outgoing webhook response content")?,
         ),
@@ -778,18 +791,22 @@ async fn update_event_in_storage(
     let event_update = domain::EventUpdate::UpdateResponse {
         is_webhook_notified,
         response: Some(
-            domain_types::encrypt(
+            crypto_operation(
                 key_manager_state,
-                response_to_store
-                    .encode_to_string_of_json()
-                    .change_context(
-                        errors::WebhooksFlowError::OutgoingWebhookResponseEncodingFailed,
-                    )
-                    .map(Secret::new)?,
+                type_name!(domain::Event),
+                CryptoOperation::Encrypt(
+                    response_to_store
+                        .encode_to_string_of_json()
+                        .change_context(
+                            errors::WebhooksFlowError::OutgoingWebhookResponseEncodingFailed,
+                        )
+                        .map(Secret::new)?,
+                ),
                 Identifier::Merchant(merchant_key_store.merchant_id.clone()),
                 merchant_key_store.key.get_inner().peek(),
             )
             .await
+            .and_then(|val| val.try_into_operation())
             .change_context(errors::WebhooksFlowError::WebhookEventUpdationFailed)
             .attach_printable("Failed to encrypt outgoing webhook response content")?,
         ),
diff --git a/crates/router/src/db/events.rs b/crates/router/src/db/events.rs
index 0cecea9c627..3b0f789cf04 100644
--- a/crates/router/src/db/events.rs
+++ b/crates/router/src/db/events.rs
@@ -770,7 +770,7 @@ impl EventInterface for MockDb {
 mod tests {
     use std::sync::Arc;
 
-    use common_utils::types::keymanager::Identifier;
+    use common_utils::{type_name, types::keymanager::Identifier};
     use diesel_models::{enums, events::EventMetadata};
     use time::macros::datetime;
 
@@ -818,13 +818,17 @@ mod tests {
                 key_manager_state,
                 domain::MerchantKeyStore {
                     merchant_id: merchant_id.clone(),
-                    key: domain::types::encrypt(
+                    key: domain::types::crypto_operation(
                         key_manager_state,
-                        services::generate_aes256_key().unwrap().to_vec().into(),
+                        type_name!(domain::MerchantKeyStore),
+                        domain::types::CryptoOperation::Encrypt(
+                            services::generate_aes256_key().unwrap().to_vec().into(),
+                        ),
                         Identifier::Merchant(merchant_id.to_owned()),
                         master_key,
                     )
                     .await
+                    .and_then(|val| val.try_into_operation())
                     .unwrap(),
                     created_at: datetime!(2023-02-01 0:00),
                 },
diff --git a/crates/router/src/db/merchant_connector_account.rs b/crates/router/src/db/merchant_connector_account.rs
index 80019012c0b..de69456f349 100644
--- a/crates/router/src/db/merchant_connector_account.rs
+++ b/crates/router/src/db/merchant_connector_account.rs
@@ -1420,7 +1420,7 @@ mod merchant_connector_account_cache_tests {
         not(feature = "merchant_connector_account_v2")
     ))]
     use api_models::enums::CountryAlpha2;
-    use common_utils::{date_time, types::keymanager::Identifier};
+    use common_utils::{date_time, type_name, types::keymanager::Identifier};
     use diesel_models::enums::ConnectorType;
     use error_stack::ResultExt;
     use masking::PeekInterface;
@@ -1493,13 +1493,17 @@ mod merchant_connector_account_cache_tests {
             key_manager_state,
             domain::MerchantKeyStore {
                 merchant_id: merchant_id.clone(),
-                key: domain::types::encrypt(
+                key: domain::types::crypto_operation(
                     key_manager_state,
-                    services::generate_aes256_key().unwrap().to_vec().into(),
+                    type_name!(domain::MerchantKeyStore),
+                    domain::types::CryptoOperation::Encrypt(
+                        services::generate_aes256_key().unwrap().to_vec().into(),
+                    ),
                     Identifier::Merchant(merchant_id.clone()),
                     master_key,
                 )
                 .await
+                .and_then(|val| val.try_into_operation())
                 .unwrap(),
                 created_at: datetime!(2023-02-01 0:00),
             },
@@ -1520,13 +1524,15 @@ mod merchant_connector_account_cache_tests {
         let mca = domain::MerchantConnectorAccount {
             merchant_id: merchant_id.to_owned(),
             connector_name: "stripe".to_string(),
-            connector_account_details: domain::types::encrypt(
+            connector_account_details: domain::types::crypto_operation(
                 key_manager_state,
-                serde_json::Value::default().into(),
+                type_name!(domain::MerchantConnectorAccount),
+                domain::types::CryptoOperation::Encrypt(serde_json::Value::default().into()),
                 Identifier::Merchant(merchant_key.merchant_id.clone()),
                 merchant_key.key.get_inner().peek(),
             )
             .await
+            .and_then(|val| val.try_into_operation())
             .unwrap(),
             test_mode: None,
             disabled: None,
@@ -1547,13 +1553,15 @@ mod merchant_connector_account_cache_tests {
             pm_auth_config: None,
             status: common_enums::ConnectorStatus::Inactive,
             connector_wallets_details: Some(
-                domain::types::encrypt(
+                domain::types::crypto_operation(
                     key_manager_state,
-                    serde_json::Value::default().into(),
+                    type_name!(domain::MerchantConnectorAccount),
+                    domain::types::CryptoOperation::Encrypt(serde_json::Value::default().into()),
                     Identifier::Merchant(merchant_key.merchant_id.clone()),
                     merchant_key.key.get_inner().peek(),
                 )
                 .await
+                .and_then(|val| val.try_into_operation())
                 .unwrap(),
             ),
             additional_merchant_data: None,
@@ -1653,13 +1661,17 @@ mod merchant_connector_account_cache_tests {
             key_manager_state,
             domain::MerchantKeyStore {
                 merchant_id: merchant_id.clone(),
-                key: domain::types::encrypt(
+                key: domain::types::crypto_operation(
                     key_manager_state,
-                    services::generate_aes256_key().unwrap().to_vec().into(),
+                    type_name!(domain::MerchantConnectorAccount),
+                    domain::types::CryptoOperation::Encrypt(
+                        services::generate_aes256_key().unwrap().to_vec().into(),
+                    ),
                     Identifier::Merchant(merchant_id.clone()),
                     master_key,
                 )
                 .await
+                .and_then(|val| val.try_into_operation())
                 .unwrap(),
                 created_at: datetime!(2023-02-01 0:00),
             },
@@ -1681,13 +1693,15 @@ mod merchant_connector_account_cache_tests {
             id: id.to_string(),
             merchant_id: merchant_id.clone(),
             connector_name: "stripe".to_string(),
-            connector_account_details: domain::types::encrypt(
+            connector_account_details: domain::types::crypto_operation(
                 key_manager_state,
-                serde_json::Value::default().into(),
+                type_name!(domain::MerchantConnectorAccount),
+                domain::types::CryptoOperation::Encrypt(serde_json::Value::default().into()),
                 Identifier::Merchant(merchant_key.merchant_id.clone()),
                 merchant_key.key.get_inner().peek(),
             )
             .await
+            .and_then(|val| val.try_into_operation())
             .unwrap(),
             disabled: None,
             payment_methods_enabled: None,
@@ -1703,13 +1717,15 @@ mod merchant_connector_account_cache_tests {
             pm_auth_config: None,
             status: common_enums::ConnectorStatus::Inactive,
             connector_wallets_details: Some(
-                domain::types::encrypt(
+                domain::types::crypto_operation(
                     key_manager_state,
-                    serde_json::Value::default().into(),
+                    type_name!(domain::MerchantConnectorAccount),
+                    domain::types::CryptoOperation::Encrypt(serde_json::Value::default().into()),
                     Identifier::Merchant(merchant_key.merchant_id.clone()),
                     merchant_key.key.get_inner().peek(),
                 )
                 .await
+                .and_then(|val| val.try_into_operation())
                 .unwrap(),
             ),
             additional_merchant_data: None,
diff --git a/crates/router/src/db/merchant_key_store.rs b/crates/router/src/db/merchant_key_store.rs
index 1fe24999b6f..65a5515a391 100644
--- a/crates/router/src/db/merchant_key_store.rs
+++ b/crates/router/src/db/merchant_key_store.rs
@@ -321,7 +321,7 @@ impl MerchantKeyStoreInterface for MockDb {
 mod tests {
     use std::{borrow::Cow, sync::Arc};
 
-    use common_utils::types::keymanager::Identifier;
+    use common_utils::{type_name, types::keymanager::Identifier};
     use time::macros::datetime;
     use tokio::sync::oneshot;
 
@@ -364,13 +364,17 @@ mod tests {
                 key_manager_state,
                 domain::MerchantKeyStore {
                     merchant_id: merchant_id.clone(),
-                    key: domain::types::encrypt(
+                    key: domain::types::crypto_operation(
                         key_manager_state,
-                        services::generate_aes256_key().unwrap().to_vec().into(),
+                        type_name!(domain::MerchantKeyStore),
+                        domain::types::CryptoOperation::Encrypt(
+                            services::generate_aes256_key().unwrap().to_vec().into(),
+                        ),
                         identifier.clone(),
                         master_key,
                     )
                     .await
+                    .and_then(|val| val.try_into_operation())
                     .unwrap(),
                     created_at: datetime!(2023-02-01 0:00),
                 },
@@ -396,13 +400,17 @@ mod tests {
                 key_manager_state,
                 domain::MerchantKeyStore {
                     merchant_id: merchant_id.clone(),
-                    key: domain::types::encrypt(
+                    key: domain::types::crypto_operation(
                         key_manager_state,
-                        services::generate_aes256_key().unwrap().to_vec().into(),
+                        type_name!(domain::MerchantKeyStore),
+                        domain::types::CryptoOperation::Encrypt(
+                            services::generate_aes256_key().unwrap().to_vec().into(),
+                        ),
                         identifier.clone(),
                         master_key,
                     )
                     .await
+                    .and_then(|val| val.try_into_operation())
                     .unwrap(),
                     created_at: datetime!(2023-02-01 0:00),
                 },
diff --git a/crates/router/src/types/api/admin.rs b/crates/router/src/types/api/admin.rs
index e7127e5d53b..c899c54b79d 100644
--- a/crates/router/src/types/api/admin.rs
+++ b/crates/router/src/types/api/admin.rs
@@ -11,11 +11,12 @@ pub use api_models::{
     },
     organization::{OrganizationId, OrganizationRequest, OrganizationResponse},
 };
-use common_utils::{ext_traits::ValueExt, types::keymanager::Identifier};
+use common_utils::{ext_traits::ValueExt, type_name, types::keymanager::Identifier};
 use diesel_models::organization::OrganizationBridge;
 use error_stack::ResultExt;
 use hyperswitch_domain_models::{
-    merchant_key_store::MerchantKeyStore, type_encryption::decrypt_optional,
+    merchant_key_store::MerchantKeyStore,
+    type_encryption::{crypto_operation, CryptoOperation},
 };
 use masking::{ExposeInterface, PeekInterface};
 
@@ -118,13 +119,15 @@ pub async fn business_profile_response(
     key_store: &MerchantKeyStore,
 ) -> Result<BusinessProfileResponse, error_stack::Report<errors::ParsingError>> {
     let outgoing_webhook_custom_http_headers =
-        decrypt_optional::<serde_json::Value, masking::WithType>(
+        crypto_operation::<serde_json::Value, masking::WithType>(
             &state.into(),
-            item.outgoing_webhook_custom_http_headers.clone(),
+            type_name!(storage::business_profile::BusinessProfile),
+            CryptoOperation::DecryptOptional(item.outgoing_webhook_custom_http_headers.clone()),
             Identifier::Merchant(key_store.merchant_id.clone()),
             key_store.key.get_inner().peek(),
         )
         .await
+        .and_then(|val| val.try_into_optionaloperation())
         .change_context(errors::ParsingError::StructParseFailure(
             "Outgoing webhook custom HTTP headers",
         ))
diff --git a/crates/router/src/types/domain/address.rs b/crates/router/src/types/domain/address.rs
index 55d83679db9..680e26e1f67 100644
--- a/crates/router/src/types/domain/address.rs
+++ b/crates/router/src/types/domain/address.rs
@@ -4,7 +4,7 @@ use common_utils::{
     date_time,
     encryption::Encryption,
     errors::{CustomResult, ValidationError},
-    id_type,
+    id_type, type_name,
     types::keymanager::{Identifier, KeyManagerState, ToEncryptable},
 };
 use diesel_models::{address::AddressUpdateInternal, enums};
@@ -188,13 +188,17 @@ impl behaviour::Conversion for Address {
         _key_manager_identifier: Identifier,
     ) -> CustomResult<Self, ValidationError> {
         let identifier = Identifier::Merchant(other.merchant_id.clone());
-        let decrypted: FxHashMap<String, Encryptable<Secret<String>>> = types::batch_decrypt(
+        let decrypted: FxHashMap<String, Encryptable<Secret<String>>> = types::crypto_operation(
             state,
-            diesel_models::Address::to_encryptable(other.clone()),
+            type_name!(Self::DstType),
+            types::CryptoOperation::BatchDecrypt(diesel_models::Address::to_encryptable(
+                other.clone(),
+            )),
             identifier.clone(),
             key.peek(),
         )
         .await
+        .and_then(|val| val.try_into_batchoperation())
         .change_context(ValidationError::InvalidValue {
             message: "Failed while decrypting".to_string(),
         })?;
diff --git a/crates/router/src/types/domain/event.rs b/crates/router/src/types/domain/event.rs
index 67183a2d3a4..872eb303901 100644
--- a/crates/router/src/types/domain/event.rs
+++ b/crates/router/src/types/domain/event.rs
@@ -1,5 +1,6 @@
 use common_utils::{
     crypto::OptionalEncryptableSecretString,
+    type_name,
     types::keymanager::{KeyManagerState, ToEncryptable},
 };
 use diesel_models::{
@@ -92,16 +93,20 @@ impl super::behaviour::Conversion for Event {
     where
         Self: Sized,
     {
-        let decrypted = types::batch_decrypt(
+        let decrypted = types::crypto_operation(
             state,
-            EventWithEncryption::to_encryptable(EventWithEncryption {
-                request: item.request.clone(),
-                response: item.response.clone(),
-            }),
+            type_name!(Self::DstType),
+            types::CryptoOperation::BatchDecrypt(EventWithEncryption::to_encryptable(
+                EventWithEncryption {
+                    request: item.request.clone(),
+                    response: item.response.clone(),
+                },
+            )),
             key_manager_identifier,
             key.peek(),
         )
         .await
+        .and_then(|val| val.try_into_batchoperation())
         .change_context(ValidationError::InvalidValue {
             message: "Failed while decrypting event data".to_string(),
         })?;
diff --git a/crates/router/src/types/domain/types.rs b/crates/router/src/types/domain/types.rs
index e105b2eba09..10657adc122 100644
--- a/crates/router/src/types/domain/types.rs
+++ b/crates/router/src/types/domain/types.rs
@@ -1,7 +1,6 @@
 use common_utils::types::keymanager::KeyManagerState;
 pub use hyperswitch_domain_models::type_encryption::{
-    batch_decrypt, batch_encrypt, decrypt, decrypt_optional, encrypt, encrypt_optional, AsyncLift,
-    Lift,
+    crypto_operation, AsyncLift, CryptoOperation, Lift,
 };
 
 impl From<&crate::SessionState> for KeyManagerState {
diff --git a/crates/router/src/types/domain/user.rs b/crates/router/src/types/domain/user.rs
index 41fbc96f6d2..3df0a11af0e 100644
--- a/crates/router/src/types/domain/user.rs
+++ b/crates/router/src/types/domain/user.rs
@@ -5,7 +5,7 @@ use api_models::{
 };
 use common_enums::TokenPurpose;
 use common_utils::{
-    crypto::Encryptable, errors::CustomResult, id_type, new_type::MerchantName, pii,
+    crypto::Encryptable, errors::CustomResult, id_type, new_type::MerchantName, pii, type_name,
     types::keymanager::Identifier,
 };
 use diesel_models::{
@@ -1001,13 +1001,15 @@ impl UserFromStorage {
 
             let key_store = UserKeyStore {
                 user_id: self.get_user_id().to_string(),
-                key: domain_types::encrypt(
+                key: domain_types::crypto_operation(
                     key_manager_state,
-                    key.to_vec().into(),
+                    type_name!(UserKeyStore),
+                    domain_types::CryptoOperation::Encrypt(key.to_vec().into()),
                     Identifier::User(self.get_user_id().to_string()),
                     master_key,
                 )
                 .await
+                .and_then(|val| val.try_into_operation())
                 .change_context(UserErrors::InternalServerError)?,
                 created_at: common_utils::date_time::now(),
             };
@@ -1051,13 +1053,15 @@ impl UserFromStorage {
             .await
             .change_context(UserErrors::InternalServerError)?;
 
-        Ok(domain_types::decrypt_optional::<String, masking::WithType>(
+        Ok(domain_types::crypto_operation::<String, masking::WithType>(
             key_manager_state,
-            self.0.totp_secret.clone(),
+            type_name!(storage_user::User),
+            domain_types::CryptoOperation::DecryptOptional(self.0.totp_secret.clone()),
             Identifier::User(user_key_store.user_id.clone()),
             user_key_store.key.peek(),
         )
         .await
+        .and_then(|val| val.try_into_optionaloperation())
         .change_context(UserErrors::InternalServerError)?
         .map(Encryptable::into_inner))
     }
diff --git a/crates/router/src/types/domain/user_key_store.rs b/crates/router/src/types/domain/user_key_store.rs
index b0b57732cc8..696fab7eef5 100644
--- a/crates/router/src/types/domain/user_key_store.rs
+++ b/crates/router/src/types/domain/user_key_store.rs
@@ -1,10 +1,10 @@
 use common_utils::{
     crypto::Encryptable,
-    date_time,
+    date_time, type_name,
     types::keymanager::{Identifier, KeyManagerState},
 };
 use error_stack::ResultExt;
-use hyperswitch_domain_models::type_encryption::decrypt;
+use hyperswitch_domain_models::type_encryption::{crypto_operation, CryptoOperation};
 use masking::{PeekInterface, Secret};
 use time::PrimitiveDateTime;
 
@@ -41,11 +41,18 @@ impl super::behaviour::Conversion for UserKeyStore {
     {
         let identifier = Identifier::User(item.user_id.clone());
         Ok(Self {
-            key: decrypt(state, item.key, identifier, key.peek())
-                .await
-                .change_context(ValidationError::InvalidValue {
-                    message: "Failed while decrypting customer data".to_string(),
-                })?,
+            key: crypto_operation(
+                state,
+                type_name!(Self::DstType),
+                CryptoOperation::Decrypt(item.key),
+                identifier,
+                key.peek(),
+            )
+            .await
+            .and_then(|val| val.try_into_operation())
+            .change_context(ValidationError::InvalidValue {
+                message: "Failed while decrypting customer data".to_string(),
+            })?,
             user_id: item.user_id,
             created_at: item.created_at,
         })
diff --git a/crates/router/src/utils.rs b/crates/router/src/utils.rs
index 5b46dce1392..44396de7ac2 100644
--- a/crates/router/src/utils.rs
+++ b/crates/router/src/utils.rs
@@ -22,8 +22,6 @@ use api_models::{
 };
 use base64::Engine;
 use common_utils::types::keymanager::KeyManagerState;
-#[cfg(all(any(feature = "v1", feature = "v2"), not(feature = "customer_v2")))]
-use common_utils::types::keymanager::{Identifier, ToEncryptable};
 pub use common_utils::{
     crypto,
     ext_traits::{ByteSliceExt, BytesExt, Encode, StringExt, ValueExt},
@@ -31,10 +29,15 @@ pub use common_utils::{
     id_type,
     validation::validate_email,
 };
+#[cfg(all(any(feature = "v1", feature = "v2"), not(feature = "customer_v2")))]
+use common_utils::{
+    type_name,
+    types::keymanager::{Identifier, ToEncryptable},
+};
 use error_stack::ResultExt;
 use hyperswitch_domain_models::payments::PaymentIntent;
 #[cfg(all(any(feature = "v1", feature = "v2"), not(feature = "customer_v2")))]
-use hyperswitch_domain_models::type_encryption::batch_encrypt;
+use hyperswitch_domain_models::type_encryption::{crypto_operation, CryptoOperation};
 use image::Luma;
 use nanoid::nanoid;
 use qrcode;
@@ -794,17 +797,21 @@ impl CustomerAddress for api_models::customers::CustomerRequest {
         storage_scheme: storage::enums::MerchantStorageScheme,
         merchant_id: id_type::MerchantId,
     ) -> CustomResult<storage::AddressUpdate, common_utils::errors::CryptoError> {
-        let encrypted_data = batch_encrypt(
+        let encrypted_data = crypto_operation(
             &state.into(),
-            AddressDetailsWithPhone::to_encryptable(AddressDetailsWithPhone {
-                address: Some(address_details.clone()),
-                phone_number: self.phone.clone(),
-                email: self.email.clone(),
-            }),
+            type_name!(storage::Address),
+            CryptoOperation::BatchEncrypt(AddressDetailsWithPhone::to_encryptable(
+                AddressDetailsWithPhone {
+                    address: Some(address_details.clone()),
+                    phone_number: self.phone.clone(),
+                    email: self.email.clone(),
+                },
+            )),
             Identifier::Merchant(merchant_id),
             key,
         )
-        .await?;
+        .await
+        .and_then(|val| val.try_into_batchoperation())?;
         let encryptable_address = AddressDetailsWithPhone::from_encryptable(encrypted_data)
             .change_context(common_utils::errors::CryptoError::EncodingFailed)?;
         Ok(storage::AddressUpdate::Update {
@@ -833,17 +840,21 @@ impl CustomerAddress for api_models::customers::CustomerRequest {
         key: &[u8],
         storage_scheme: storage::enums::MerchantStorageScheme,
     ) -> CustomResult<domain::CustomerAddress, common_utils::errors::CryptoError> {
-        let encrypted_data = batch_encrypt(
+        let encrypted_data = crypto_operation(
             &state.into(),
-            AddressDetailsWithPhone::to_encryptable(AddressDetailsWithPhone {
-                address: Some(address_details.clone()),
-                phone_number: self.phone.clone(),
-                email: self.email.clone(),
-            }),
+            type_name!(storage::Address),
+            CryptoOperation::BatchEncrypt(AddressDetailsWithPhone::to_encryptable(
+                AddressDetailsWithPhone {
+                    address: Some(address_details.clone()),
+                    phone_number: self.phone.clone(),
+                    email: self.email.clone(),
+                },
+            )),
             Identifier::Merchant(merchant_id.to_owned()),
             key,
         )
-        .await?;
+        .await
+        .and_then(|val| val.try_into_batchoperation())?;
         let encryptable_address = AddressDetailsWithPhone::from_encryptable(encrypted_data)
             .change_context(common_utils::errors::CryptoError::EncodingFailed)?;
         let address = domain::Address {
diff --git a/crates/router/src/utils/user.rs b/crates/router/src/utils/user.rs
index 2dad55c4b89..1de45b74360 100644
--- a/crates/router/src/utils/user.rs
+++ b/crates/router/src/utils/user.rs
@@ -3,7 +3,7 @@ use std::{collections::HashMap, sync::Arc};
 use api_models::user as user_api;
 use common_enums::UserAuthType;
 use common_utils::{
-    encryption::Encryption, errors::CustomResult, id_type, types::keymanager::Identifier,
+    encryption::Encryption, errors::CustomResult, id_type, type_name, types::keymanager::Identifier,
 };
 use diesel_models::{enums::UserStatus, user_role::UserRole};
 use error_stack::{report, ResultExt};
@@ -260,15 +260,18 @@ pub async fn construct_public_and_private_db_configs(
                 .change_context(UserErrors::InternalServerError)
                 .attach_printable("Failed to convert auth config to json")?;
 
-            let encrypted_config = domain::types::encrypt::<serde_json::Value, masking::WithType>(
-                &state.into(),
-                private_config_value.into(),
-                Identifier::UserAuth(id),
-                encryption_key,
-            )
-            .await
-            .change_context(UserErrors::InternalServerError)
-            .attach_printable("Failed to encrypt auth config")?;
+            let encrypted_config =
+                domain::types::crypto_operation::<serde_json::Value, masking::WithType>(
+                    &state.into(),
+                    type_name!(diesel_models::user::User),
+                    domain::types::CryptoOperation::Encrypt(private_config_value.into()),
+                    Identifier::UserAuth(id),
+                    encryption_key,
+                )
+                .await
+                .and_then(|val| val.try_into_operation())
+                .change_context(UserErrors::InternalServerError)
+                .attach_printable("Failed to encrypt auth config")?;
 
             Ok((
                 Some(encrypted_config.into()),
@@ -309,13 +312,15 @@ pub async fn decrypt_oidc_private_config(
     .change_context(UserErrors::InternalServerError)
     .attach_printable("Failed to decode DEK")?;
 
-    let private_config = domain::types::decrypt_optional::<serde_json::Value, masking::WithType>(
+    let private_config = domain::types::crypto_operation::<serde_json::Value, masking::WithType>(
         &state.into(),
-        encrypted_config,
+        type_name!(diesel_models::user::User),
+        domain::types::CryptoOperation::DecryptOptional(encrypted_config),
         Identifier::UserAuth(id),
         &user_auth_key,
     )
     .await
+    .and_then(|val| val.try_into_optionaloperation())
     .change_context(UserErrors::InternalServerError)
     .attach_printable("Failed to decrypt private config")?
     .ok_or(UserErrors::InternalServerError)

## Type of Change
<!-- Put an `x` in the boxes that apply -->
- [x] Enhancement

## Description
<!-- Describe your changes in detail -->
Added a wrapper for Crypto Operation (Encrypt, Decrypt). So any changes in Encryption framework can be done in one place. This also adds logging for table name for which the Encryption and Decryption is happening

## Motivation and Context
<!--
Why is this change required? What problem does it solve?
If it fixes an open issue, please link to the issue here.

If you don't have an issue, we'd recommend starting with one first so the PR
can focus on the implementation (unless it is an obvious bug or documentation fix
that will have little conversation).
-->
This adds two things

- A wrapper for encryption and decryption operation
- A table name field for encryption and decryption logs

## How did you test it?
<!--
Did you write an integration/unit/API test to verify the code changes?
Or did you test this change manually (provide relevant screenshots)?
-->
- All sanity tests for MerchantAccount Create, Payments, Refunds
- Check the table name field in the encryption logs

![Screenshot 2024-08-07 at 2 49 36 PM](https://github.com/user-attachments/assets/d46e0cfc-a59e-4923-87e1-47a92161cd28)


## Checklist
<!-- Put an `x` in the boxes that apply -->

- [x] I formatted the code `cargo +nightly fmt --all`
- [x] I addressed lints thrown by `cargo clippy`
- [x]  I reviewed the submitted code