Bug: [FEATURE] loonio webhooks



### Feature Description

Implement webhook support for loonio

### Possible Implementation

Implement Webhook - Payment

### Have you spent some time checking if this feature request has been raised before?

- [x] I checked and didn't find a similar issue

### Have you read the Contributing Guidelines?

- [x] I have read the [Contributing Guidelines](https://github.com/juspay/hyperswitch/blob/main/docs/CONTRIBUTING.md)

### Are you willing to submit a PR?

None
diff --git a/crates/hyperswitch_connectors/src/connectors/loonio.rs b/crates/hyperswitch_connectors/src/connectors/loonio.rs
index 96ee717b862..1de6f4236d4 100644
--- a/crates/hyperswitch_connectors/src/connectors/loonio.rs
+++ b/crates/hyperswitch_connectors/src/connectors/loonio.rs
@@ -2,12 +2,13 @@ pub mod transformers;
 
 use common_enums::enums;
 use common_utils::{
+    crypto::Encryptable,
     errors::CustomResult,
-    ext_traits::BytesExt,
+    ext_traits::{ByteSliceExt, BytesExt},
     request::{Method, Request, RequestBuilder, RequestContent},
     types::{AmountConvertor, FloatMajorUnit, FloatMajorUnitForConnector},
 };
-use error_stack::{report, ResultExt};
+use error_stack::ResultExt;
 use hyperswitch_domain_models::{
     payment_method_data::PaymentMethodData,
     router_data::{AccessToken, ConnectorAuthType, ErrorResponse, RouterData},
@@ -42,7 +43,7 @@ use hyperswitch_interfaces::{
     webhooks,
 };
 use lazy_static::lazy_static;
-use masking::{ExposeInterface, Mask};
+use masking::{ExposeInterface, Mask, Secret};
 use transformers as loonio;
 
 use crate::{constants::headers, types::ResponseRouterData, utils};
@@ -334,9 +335,9 @@ impl ConnectorIntegration<PSync, PaymentsSyncData, PaymentsResponseData> for Loo
         event_builder: Option<&mut ConnectorEvent>,
         res: Response,
     ) -> CustomResult<PaymentsSyncRouterData, errors::ConnectorError> {
-        let response: loonio::LoonioTransactionSyncResponse = res
+        let response: loonio::LoonioPaymentResponseData = res
             .response
-            .parse_struct("loonio LoonioTransactionSyncResponse")
+            .parse_struct("loonio LoonioPaymentResponseData")
             .change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
         event_builder.map(|i| i.set_response_body(&response));
         router_env::logger::info!(connector_response=?response);
@@ -588,25 +589,56 @@ impl ConnectorIntegration<RSync, RefundsData, RefundsResponseData> for Loonio {
 
 #[async_trait::async_trait]
 impl webhooks::IncomingWebhook for Loonio {
-    fn get_webhook_object_reference_id(
+    async fn verify_webhook_source(
         &self,
         _request: &webhooks::IncomingWebhookRequestDetails<'_>,
+        _merchant_id: &common_utils::id_type::MerchantId,
+        _connector_webhook_details: Option<common_utils::pii::SecretSerdeValue>,
+        _connector_account_details: Encryptable<Secret<serde_json::Value>>,
+        _connector_name: &str,
+    ) -> CustomResult<bool, errors::ConnectorError> {
+        Ok(false)
+    }
+
+    fn get_webhook_object_reference_id(
+        &self,
+        request: &webhooks::IncomingWebhookRequestDetails<'_>,
     ) -> CustomResult<api_models::webhooks::ObjectReferenceId, errors::ConnectorError> {
-        Err(report!(errors::ConnectorError::WebhooksNotImplemented))
+        let webhook_body: loonio::LoonioWebhookBody = request
+            .body
+            .parse_struct("LoonioWebhookBody")
+            .change_context(errors::ConnectorError::WebhookBodyDecodingFailed)?;
+
+        Ok(api_models::webhooks::ObjectReferenceId::PaymentId(
+            api_models::payments::PaymentIdType::ConnectorTransactionId(
+                webhook_body.api_transaction_id,
+            ),
+        ))
     }
 
     fn get_webhook_event_type(
         &self,
-        _request: &webhooks::IncomingWebhookRequestDetails<'_>,
+        request: &webhooks::IncomingWebhookRequestDetails<'_>,
     ) -> CustomResult<api_models::webhooks::IncomingWebhookEvent, errors::ConnectorError> {
-        Err(report!(errors::ConnectorError::WebhooksNotImplemented))
+        let webhook_body: loonio::LoonioWebhookBody = request
+            .body
+            .parse_struct("LoonioWebhookBody")
+            .change_context(errors::ConnectorError::WebhookBodyDecodingFailed)?;
+        Ok((&webhook_body.event_code).into())
     }
 
     fn get_webhook_resource_object(
         &self,
-        _request: &webhooks::IncomingWebhookRequestDetails<'_>,
+        request: &webhooks::IncomingWebhookRequestDetails<'_>,
     ) -> CustomResult<Box<dyn masking::ErasedMaskSerialize>, errors::ConnectorError> {
-        Err(report!(errors::ConnectorError::WebhooksNotImplemented))
+        let webhook_body: loonio::LoonioWebhookBody = request
+            .body
+            .parse_struct("LoonioWebhookBody")
+            .change_context(errors::ConnectorError::WebhookBodyDecodingFailed)?;
+
+        let resource = loonio::LoonioPaymentResponseData::Webhook(webhook_body);
+
+        Ok(Box::new(resource))
     }
 }
 
@@ -614,8 +646,8 @@ lazy_static! {
     static ref LOONIO_SUPPORTED_PAYMENT_METHODS: SupportedPaymentMethods = {
         let supported_capture_methods = vec![enums::CaptureMethod::Automatic];
 
-        let mut gigadat_supported_payment_methods = SupportedPaymentMethods::new();
-        gigadat_supported_payment_methods.add(
+        let mut loonio_supported_payment_methods = SupportedPaymentMethods::new();
+        loonio_supported_payment_methods.add(
             enums::PaymentMethod::BankRedirect,
             enums::PaymentMethodType::Interac,
             PaymentMethodDetails {
@@ -626,7 +658,7 @@ lazy_static! {
             },
         );
 
-        gigadat_supported_payment_methods
+        loonio_supported_payment_methods
     };
     static ref LOONIO_CONNECTOR_INFO: ConnectorInfo = ConnectorInfo {
         display_name: "Loonio",
@@ -634,7 +666,9 @@ lazy_static! {
         connector_type: enums::HyperswitchConnectorCategory::PaymentGateway,
         integration_status: enums::ConnectorIntegrationStatus::Sandbox,
     };
-    static ref LOONIO_SUPPORTED_WEBHOOK_FLOWS: Vec<enums::EventClass> = Vec::new();
+    static ref LOONIO_SUPPORTED_WEBHOOK_FLOWS: Vec<enums::EventClass> = vec![
+        enums::EventClass::Payments,
+    ];
 }
 
 impl ConnectorSpecifications for Loonio {
diff --git a/crates/hyperswitch_connectors/src/connectors/loonio/transformers.rs b/crates/hyperswitch_connectors/src/connectors/loonio/transformers.rs
index 7efc1a895dc..f1c594145b6 100644
--- a/crates/hyperswitch_connectors/src/connectors/loonio/transformers.rs
+++ b/crates/hyperswitch_connectors/src/connectors/loonio/transformers.rs
@@ -1,5 +1,6 @@
 use std::collections::HashMap;
 
+use api_models::webhooks;
 use common_enums::{enums, Currency};
 use common_utils::{id_type, pii::Email, request::Method, types::FloatMajorUnit};
 use hyperswitch_domain_models::{
@@ -18,7 +19,6 @@ use crate::{
     types::{RefundsResponseRouterData, ResponseRouterData},
     utils::{self, PaymentsAuthorizeRequestData, RouterData as _},
 };
-
 pub struct LoonioRouterData<T> {
     pub amount: FloatMajorUnit,
     pub router_data: T,
@@ -62,6 +62,8 @@ pub struct LoonioPaymentRequest {
     pub payment_method_type: InteracPaymentMethodType,
     #[serde(skip_serializing_if = "Option::is_none")]
     pub redirect_url: Option<LoonioRedirectUrl>,
+    #[serde(skip_serializing_if = "Option::is_none")]
+    pub webhook_url: Option<String>,
 }
 
 #[derive(Debug, Serialize)]
@@ -102,7 +104,6 @@ impl TryFrom<&LoonioRouterData<&PaymentsAuthorizeRouterData>> for LoonioPaymentR
                     success_url: item.router_data.request.get_router_return_url()?,
                     failed_url: item.router_data.request.get_router_return_url()?,
                 };
-
                 Ok(Self {
                     currency_code: item.router_data.request.currency,
                     customer_profile,
@@ -111,6 +112,7 @@ impl TryFrom<&LoonioRouterData<&PaymentsAuthorizeRouterData>> for LoonioPaymentR
                     transaction_id,
                     payment_method_type: InteracPaymentMethodType::InteracEtransfer,
                     redirect_url: Some(redirect_url),
+                    webhook_url: Some(item.router_data.request.get_webhook_url()?),
                 })
             }
             PaymentMethodData::BankRedirect(_) => Err(errors::ConnectorError::NotImplemented(
@@ -140,7 +142,9 @@ impl<F, T> TryFrom<ResponseRouterData<F, LoonioPaymentsResponse, T, PaymentsResp
         Ok(Self {
             status: enums::AttemptStatus::AuthenticationPending,
             response: Ok(PaymentsResponseData::TransactionResponse {
-                resource_id: ResponseId::ConnectorTransactionId(item.response.payment_form.clone()),
+                resource_id: ResponseId::ConnectorTransactionId(
+                    item.data.connector_request_reference_id.clone(),
+                ),
                 redirection_data: Box::new(Some(RedirectForm::Form {
                     endpoint: item.response.payment_form,
                     method: Method::Get,
@@ -211,29 +215,48 @@ impl<F> TryFrom<&LoonioRouterData<&RefundsRouterData<F>>> for LoonioRefundReques
     }
 }
 
-impl<F, T> TryFrom<ResponseRouterData<F, LoonioTransactionSyncResponse, T, PaymentsResponseData>>
+impl<F, T> TryFrom<ResponseRouterData<F, LoonioPaymentResponseData, T, PaymentsResponseData>>
     for RouterData<F, T, PaymentsResponseData>
 {
     type Error = error_stack::Report<errors::ConnectorError>;
     fn try_from(
-        item: ResponseRouterData<F, LoonioTransactionSyncResponse, T, PaymentsResponseData>,
+        item: ResponseRouterData<F, LoonioPaymentResponseData, T, PaymentsResponseData>,
     ) -> Result<Self, Self::Error> {
-        Ok(Self {
-            status: enums::AttemptStatus::from(item.response.state),
-            response: Ok(PaymentsResponseData::TransactionResponse {
-                resource_id: ResponseId::ConnectorTransactionId(
-                    item.response.transaction_id.clone(),
-                ),
-                redirection_data: Box::new(None),
-                mandate_reference: Box::new(None),
-                connector_metadata: None,
-                network_txn_id: None,
-                connector_response_reference_id: None,
-                incremental_authorization_allowed: None,
-                charges: None,
+        match item.response {
+            LoonioPaymentResponseData::Sync(sync_response) => Ok(Self {
+                status: enums::AttemptStatus::from(sync_response.state),
+                response: Ok(PaymentsResponseData::TransactionResponse {
+                    resource_id: ResponseId::ConnectorTransactionId(sync_response.transaction_id),
+                    redirection_data: Box::new(None),
+                    mandate_reference: Box::new(None),
+                    connector_metadata: None,
+                    network_txn_id: None,
+                    connector_response_reference_id: None,
+                    incremental_authorization_allowed: None,
+                    charges: None,
+                }),
+                ..item.data
             }),
-            ..item.data
-        })
+            LoonioPaymentResponseData::Webhook(webhook_body) => {
+                let payment_status = enums::AttemptStatus::from(&webhook_body.event_code);
+                Ok(Self {
+                    status: payment_status,
+                    response: Ok(PaymentsResponseData::TransactionResponse {
+                        resource_id: ResponseId::ConnectorTransactionId(
+                            webhook_body.api_transaction_id,
+                        ),
+                        redirection_data: Box::new(None),
+                        mandate_reference: Box::new(None),
+                        connector_metadata: None,
+                        network_txn_id: None,
+                        connector_response_reference_id: None,
+                        incremental_authorization_allowed: None,
+                        charges: None,
+                    }),
+                    ..item.data
+                })
+            }
+        }
     }
 }
 
@@ -303,3 +326,94 @@ pub struct LoonioErrorResponse {
     pub error_code: Option<String>,
     pub message: String,
 }
+
+// Webhook related structs
+
+#[derive(Debug, Serialize, Deserialize)]
+#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
+pub enum LoonioWebhookEventCode {
+    TransactionPrepared,
+    TransactionPending,
+    TransactionAvailable,
+    TransactionSettled,
+    TransactionFailed,
+    TransactionRejected,
+    #[serde(rename = "TRANSACTION_WAITING_STATUS_FILE")]
+    TransactionWaitingStatusFile,
+    #[serde(rename = "TRANSACTION_STATUS_FILE_RECEIVED")]
+    TransactionStatusFileReceived,
+    #[serde(rename = "TRANSACTION_STATUS_FILE_FAILED")]
+    TransactionStatusFileFailed,
+    #[serde(rename = "TRANSACTION_RETURNED")]
+    TransactionReturned,
+    #[serde(rename = "TRANSACTION_WRONG_DESTINATION")]
+    TransactionWrongDestination,
+    #[serde(rename = "TRANSACTION_NSF")]
+    TransactionNsf,
+}
+
+#[derive(Debug, Serialize, Deserialize)]
+#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
+pub enum LoonioWebhookTransactionType {
+    Incoming,
+    OutgoingVerified,
+    OutgoingNotVerified,
+    OutgoingCustomerDefined,
+}
+
+#[derive(Debug, Serialize, Deserialize)]
+pub struct LoonioWebhookBody {
+    pub amount: FloatMajorUnit,
+    pub api_transaction_id: String,
+    pub signature: Option<String>,
+    pub event_code: LoonioWebhookEventCode,
+    pub id: i32,
+    #[serde(rename = "type")]
+    pub transaction_type: LoonioWebhookTransactionType,
+}
+
+#[derive(Debug, Serialize, Deserialize)]
+#[serde(untagged)]
+pub enum LoonioPaymentResponseData {
+    Sync(LoonioTransactionSyncResponse),
+    Webhook(LoonioWebhookBody),
+}
+impl From<&LoonioWebhookEventCode> for webhooks::IncomingWebhookEvent {
+    fn from(event_code: &LoonioWebhookEventCode) -> Self {
+        match event_code {
+            LoonioWebhookEventCode::TransactionSettled
+            | LoonioWebhookEventCode::TransactionAvailable => Self::PaymentIntentSuccess,
+            LoonioWebhookEventCode::TransactionPending
+            | LoonioWebhookEventCode::TransactionPrepared => Self::PaymentIntentProcessing,
+            LoonioWebhookEventCode::TransactionFailed
+            // deprecated
+            | LoonioWebhookEventCode::TransactionRejected
+            | LoonioWebhookEventCode::TransactionStatusFileFailed
+            | LoonioWebhookEventCode::TransactionReturned
+            | LoonioWebhookEventCode::TransactionWrongDestination
+            | LoonioWebhookEventCode::TransactionNsf => Self::PaymentIntentFailure,
+            _ => Self::EventNotSupported,
+        }
+    }
+}
+
+impl From<&LoonioWebhookEventCode> for enums::AttemptStatus {
+    fn from(event_code: &LoonioWebhookEventCode) -> Self {
+        match event_code {
+            LoonioWebhookEventCode::TransactionSettled
+            | LoonioWebhookEventCode::TransactionAvailable => Self::Charged,
+
+            LoonioWebhookEventCode::TransactionPending
+            | LoonioWebhookEventCode::TransactionPrepared => Self::Pending,
+
+            LoonioWebhookEventCode::TransactionFailed
+            | LoonioWebhookEventCode::TransactionRejected
+            | LoonioWebhookEventCode::TransactionStatusFileFailed
+            | LoonioWebhookEventCode::TransactionReturned
+            | LoonioWebhookEventCode::TransactionWrongDestination
+            | LoonioWebhookEventCode::TransactionNsf => Self::Failure,
+
+            _ => Self::Pending,
+        }
+    }
+}

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

- [ ] Bugfix
- [x] New feature
- [ ] Enhancement
- [ ] Refactoring
- [ ] Dependency updates
- [ ] Documentation
- [ ] CI/CD

## Description
<!-- Describe your changes in detail -->

Loomio webhooks for payments 


## payment request

```json
{
    "amount": 1500,
    "currency": "CAD",
    "confirm": true,
    "capture_method": "automatic",
    "customer_id": "aaaa",

    "authentication_type": "three_ds",
    "payment_method": "bank_redirect",
    "payment_method_type": "interac",
    "payment_method_data": {
        "bank_redirect": {
            "interac": {}
        }
    },
    "billing": {
        "address": {
            "line1": "Singapore Changi Airport. 2nd flr",
            "line2": "",
            "line3": "",
            "city": "Downtown Core",
            "state": "Central Indiana America",
            "zip": "039393",
            "country": "SG",
            "first_name": "Swangi",
            "last_name": "Kumari"
        },
        "phone": {
            "number": "8056594427",
            "country_code": "+91"
        },
        "email": "swangi.kumari@juspay.in"
    },
    "browser_info": {
        "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36",
        "accept_header": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8",
        "language": "nl-NL",
        "color_depth": 24,
        "screen_height": 723,
        "screen_width": 1536,
        "time_zone": 0,
        "java_enabled": true,
        "java_script_enabled": true,
        "ip_address": "127.0.0.1"
    }
}
```

## response

```json
{
    "payment_id": "pay_J3xaVGqCX1QbnGKyQoCQ",
    "merchant_id": "merchant_1759821555",
    "status": "requires_customer_action",
    "amount": 1500,
    "net_amount": 1500,
    "shipping_cost": null,
    "amount_capturable": 1500,
    "amount_received": null,
    "connector": "loonio",
    "client_secret": "pay_J3xaVGqCX1QbnGKyQoCQ_secret_IfvZo54PdakCzmi10muX",
    "created": "2025-10-07T09:15:47.349Z",
    "currency": "CAD",
    "customer_id": "aaaa",
    "customer": {
        "id": "aaaa",
        "name": null,
        "email": null,
        "phone": null,
        "phone_country_code": null
    },
    "description": null,
    "refunds": null,
    "disputes": null,
    "mandate_id": null,
    "mandate_data": null,
    "setup_future_usage": null,
    "off_session": null,
    "capture_on": null,
    "capture_method": "automatic",
    "payment_method": "bank_redirect",
    "payment_method_data": {
        "bank_redirect": {
            "type": "BankRedirectResponse",
            "bank_name": null
        },
        "billing": null
    },
    "payment_token": null,
    "shipping": null,
    "billing": {
        "address": {
            "city": "Downtown Core",
            "country": "SG",
            "line1": "Singapore Changi Airport. 2nd flr",
            "line2": "",
            "line3": "",
            "zip": "039393",
            "state": "Central Indiana America",
            "first_name": "Swangi",
            "last_name": "Kumari",
            "origin_zip": null
        },
        "phone": {
            "number": "8056594427",
            "country_code": "+91"
        },
        "email": "swangi.kumari@juspay.in"
    },
    "order_details": null,
    "email": null,
    "name": null,
    "phone": null,
    "return_url": null,
    "authentication_type": "three_ds",
    "statement_descriptor_name": null,
    "statement_descriptor_suffix": null,
    "next_action": {
        "type": "redirect_to_url",
        "redirect_to_url": "http://localhost:8080/payments/redirect/pay_J3xaVGqCX1QbnGKyQoCQ/merchant_1759821555/pay_J3xaVGqCX1QbnGKyQoCQ_1"
    },
    "cancellation_reason": null,
    "error_code": null,
    "error_message": null,
    "unified_code": null,
    "unified_message": null,
    "payment_experience": null,
    "payment_method_type": "interac",
    "connector_label": null,
    "business_country": null,
    "business_label": "default",
    "business_sub_label": null,
    "allowed_payment_method_types": null,
    "ephemeral_key": {
        "customer_id": "aaaa",
        "created_at": 1759828547,
        "expires": 1759832147,
        "secret": "epk_dfb1c2f173f34c4da48ee0a98d48051f"
    },
    "manual_retry_allowed": null,
    "connector_transaction_id": "pay_J3xaVGqCX1QbnGKyQoCQ_1",
    "frm_message": null,
    "metadata": null,
    "connector_metadata": null,
    "feature_metadata": {
        "redirect_response": null,
        "search_tags": null,
        "apple_pay_recurring_details": null,
        "gateway_system": "direct"
    },
    "reference_id": null,
    "payment_link": null,
    "profile_id": "pro_MLEtbytGk3haqiqlaheV",
    "surcharge_details": null,
    "attempt_count": 1,
    "merchant_decision": null,
    "merchant_connector_id": "mca_UKE4wkdWmZVIs8oRKgbo",
    "incremental_authorization_allowed": false,
    "authorization_count": null,
    "incremental_authorizations": null,
    "external_authentication_details": null,
    "external_3ds_authentication_attempted": false,
    "expires_on": "2025-10-07T09:30:47.349Z",
    "fingerprint": null,
    "browser_info": {
        "language": "nl-NL",
        "time_zone": 0,
        "ip_address": "127.0.0.1",
        "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36",
        "color_depth": 24,
        "java_enabled": true,
        "screen_width": 1536,
        "accept_header": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8",
        "screen_height": 723,
        "java_script_enabled": true
    },
    "payment_channel": null,
    "payment_method_id": null,
    "network_transaction_id": null,
    "payment_method_status": null,
    "updated": "2025-10-07T09:15:48.782Z",
    "split_payments": null,
    "frm_metadata": null,
    "extended_authorization_applied": null,
    "request_extended_authorization": null,
    "capture_before": null,
    "merchant_order_reference_id": null,
    "order_tax_amount": null,
    "connector_mandate_id": null,
    "card_discovery": null,
    "force_3ds_challenge": false,
    "force_3ds_challenge_trigger": false,
    "issuer_error_code": null,
    "issuer_error_message": null,
    "is_iframe_redirection_enabled": null,
    "whole_connector_response": null,
    "enable_partial_authorization": null,
    "enable_overcapture": null,
    "is_overcapture_enabled": null,
    "network_details": null,
    "is_stored_credential": null,
    "mit_category": null
}
```

## make redirect
<img width="1708" height="1115" alt="Screenshot 2025-10-07 at 2 47 11 PM" src="https://github.com/user-attachments/assets/35ea68fa-8b86-48ef-9600-64916ebdaf2b" />

## the status will change when webhook reaches without force psync

<img width="1178" height="678" alt="Screenshot 2025-10-07 at 2 47 43 PM" src="https://github.com/user-attachments/assets/254d2a5f-eab1-4b15-988a-a353338d1536" />

## webhook source verificaiton = false


<img width="1085" height="311" alt="Screenshot 2025-10-07 at 6 15 09 PM" src="https://github.com/user-attachments/assets/0f21632f-0927-47ac-95b4-4593dcbb1633" />
<img width="648" height="246" alt="Screenshot 2025-10-07 at 6 15 21 PM" src="https://github.com/user-attachments/assets/1871af58-ce58-4c78-97d3-7c1502ab77ba" />


### Additional Changes

- [ ] This PR modifies the API contract
- [ ] This PR modifies the database schema
- [ ] This PR modifies application configuration/environment variables

<!--
Provide links to the files with corresponding changes.

Following are the paths where you can find config files:
1. `config`
2. `crates/router/src/configs`
3. `loadtest/config`
-->


## 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).
-->


## 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)?
-->


## 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
- [ ] I added unit tests for my changes where possible
