diff --git a/CHANGELOG.md b/CHANGELOG.md
index b311c1fe7..3d0281313 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,27 @@
+## [0.101.3](https://github.com/juspay/hyperswitch-web/compare/v0.101.2...v0.101.3) (2024-11-07)
+
+## [0.101.2](https://github.com/juspay/hyperswitch-web/compare/v0.101.1...v0.101.2) (2024-11-07)
+
+## [0.101.1](https://github.com/juspay/hyperswitch-web/compare/v0.101.0...v0.101.1) (2024-11-07)
+
+# [0.101.0](https://github.com/juspay/hyperswitch-web/compare/v0.100.1...v0.101.0) (2024-11-07)
+
+
+### Features
+
+* added dynamic fields support for sepa bank transfer ([#775](https://github.com/juspay/hyperswitch-web/issues/775)) ([52d2d15](https://github.com/juspay/hyperswitch-web/commit/52d2d15ed2b2b8ed364a81fe9bbd3dfbd64c0cec))
+
+## [0.100.1](https://github.com/juspay/hyperswitch-web/compare/v0.100.0...v0.100.1) (2024-11-06)
+
+# [0.100.0](https://github.com/juspay/hyperswitch-web/compare/v0.99.6...v0.100.0) (2024-11-06)
+
+
+### Features
+
+* add dynamic fields support for affirm ([#776](https://github.com/juspay/hyperswitch-web/issues/776)) ([e55e533](https://github.com/juspay/hyperswitch-web/commit/e55e533a197efad11c9b8cceb4b06c672a365dfe))
+
+## [0.99.6](https://github.com/juspay/hyperswitch-web/compare/v0.99.5...v0.99.6) (2024-11-06)
+
 ## [0.99.5](https://github.com/juspay/hyperswitch-web/compare/v0.99.4...v0.99.5) (2024-11-06)
 
 ## [0.99.4](https://github.com/juspay/hyperswitch-web/compare/v0.99.3...v0.99.4) (2024-11-05)
diff --git a/cypress-tests/cypress/e2e/external-3DS-netcetera-e2e-test.cy.ts b/cypress-tests/cypress/e2e/external-3DS-netcetera-e2e-test.cy.ts
new file mode 100644
index 000000000..333ceb201
--- /dev/null
+++ b/cypress-tests/cypress/e2e/external-3DS-netcetera-e2e-test.cy.ts
@@ -0,0 +1,81 @@
+import * as testIds from "../../../src/Utilities/TestUtils.bs";
+import { getClientURL, netceteraChallengeTestCard, createPaymentBody, changeObjectKeyValue, connectorProfileIdMapping, connectorEnum } from "../support/utils";
+describe("External 3DS using Netcetera Checks", () => {
+    let getIframeBody: () => Cypress.Chainable<JQuery<HTMLBodyElement>>;
+    const publishableKey = Cypress.env('HYPERSWITCH_PUBLISHABLE_KEY')
+    const secretKey = Cypress.env('HYPERSWITCH_SECRET_KEY')
+    changeObjectKeyValue(createPaymentBody, "profile_id", connectorProfileIdMapping.get(connectorEnum.NETCETERA))
+    changeObjectKeyValue(createPaymentBody, "request_external_three_ds_authentication", true)
+    changeObjectKeyValue(createPaymentBody, "authentication_type", "three_ds")
+    let iframeSelector =
+        "#orca-payment-element-iframeRef-orca-elements-payment-element-payment-element";
+
+    beforeEach(() => {
+        getIframeBody = () => cy.iframe(iframeSelector);
+        cy.createPaymentIntent(secretKey, createPaymentBody).then(() => {
+            cy.getGlobalState("clientSecret").then((clientSecret) => {
+
+                cy.visit(getClientURL(clientSecret, publishableKey));
+            });
+
+        })
+    });
+
+
+    it("title rendered correctly", () => {
+        cy.contains("Hyperswitch Unified Checkout").should("be.visible");
+    });
+
+    it("orca-payment-element iframe loaded", () => {
+        cy.get(
+            "#orca-payment-element-iframeRef-orca-elements-payment-element-payment-element"
+        )
+            .should("be.visible")
+            .its("0.contentDocument")
+            .its("body");
+    });
+
+
+    it('If the user completes the challenge, the payment should be successful.', () => {
+        getIframeBody().find(`[data-testid=${testIds.addNewCardIcon}]`).click()
+        getIframeBody().find(`[data-testid=${testIds.cardNoInputTestId}]`).type(netceteraChallengeTestCard)
+        getIframeBody().find(`[data-testid=${testIds.expiryInputTestId}]`).type("0444")
+        cy.wait(1000)
+        getIframeBody().find(`[data-testid=${testIds.cardCVVInputTestId}]`).type("1234")
+        getIframeBody().get("#submit").click();
+        cy.wait(4000)
+
+        cy.nestedIFrame("#threeDsAuthFrame", ($body) => {
+            cy.wrap($body).find('#otp')
+                .type('1234')
+
+            cy.wrap($body).find('#sendOtp')
+                .click()
+            cy.contains("Thanks for your order!").should("be.visible");
+        })
+
+    })
+
+    it('If the user closes the challenge, the payment should fail.', () => {
+        getIframeBody().find(`[data-testid=${testIds.addNewCardIcon}]`).click()
+        getIframeBody().find(`[data-testid=${testIds.cardNoInputTestId}]`).type(netceteraChallengeTestCard)
+        getIframeBody().find(`[data-testid=${testIds.expiryInputTestId}]`).type("0444")
+        cy.wait(1000)
+        getIframeBody().find(`[data-testid=${testIds.cardCVVInputTestId}]`).type("1234")
+        getIframeBody().get("#submit").click();
+        cy.wait(4000)
+
+        cy.nestedIFrame("#threeDsAuthFrame", ($body) => {
+            cy.wrap($body)
+                .find('#cancel')
+                .click()
+            cy.contains("Payment Failed!").should("be.visible");
+        })
+    })
+
+
+})
+
+
+
+
diff --git a/cypress-tests/cypress/support/commands.ts b/cypress-tests/cypress/support/commands.ts
index fe84834c0..ba44cde2b 100644
--- a/cypress-tests/cypress/support/commands.ts
+++ b/cypress-tests/cypress/support/commands.ts
@@ -173,3 +173,11 @@ Cypress.Commands.add("createPaymentIntent", (secretKey: string, createPaymentBod
 Cypress.Commands.add("getGlobalState", (key: any) => {
   return globalState[key];
 });
+
+Cypress.Commands.add("nestedIFrame", (selector, callback) => {
+  cy.iframe("#orca-fullscreen").find(selector).should("exist").should("be.visible").then(($ele) => {
+    const $body =
+      $ele.contents().find('body')
+    callback($body);
+  })
+});
\ No newline at end of file
diff --git a/cypress-tests/cypress/support/types.ts b/cypress-tests/cypress/support/types.ts
index d1db388d1..1ad709b50 100644
--- a/cypress-tests/cypress/support/types.ts
+++ b/cypress-tests/cypress/support/types.ts
@@ -26,6 +26,7 @@ declare global {
             ): Chainable<JQuery<HTMLElement>>
             createPaymentIntent(secretKey: string, createPaymentBody: Record<string, any>): Chainable<Response<any>>
             getGlobalState(key: string): Chainable<Response<any>>
+            nestedIFrame(selector: string, callback: (body: Chainable<JQuery<HTMLElement>>) => void): Chainable<void>;
         }
     }
 }
\ No newline at end of file
diff --git a/cypress-tests/cypress/support/utils.ts b/cypress-tests/cypress/support/utils.ts
index 496d55606..18a484a01 100644
--- a/cypress-tests/cypress/support/utils.ts
+++ b/cypress-tests/cypress/support/utils.ts
@@ -6,15 +6,17 @@ export const getClientURL = (clientSecret, publishableKey) => {
   return `${CLIENT_BASE_URL}?isCypressTestMode=true&clientSecret=${clientSecret}&publishableKey=${publishableKey}`;
 }
 
-export const enum connectorEnum{
+export const enum connectorEnum {
   TRUSTPAY,
   ADYEN,
-  STRIPE
+  STRIPE,
+  NETCETERA
 }
 export const connectorProfileIdMapping = new Map<connectorEnum, string>([
   [connectorEnum.TRUSTPAY, "pro_eP323T9e4ApKpilWBfPA"],
   [connectorEnum.ADYEN, "pro_Kvqzu8WqBZsT1OjHlCj4"],
   [connectorEnum.STRIPE, "pro_5fVcCxU8MFTYozgtf0P8"],
+  [connectorEnum.NETCETERA, "pro_h9VHXnJx8s6W4KSZfSUL"]
 ]);
 
 export const createPaymentBody = {
@@ -78,7 +80,7 @@ export const createPaymentBody = {
 
 }
 
-export const changeObjectKeyValue = (object: Record<string, any>, key: string, value: string) => {
+export const changeObjectKeyValue = (object: Record<string, any>, key: string, value: boolean | string) => {
   object[key] = value
 }
 
@@ -128,3 +130,4 @@ export const adyenTestCard = "4917610000000000";
 export const bluesnapTestCard = "4000000000001091";
 export const amexTestCard = "378282246310005"
 export const visaTestCard = "4242424242424242";
+export const netceteraChallengeTestCard = "348638267931507";
\ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
index facd283d8..76d00eb7f 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
 {
   "name": "orca-payment-page",
-  "version": "0.99.5",
+  "version": "0.101.3",
   "lockfileVersion": 3,
   "requires": true,
   "packages": {
     "": {
       "name": "orca-payment-page",
-      "version": "0.99.5",
+      "version": "0.101.3",
       "hasInstallScript": true,
       "dependencies": {
         "@glennsl/rescript-fetch": "^0.2.0",
diff --git a/package.json b/package.json
index e87738c56..d6b56eb7b 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "orca-payment-page",
-  "version": "0.99.5",
+  "version": "0.101.3",
   "main": "index.js",
   "private": true,
   "dependencies": {
diff --git a/src/Components/DynamicFields.res b/src/Components/DynamicFields.res
index ee1fe6e3d..2c6f9ea30 100644
--- a/src/Components/DynamicFields.res
+++ b/src/Components/DynamicFields.res
@@ -1,4 +1,3 @@
-open RecoilAtoms
 @react.component
 let make = (
   ~paymentType,
@@ -12,7 +11,9 @@ let make = (
   ~cvcProps=None,
   ~isBancontact=false,
 ) => {
+  open DynamicFieldsUtils
   open Utils
+  open RecoilAtoms
   let paymentMethodListValue = Recoil.useRecoilValueFromAtom(PaymentUtils.paymentMethodListValue)
 
   React.useEffect(() => {
@@ -41,10 +42,8 @@ let make = (
 
       paymentMethodTypes.required_fields
       ->Array.concat(creditRequiredFields)
-      ->DynamicFieldsUtils.removeRequiredFieldsDuplicates
-    } else if (
-      PaymentMethodsRecord.dynamicFieldsEnabledPaymentMethods->Array.includes(paymentMethodType)
-    ) {
+      ->removeRequiredFieldsDuplicates
+    } else if dynamicFieldsEnabledPaymentMethods->Array.includes(paymentMethodType) {
       paymentMethodTypes.required_fields
     } else {
       []
@@ -52,9 +51,7 @@ let make = (
   }, (paymentMethod, paymentMethodTypes.required_fields, paymentMethodType))
 
   let requiredFields = React.useMemo(() => {
-    requiredFieldsWithBillingDetails->DynamicFieldsUtils.removeBillingDetailsIfUseBillingAddress(
-      billingAddress,
-    )
+    requiredFieldsWithBillingDetails->removeBillingDetailsIfUseBillingAddress(billingAddress)
   }, [requiredFieldsWithBillingDetails])
 
   let isAllStoredCardsHaveName = React.useMemo(() => {
@@ -69,7 +66,7 @@ let make = (
       ~isSavedCardFlow,
       ~isAllStoredCardsHaveName,
     )
-    ->DynamicFieldsUtils.updateDynamicFields(billingAddress)
+    ->updateDynamicFields(billingAddress)
     ->Belt.SortArray.stableSortBy(PaymentMethodsRecord.sortPaymentMethodFields)
     //<...>//
   }, (requiredFields, isAllStoredCardsHaveName, isSavedCardFlow))
@@ -255,7 +252,7 @@ let make = (
     }
   }
 
-  DynamicFieldsUtils.useRequiredFieldsEmptyAndValid(
+  useRequiredFieldsEmptyAndValid(
     ~requiredFields,
     ~fieldsArr,
     ~countryNames,
@@ -268,14 +265,14 @@ let make = (
     ~cvcNumber,
   )
 
-  DynamicFieldsUtils.useSetInitialRequiredFields(
+  useSetInitialRequiredFields(
     ~requiredFields={
       billingAddress.usePrefilledValues === Auto ? requiredFieldsWithBillingDetails : requiredFields
     },
     ~paymentMethodType,
   )
 
-  DynamicFieldsUtils.useRequiredFieldsBody(
+  useRequiredFieldsBody(
     ~requiredFields,
     ~paymentMethodType,
     ~cardNumber,
@@ -286,7 +283,7 @@ let make = (
     ~setRequiredFieldsBody,
   )
 
-  let submitCallback = DynamicFieldsUtils.useSubmitCallback()
+  let submitCallback = useSubmitCallback()
   useSubmitPaymentData(submitCallback)
 
   let bottomElement = <InfoElement />
@@ -307,11 +304,11 @@ let make = (
   }
 
   let dynamicFieldsToRenderOutsideBilling = React.useMemo(() => {
-    fieldsArr->Array.filter(DynamicFieldsUtils.isFieldTypeToRenderOutsideBilling)
+    fieldsArr->Array.filter(isFieldTypeToRenderOutsideBilling)
   }, [fieldsArr])
 
   let dynamicFieldsToRenderInsideBilling = React.useMemo(() => {
-    fieldsArr->Array.filter(field => !(field->DynamicFieldsUtils.isFieldTypeToRenderOutsideBilling))
+    fieldsArr->Array.filter(field => !(field->isFieldTypeToRenderOutsideBilling))
   }, [fieldsArr])
 
   let isInfoElementPresent = dynamicFieldsToRenderInsideBilling->Array.includes(InfoElement)
diff --git a/src/Components/SavedMethods.res b/src/Components/SavedMethods.res
index ae2dbdf1f..377deb887 100644
--- a/src/Components/SavedMethods.res
+++ b/src/Components/SavedMethods.res
@@ -147,11 +147,7 @@ let make = (
           | _ =>
             // TODO - To be replaced with proper error message
             intent(
-              ~bodyArr=savedPaymentMethodBody
-              ->getJsonFromArrayOfJson
-              ->flattenObject(true)
-              ->mergeTwoFlattenedJsonDicts(requiredFieldsBody)
-              ->getArrayOfTupleFromDict,
+              ~bodyArr=savedPaymentMethodBody->mergeAndFlattenToTuples(requiredFieldsBody),
               ~confirmParam=confirm.confirmParams,
               ~handleUserError=false,
               ~manualRetry=isManualRetryEnabled,
@@ -168,11 +164,7 @@ let make = (
           | _ =>
             // TODO - To be replaced with proper error message
             intent(
-              ~bodyArr=savedPaymentMethodBody
-              ->getJsonFromArrayOfJson
-              ->flattenObject(true)
-              ->mergeTwoFlattenedJsonDicts(requiredFieldsBody)
-              ->getArrayOfTupleFromDict,
+              ~bodyArr=savedPaymentMethodBody->mergeAndFlattenToTuples(requiredFieldsBody),
               ~confirmParam=confirm.confirmParams,
               ~handleUserError=false,
               ~manualRetry=isManualRetryEnabled,
@@ -180,11 +172,7 @@ let make = (
           }
         | _ =>
           intent(
-            ~bodyArr=savedPaymentMethodBody
-            ->getJsonFromArrayOfJson
-            ->flattenObject(true)
-            ->mergeTwoFlattenedJsonDicts(requiredFieldsBody)
-            ->getArrayOfTupleFromDict,
+            ~bodyArr=savedPaymentMethodBody->mergeAndFlattenToTuples(requiredFieldsBody),
             ~confirmParam=confirm.confirmParams,
             ~handleUserError=false,
             ~manualRetry=isManualRetryEnabled,
diff --git a/src/Hooks/Fetcher.res b/src/Hooks/Fetcher.res
deleted file mode 100644
index ebd789fdb..000000000
--- a/src/Hooks/Fetcher.res
+++ /dev/null
@@ -1,22 +0,0 @@
-type match
-type pathname = {match: match}
-type url = {pathname: pathname}
-@new external url: string => url = "URL"
-
-let useFetcher = fileName => {
-  let _url = RescriptReactRouter.useUrl()
-  let (optionalJson, setJson) = React.useState(() => None)
-  React.useEffect(() => {
-    open Promise
-    Fetch.get(`${Window.Location.hostname}/json/${fileName}.json`)
-    ->then(Fetch.Response.json)
-    ->thenResolve(json => {
-      setJson(_ => Some(json))
-    })
-    ->ignore
-
-    None
-  }, [fileName])
-
-  optionalJson
-}
diff --git a/src/PaymentMethodCollectElement.res b/src/PaymentMethodCollectElement.res
index 8a3679d25..366750c6a 100644
--- a/src/PaymentMethodCollectElement.res
+++ b/src/PaymentMethodCollectElement.res
@@ -74,7 +74,7 @@ let make = (~integrateError, ~logger) => {
         setTimeout(() => {
           clearInterval(interval)
           // Append query params and redirect
-          let url = PaymentHelpers.urlSearch(returnUrl)
+          let url = URLModule.makeUrl(returnUrl)
           url.searchParams.set("payout_id", options.payoutId)
           url.searchParams.set("status", statusInfo.status->getPayoutStatusString)
           Utils.openUrl(url.href)
diff --git a/src/Payments/ACHBankTransfer.res b/src/Payments/ACHBankTransfer.res
index c4665addb..c7fc5b913 100644
--- a/src/Payments/ACHBankTransfer.res
+++ b/src/Payments/ACHBankTransfer.res
@@ -10,7 +10,8 @@ let make = (~paymentType: CardThemeType.mode) => {
   let intent = PaymentHelpers.usePaymentIntent(Some(loggerState), BankTransfer)
   let (email, _) = Recoil.useLoggedRecoilState(userEmailAddress, "email", loggerState)
   let setComplete = Recoil.useSetRecoilState(fieldsComplete)
-  let paymentMethodListValue = Recoil.useRecoilValueFromAtom(PaymentUtils.paymentMethodListValue)
+
+  let (requiredFieldsBody, setRequiredFieldsBody) = React.useState(_ => Dict.make())
 
   let complete = email.value != "" && email.isValid->Option.getOr(false)
   let empty = email.value == ""
@@ -27,9 +28,12 @@ let make = (~paymentType: CardThemeType.mode) => {
     let confirm = json->getDictFromJson->ConfirmType.itemToObjMapper
     if confirm.doSubmit {
       if complete {
-        let (connectors, _) = paymentMethodListValue->PaymentUtils.getConnectors(BankTransfer(ACH))
+        let bodyArr =
+          PaymentBody.dynamicPaymentBody("bank_transfer", "ach")->mergeAndFlattenToTuples(
+            requiredFieldsBody,
+          )
         intent(
-          ~bodyArr=PaymentBody.achBankTransferBody(~email=email.value, ~connectors),
+          ~bodyArr,
           ~confirmParam=confirm.confirmParams,
           ~handleUserError=false,
           ~iframeId,
@@ -43,7 +47,9 @@ let make = (~paymentType: CardThemeType.mode) => {
   useSubmitPaymentData(submitCallback)
 
   <div className="flex flex-col animate-slowShow" style={gridGap: themeObj.spacingTab}>
-    <EmailPaymentInput paymentType />
+    <DynamicFields
+      paymentType paymentMethod="bank_transfer" paymentMethodType="ach" setRequiredFieldsBody
+    />
     <Surcharge paymentMethod="bank_transfer" paymentMethodType="ach" />
     <InfoElement />
   </div>
diff --git a/src/Payments/CardPayment.res b/src/Payments/CardPayment.res
index da4da5c98..05c540660 100644
--- a/src/Payments/CardPayment.res
+++ b/src/Payments/CardPayment.res
@@ -163,11 +163,7 @@ let make = (
       if validFormat && (showFields || isBancontact) {
         intent(
           ~bodyArr={
-            (isBancontact ? banContactBody : cardBody)
-            ->getJsonFromArrayOfJson
-            ->flattenObject(true)
-            ->mergeTwoFlattenedJsonDicts(requiredFieldsBody)
-            ->getArrayOfTupleFromDict
+            (isBancontact ? banContactBody : cardBody)->mergeAndFlattenToTuples(requiredFieldsBody)
           },
           ~confirmParam=confirm.confirmParams,
           ~handleUserError=false,
diff --git a/src/Payments/KlarnaSDK.res b/src/Payments/KlarnaSDK.res
index a53771a7b..ea7ab5303 100644
--- a/src/Payments/KlarnaSDK.res
+++ b/src/Payments/KlarnaSDK.res
@@ -100,11 +100,7 @@ let make = (~sessionObj: SessionsType.token) => {
                       )
 
                       let body = {
-                        klarnaSDKBody
-                        ->getJsonFromArrayOfJson
-                        ->flattenObject(true)
-                        ->mergeTwoFlattenedJsonDicts(requiredFieldsBody)
-                        ->getArrayOfTupleFromDict
+                        klarnaSDKBody->mergeAndFlattenToTuples(requiredFieldsBody)
                       }
 
                       res.approved
diff --git a/src/Payments/PaymentMethodsRecord.res b/src/Payments/PaymentMethodsRecord.res
index d235c6bec..050542ba3 100644
--- a/src/Payments/PaymentMethodsRecord.res
+++ b/src/Payments/PaymentMethodsRecord.res
@@ -661,27 +661,6 @@ let getFieldType = (dict, isBancontact) => {
   }
 }
 
-let dynamicFieldsEnabledPaymentMethods = [
-  "crypto_currency",
-  "debit",
-  "credit",
-  "blik",
-  "google_pay",
-  "apple_pay",
-  "bancontact_card",
-  "open_banking_uk",
-  "eps",
-  "ideal",
-  "sofort",
-  "pix_transfer",
-  "giropay",
-  "local_bank_transfer_transfer",
-  "afterpay_clearpay",
-  "mifinity",
-  "upi_collect",
-  "sepa",
-]
-
 let getIsBillingField = requiredFieldType => {
   switch requiredFieldType {
   | AddressLine1
diff --git a/src/Payments/PaymentMethodsWrapper.res b/src/Payments/PaymentMethodsWrapper.res
index 857a796e8..cb4cf0627 100644
--- a/src/Payments/PaymentMethodsWrapper.res
+++ b/src/Payments/PaymentMethodsWrapper.res
@@ -84,12 +84,7 @@ let make = (~paymentType: CardThemeType.mode, ~paymentMethodName: string) => {
               phoneNumber.countryCode->Option.getOr("") ++ phoneNumber.value,
             ),
             ~paymentExperience=paymentFlow,
-          )
-          ->Dict.fromArray
-          ->JSON.Encode.object
-          ->flattenObject(true)
-          ->mergeTwoFlattenedJsonDicts(requiredFieldsBody)
-          ->getArrayOfTupleFromDict
+          )->mergeAndFlattenToTuples(requiredFieldsBody)
 
         intent(
           ~bodyArr=body,
diff --git a/src/Payments/PaypalSDKHelpers.res b/src/Payments/PaypalSDKHelpers.res
index 96603bf72..d50d0a33a 100644
--- a/src/Payments/PaypalSDKHelpers.res
+++ b/src/Payments/PaypalSDKHelpers.res
@@ -1,5 +1,4 @@
 open PaypalSDKTypes
-open Promise
 open Utils
 open TaxCalculation
 
@@ -11,13 +10,13 @@ let loadPaypalSDK = (
   ~isManualRetryEnabled,
   ~paymentMethodListValue,
   ~isGuestCustomer,
-  ~postSessionTokens: PaymentHelpers.paymentIntent,
+  ~postSessionTokens: PaymentHelpersTypes.paymentIntent,
   ~options: PaymentType.options,
   ~publishableKey,
   ~paymentMethodTypes,
   ~stateJson,
-  ~confirm: PaymentHelpers.paymentIntent,
-  ~completeAuthorize: PaymentHelpers.completeAuthorize,
+  ~confirm: PaymentHelpersTypes.paymentIntent,
+  ~completeAuthorize: PaymentHelpersTypes.completeAuthorize,
   ~handleCloseLoader,
   ~areOneClickWalletsRendered: (
     RecoilAtoms.areOneClickWalletsRendered => RecoilAtoms.areOneClickWalletsRendered
@@ -57,10 +56,10 @@ let loadPaypalSDK = (
     style: buttonStyle,
     fundingSource: paypal["FUNDING"]["PAYPAL"],
     createOrder: () => {
-      Utils.makeOneClickHandlerPromise(sdkHandleIsThere)->then(result => {
+      makeOneClickHandlerPromise(sdkHandleIsThere)->Promise.then(result => {
         let result = result->JSON.Decode.bool->Option.getOr(false)
         if result {
-          Utils.messageParentWindow([
+          messageParentWindow([
             ("fullscreen", true->JSON.Encode.bool),
             ("param", "paymentloader"->JSON.Encode.string),
             ("iframeId", iframeId->JSON.Encode.string),
@@ -84,9 +83,9 @@ let loadPaypalSDK = (
                 ~handleUserError=true,
                 ~intentCallback=val => {
                   val
-                  ->Utils.getDictFromJson
-                  ->Utils.getDictFromDict("nextActionData")
-                  ->Utils.getString("order_id", "")
+                  ->getDictFromJson
+                  ->getDictFromDict("nextActionData")
+                  ->getString("order_id", "")
                   ->resolve
                 },
                 ~manualRetry=isManualRetryEnabled,
@@ -99,8 +98,7 @@ let loadPaypalSDK = (
                   publishableKey,
                 },
                 ~handleUserError=true,
-                ~intentCallback=val =>
-                  val->Utils.getDictFromJson->Utils.getString("orderId", "")->resolve,
+                ~intentCallback=val => val->getDictFromJson->getString("orderId", "")->resolve,
                 ~manualRetry=isManualRetryEnabled,
               )
             }
@@ -111,7 +109,7 @@ let loadPaypalSDK = (
             ~eventName=PAYPAL_SDK_FLOW,
             ~paymentMethod="PAYPAL",
           )
-          resolve("")
+          Promise.resolve("")
         }
       })
     },
@@ -141,23 +139,23 @@ let loadPaypalSDK = (
           ~sessionId=data->getDictFromJson->Dict.get("orderID"),
         )
       } else {
-        Js.Json.null->Js.Promise.resolve
+        JSON.Encode.null->Promise.resolve
       }
     },
     onApprove: (_data, actions) => {
       if !options.readOnly {
         actions.order.get()
-        ->then(val => {
+        ->Promise.then(val => {
           let purchaseUnit =
             val
-            ->Utils.getDictFromJson
-            ->Utils.getArray("purchase_units")
+            ->getDictFromJson
+            ->getArray("purchase_units")
             ->Array.get(0)
             ->Option.flatMap(JSON.Decode.object)
             ->Option.getOr(Dict.make())
           let payerDetails =
             val
-            ->Utils.getDictFromJson
+            ->getDictFromJson
             ->Dict.get("payer")
             ->Option.flatMap(JSON.Decode.object)
             ->Option.getOr(Dict.make())
@@ -172,7 +170,7 @@ let loadPaypalSDK = (
 
           let (connectors, _) =
             paymentMethodListValue->PaymentUtils.getConnectors(Wallets(Paypal(SDK)))
-          let orderId = val->getDictFromJson->Utils.getString("id", "")
+          let orderId = val->getDictFromJson->getString("id", "")
           let body = PaymentBody.paypalSdkBody(~token=orderId, ~connectors)
           let modifiedPaymentBody = PaymentUtils.appendedCustomerAcceptance(
             ~isGuestCustomer,
@@ -183,8 +181,8 @@ let loadPaypalSDK = (
           let bodyArr =
             requiredFieldsBody
             ->JSON.Encode.object
-            ->Utils.unflattenObject
-            ->Utils.getArrayOfTupleFromDict
+            ->unflattenObject
+            ->getArrayOfTupleFromDict
 
           let confirmBody = bodyArr->Array.concatMany([modifiedPaymentBody])
           Promise.make((_resolve, _) => {
@@ -234,7 +232,7 @@ let loadBraintreePaypalSdk = (
   ~iframeId,
   ~paymentMethodListValue,
   ~isGuestCustomer,
-  ~intent: PaymentHelpers.paymentIntent,
+  ~intent: PaymentHelpersTypes.paymentIntent,
   ~options: PaymentType.options,
   ~orderDetails,
   ~publishableKey,
@@ -251,8 +249,8 @@ let loadBraintreePaypalSdk = (
     ~eventName=PAYPAL_SDK_FLOW,
     ~paymentMethod="PAYPAL",
   )
-  Utils.makeOneClickHandlerPromise(sdkHandleOneClickConfirmPayment)
-  ->then(result => {
+  makeOneClickHandlerPromise(sdkHandleOneClickConfirmPayment)
+  ->Promise.then(result => {
     let result = result->JSON.Decode.bool->Option.getOr(false)
     if result {
       braintree.client.create({authorization: token}, (clientErr, clientInstance) => {
@@ -276,7 +274,7 @@ let loadBraintreePaypalSdk = (
                   fundingSource: paypal["FUNDING"]["PAYPAL"],
                   createBillingAgreement: () => {
                     //Paypal Clicked
-                    Utils.messageParentWindow([
+                    messageParentWindow([
                       ("fullscreen", true->JSON.Encode.bool),
                       ("param", "paymentloader"->JSON.Encode.string),
                       ("iframeId", iframeId->JSON.Encode.string),
@@ -301,12 +299,7 @@ let loadBraintreePaypalSdk = (
                               ~statesList=stateJson,
                             )
 
-                            let paypalBody =
-                              body
-                              ->Utils.getJsonFromArrayOfJson
-                              ->Utils.flattenObject(true)
-                              ->Utils.mergeTwoFlattenedJsonDicts(requiredFieldsBody)
-                              ->Utils.getArrayOfTupleFromDict
+                            let paypalBody = body->mergeAndFlattenToTuples(requiredFieldsBody)
 
                             let modifiedPaymentBody = PaymentUtils.appendedCustomerAcceptance(
                               ~isGuestCustomer,
@@ -345,7 +338,7 @@ let loadBraintreePaypalSdk = (
         )
       })->ignore
     }
-    resolve()
+    Promise.resolve()
   })
   ->ignore
 }
diff --git a/src/Payments/PreMountLoader.res b/src/Payments/PreMountLoader.res
index 8f976ca43..1c6ecbc57 100644
--- a/src/Payments/PreMountLoader.res
+++ b/src/Payments/PreMountLoader.res
@@ -1,64 +1,72 @@
-@react.component
-let make = (
-  ~sessionId,
-  ~publishableKey,
-  ~clientSecret,
-  ~endpoint,
-  ~ephemeralKey,
-  ~hyperComponentName: Types.hyperComponentName,
-  ~merchantHostname,
-  ~customPodUri,
-) => {
-  open Utils
-  let (paymentMethodsResponseSent, setPaymentMethodsResponseSent) = React.useState(_ => false)
-  let (
-    customerPaymentMethodsResponseSent,
-    setCustomerPaymentMethodsResponseSent,
-  ) = React.useState(_ => false)
-  let (savedPaymentMethodsResponseSent, setSavedPaymentMethodsResponseSent) = React.useState(_ =>
-    false
-  )
-  let (sessionTokensResponseSent, setSessionTokensResponseSent) = React.useState(_ => false)
-  let logger = HyperLogger.make(
-    ~sessionId,
-    ~source=Loader,
-    ~merchantId=publishableKey,
-    ~clientSecret,
-  )
+let sendPromiseData = (promise, key) => {
+  let executePromise = async () => {
+    let response = try {
+      await promise
+    } catch {
+    | _ => JSON.Encode.null
+    }
+    Utils.messageParentWindow([("response", response), ("data", key->JSON.Encode.string)])
+  }
+  executePromise()->ignore
+}
+
+let useMessageHandler = getPromisesAndHandler => {
+  React.useEffect(_ => {
+    let (promises, messageHandler) = getPromisesAndHandler()
+    let setupMessageListener = _ => {
+      Utils.messageParentWindow([("preMountLoaderIframeMountedCallback", true->JSON.Encode.bool)])
+      Window.addEventListener("message", messageHandler)
+    }
+
+    let cleanupMessageListener = _ => {
+      Utils.messageParentWindow([("preMountLoaderIframeUnMount", true->JSON.Encode.bool)])
+      Window.removeEventListener("message", messageHandler)
+    }
+
+    setupMessageListener()
+
+    let executeAllPromises = async () => {
+      try {
+        let _ = await Promise.all(promises)
+      } catch {
+      | error => Console.error2("Error in message handler:", error)
+      }
+      cleanupMessageListener()
+    }
+    executeAllPromises()->ignore
 
-  let (
-    paymentMethodsResponse,
-    customerPaymentMethodsResponse,
-    sessionTokensResponse,
-    savedPaymentMethodsResponse,
-  ) = React.useMemo0(() => {
-    let paymentMethodsResponse = switch hyperComponentName {
-    | Elements =>
-      PaymentHelpers.fetchPaymentMethodList(
+    Some(cleanupMessageListener)
+  }, [])
+}
+
+module PreMountLoaderForElements = {
+  @react.component
+  let make = (
+    ~logger,
+    ~publishableKey,
+    ~clientSecret,
+    ~endpoint,
+    ~merchantHostname,
+    ~customPodUri,
+  ) => {
+    useMessageHandler(() => {
+      let paymentMethodsPromise = PaymentHelpers.fetchPaymentMethodList(
         ~clientSecret,
         ~publishableKey,
         ~logger,
         ~customPodUri,
         ~endpoint,
       )
-    | _ => JSON.Encode.null->Promise.resolve
-    }
 
-    let customerPaymentMethodsResponse = switch hyperComponentName {
-    | Elements =>
-      PaymentHelpers.fetchCustomerPaymentMethodList(
+      let customerPaymentMethodsPromise = PaymentHelpers.fetchCustomerPaymentMethodList(
         ~clientSecret,
         ~publishableKey,
         ~optLogger=Some(logger),
         ~customPodUri,
         ~endpoint,
       )
-    | _ => JSON.Encode.null->Promise.resolve
-    }
 
-    let sessionTokensResponse = switch hyperComponentName {
-    | Elements =>
-      PaymentHelpers.fetchSessions(
+      let sessionTokensPromise = PaymentHelpers.fetchSessions(
         ~clientSecret,
         ~publishableKey,
         ~optLogger=Some(logger),
@@ -66,101 +74,78 @@ let make = (
         ~endpoint,
         ~merchantHostname,
       )
-    | _ => JSON.Encode.null->Promise.resolve
-    }
 
-    let savedPaymentMethodsResponse = switch hyperComponentName {
-    | PaymentMethodsManagementElements =>
-      PaymentHelpers.fetchSavedPaymentMethodList(
+      let messageHandler = (ev: Window.event) => {
+        open Utils
+        let dict = ev.data->safeParse->getDictFromJson
+        if dict->isKeyPresentInDict("sendPaymentMethodsResponse") {
+          paymentMethodsPromise->sendPromiseData("payment_methods")
+        } else if dict->isKeyPresentInDict("sendCustomerPaymentMethodsResponse") {
+          customerPaymentMethodsPromise->sendPromiseData("customer_payment_methods")
+        } else if dict->isKeyPresentInDict("sendSessionTokensResponse") {
+          sessionTokensPromise->sendPromiseData("session_tokens")
+        }
+      }
+
+      let promises = [paymentMethodsPromise, customerPaymentMethodsPromise, sessionTokensPromise]
+      (promises, messageHandler)
+    })
+
+    React.null
+  }
+}
+
+module PreMountLoaderForPMMElements = {
+  @react.component
+  let make = (~logger, ~endpoint, ~ephemeralKey, ~customPodUri) => {
+    useMessageHandler(() => {
+      let savedPaymentMethodsPromise = PaymentHelpers.fetchSavedPaymentMethodList(
         ~ephemeralKey,
         ~optLogger=Some(logger),
         ~customPodUri,
         ~endpoint,
       )
-    | _ => JSON.Encode.null->Promise.resolve
-    }
 
-    (
-      paymentMethodsResponse,
-      customerPaymentMethodsResponse,
-      sessionTokensResponse,
-      savedPaymentMethodsResponse,
-    )
-  })
-
-  let sendPromiseData = (promise, key) => {
-    open Promise
-    promise
-    ->then(res => {
-      messageParentWindow([("response", res), ("data", key->JSON.Encode.string)])
-      switch key {
-      | "payment_methods" => setPaymentMethodsResponseSent(_ => true)
-      | "session_tokens" => setSessionTokensResponseSent(_ => true)
-      | "customer_payment_methods" => setCustomerPaymentMethodsResponseSent(_ => true)
-      | "saved_payment_methods" => setSavedPaymentMethodsResponseSent(_ => true)
-      | _ => ()
+      let messageHandler = (ev: Window.event) => {
+        open Utils
+        let dict = ev.data->safeParse->getDictFromJson
+        if dict->isKeyPresentInDict("sendSavedPaymentMethodsResponse") {
+          savedPaymentMethodsPromise->sendPromiseData("saved_payment_methods")
+        }
       }
-      resolve()
-    })
-    ->catch(_err => {
-      messageParentWindow([("response", JSON.Encode.null), ("data", key->JSON.Encode.string)])
-      resolve()
+
+      let promises = [savedPaymentMethodsPromise]
+      (promises, messageHandler)
     })
-    ->ignore
-  }
 
-  let handle = (ev: Window.event) => {
-    let json = ev.data->safeParse
-    let dict = json->Utils.getDictFromJson
-    if dict->Dict.get("sendPaymentMethodsResponse")->Option.isSome {
-      paymentMethodsResponse->sendPromiseData("payment_methods")
-    } else if dict->Dict.get("sendCustomerPaymentMethodsResponse")->Option.isSome {
-      customerPaymentMethodsResponse->sendPromiseData("customer_payment_methods")
-    } else if dict->Dict.get("sendSessionTokensResponse")->Option.isSome {
-      sessionTokensResponse->sendPromiseData("session_tokens")
-    } else if dict->Dict.get("sendSavedPaymentMethodsResponse")->Belt.Option.isSome {
-      savedPaymentMethodsResponse->sendPromiseData("saved_payment_methods")
-    }
+    React.null
   }
+}
 
-  React.useEffect0(() => {
-    Window.addEventListener("message", handle)
-    messageParentWindow([("preMountLoaderIframeMountedCallback", true->JSON.Encode.bool)])
-    Some(
-      () => {
-        Window.removeEventListener("message", handle)
-      },
-    )
-  })
-
-  React.useEffect4(() => {
-    let handleUnmount = () => {
-      messageParentWindow([("preMountLoaderIframeUnMount", true->JSON.Encode.bool)])
-      Window.removeEventListener("message", handle)
-    }
-
-    switch hyperComponentName {
-    | Elements =>
-      if (
-        paymentMethodsResponseSent &&
-        customerPaymentMethodsResponseSent &&
-        sessionTokensResponseSent
-      ) {
-        handleUnmount()
-      }
-    | PaymentMethodsManagementElements =>
-      if savedPaymentMethodsResponseSent {
-        handleUnmount()
-      }
-    }
-
-    None
-  }, (
-    paymentMethodsResponseSent,
-    customerPaymentMethodsResponseSent,
-    sessionTokensResponseSent,
-    savedPaymentMethodsResponseSent,
-  ))
+@react.component
+let make = (
+  ~sessionId,
+  ~publishableKey,
+  ~clientSecret,
+  ~endpoint,
+  ~ephemeralKey,
+  ~hyperComponentName: Types.hyperComponentName,
+  ~merchantHostname,
+  ~customPodUri,
+) => {
+  let logger = HyperLogger.make(
+    ~sessionId,
+    ~source=Loader,
+    ~merchantId=publishableKey,
+    ~clientSecret,
+  )
 
-  React.null
+  switch hyperComponentName {
+  | Elements =>
+    <PreMountLoaderForElements
+      logger publishableKey clientSecret endpoint merchantHostname customPodUri
+    />
+  | PaymentMethodsManagementElements =>
+    <PreMountLoaderForPMMElements logger endpoint ephemeralKey customPodUri />
+  }
 }
diff --git a/src/Payments/SepaBankTransfer.res b/src/Payments/SepaBankTransfer.res
index fd88fb89b..ca543425e 100644
--- a/src/Payments/SepaBankTransfer.res
+++ b/src/Payments/SepaBankTransfer.res
@@ -4,27 +4,17 @@ open Utils
 @react.component
 let make = (~paymentType) => {
   let {iframeId} = Recoil.useRecoilValueFromAtom(keys)
-  let {fields} = Recoil.useRecoilValueFromAtom(optionAtom)
   let loggerState = Recoil.useRecoilValueFromAtom(loggerAtom)
-  let {config, themeObj, localeString} = Recoil.useRecoilValueFromAtom(configAtom)
-  let intent = PaymentHelpers.usePaymentIntent(Some(loggerState), BankTransfer)
+  let {themeObj} = Recoil.useRecoilValueFromAtom(configAtom)
   let isManualRetryEnabled = Recoil.useRecoilValueFromAtom(isManualRetryEnabled)
-  let (country, setCountry) = React.useState(_ => "France")
+  let setComplete = Recoil.useSetRecoilState(fieldsComplete)
   let (email, _) = Recoil.useLoggedRecoilState(userEmailAddress, "email", loggerState)
   let (fullName, _) = Recoil.useLoggedRecoilState(userFullName, "fullName", loggerState)
-  let showAddressDetails = PaymentType.getShowAddressDetails(
-    ~billingDetails=fields.billingDetails,
-    ~logger=loggerState,
-  )
-  let countryNames = Utils.getCountryNames(Country.country)
-  let setComplete = Recoil.useSetRecoilState(fieldsComplete)
-  let clientCountryCode =
-    Country.country
-    ->Array.find(item => item.countryName == country)
-    ->Option.getOr(Country.defaultTimeZone)
+  let intent = PaymentHelpers.usePaymentIntent(Some(loggerState), BankTransfer)
+
+  let (requiredFieldsBody, setRequiredFieldsBody) = React.useState(_ => Dict.make())
   let complete = email.value != "" && fullName.value != "" && email.isValid->Option.getOr(false)
   let empty = email.value == "" || fullName.value == ""
-  let paymentMethodListValue = Recoil.useRecoilValueFromAtom(PaymentUtils.paymentMethodListValue)
 
   UtilityHooks.useHandlePostMessages(~complete, ~empty, ~paymentType="bank_transfer")
 
@@ -38,14 +28,13 @@ let make = (~paymentType) => {
     let confirm = json->getDictFromJson->ConfirmType.itemToObjMapper
     if confirm.doSubmit {
       if complete {
-        let (connectors, _) = paymentMethodListValue->PaymentUtils.getConnectors(BankTransfer(Sepa))
+        let bodyArr =
+          PaymentBody.dynamicPaymentBody("bank_transfer", "sepa")->mergeAndFlattenToTuples(
+            requiredFieldsBody,
+          )
+
         intent(
-          ~bodyArr=PaymentBody.sepaBankTransferBody(
-            ~email=email.value,
-            ~name=fullName.value,
-            ~country=clientCountryCode.isoAlpha2,
-            ~connectors,
-          ),
+          ~bodyArr,
           ~confirmParam=confirm.confirmParams,
           ~handleUserError=false,
           ~iframeId,
@@ -55,25 +44,13 @@ let make = (~paymentType) => {
         postFailedSubmitResponse(~errortype="validation_error", ~message="Please enter all fields")
       }
     }
-  }, (email, fullName, country, isManualRetryEnabled))
+  }, (email, fullName, isManualRetryEnabled))
   useSubmitPaymentData(submitCallback)
 
-  let updatedOptionsArrayForCountry =
-    countryNames->DropdownField.updateArrayOfStringToOptionsTypeArray
-
   <div className="flex flex-col animate-slowShow" style={gridGap: themeObj.spacingTab}>
-    <EmailPaymentInput paymentType />
-    <FullNamePaymentInput paymentType={paymentType} />
-    <RenderIf condition={showAddressDetails.country == Auto}>
-      <DropdownField
-        appearance=config.appearance
-        fieldName=localeString.countryLabel
-        value=country
-        setValue=setCountry
-        disabled=false
-        options=updatedOptionsArrayForCountry
-      />
-    </RenderIf>
+    <DynamicFields
+      paymentType paymentMethod="bank_transfer" paymentMethodType="sepa" setRequiredFieldsBody
+    />
     <Surcharge paymentMethod="bank_transfer" paymentMethodType="sepa" />
     <InfoElement />
   </div>
diff --git a/src/Utilities/ApplePayHelpers.res b/src/Utilities/ApplePayHelpers.res
index b337e3ede..3a342cacd 100644
--- a/src/Utilities/ApplePayHelpers.res
+++ b/src/Utilities/ApplePayHelpers.res
@@ -7,7 +7,7 @@ let processPayment = (
   ~isThirdPartyFlow=false,
   ~isGuestCustomer,
   ~paymentMethodListValue=PaymentMethodsRecord.defaultList,
-  ~intent: PaymentHelpers.paymentIntent,
+  ~intent: PaymentHelpersTypes.paymentIntent,
   ~options: PaymentType.options,
   ~publishableKey,
   ~isManualRetryEnabled,
@@ -61,11 +61,7 @@ let getApplePayFromResponse = (
 
   let bodyDict = PaymentBody.applePayBody(~token, ~connectors)
 
-  bodyDict
-  ->getJsonFromArrayOfJson
-  ->flattenObject(true)
-  ->mergeTwoFlattenedJsonDicts(requiredFieldsBody)
-  ->getArrayOfTupleFromDict
+  bodyDict->mergeAndFlattenToTuples(requiredFieldsBody)
 }
 
 let startApplePaySession = (
@@ -261,11 +257,7 @@ let useHandleApplePayResponse = (
           let bodyArr = if isWallet {
             applePayBody
           } else {
-            applePayBody
-            ->getJsonFromArrayOfJson
-            ->flattenObject(true)
-            ->mergeTwoFlattenedJsonDicts(requiredFieldsBody)
-            ->getArrayOfTupleFromDict
+            applePayBody->mergeAndFlattenToTuples(requiredFieldsBody)
           }
 
           processPayment(
diff --git a/src/Utilities/DynamicFieldsUtils.res b/src/Utilities/DynamicFieldsUtils.res
index 380d087ed..4861d6f45 100644
--- a/src/Utilities/DynamicFieldsUtils.res
+++ b/src/Utilities/DynamicFieldsUtils.res
@@ -1,5 +1,28 @@
 open RecoilAtoms
 
+let dynamicFieldsEnabledPaymentMethods = [
+  "crypto_currency",
+  "debit",
+  "credit",
+  "blik",
+  "google_pay",
+  "apple_pay",
+  "bancontact_card",
+  "open_banking_uk",
+  "eps",
+  "ideal",
+  "sofort",
+  "pix_transfer",
+  "giropay",
+  "local_bank_transfer_transfer",
+  "afterpay_clearpay",
+  "mifinity",
+  "upi_collect",
+  "sepa",
+  "affirm",
+  "ach",
+]
+
 let getName = (item: PaymentMethodsRecord.required_fields, field: RecoilAtomTypes.field) => {
   let fieldNameArr = field.value->String.split(" ")
   let requiredFieldsArr = item.required_field->String.split(".")
diff --git a/src/Utilities/GooglePayHelpers.res b/src/Utilities/GooglePayHelpers.res
index 1f1118e57..8552941d3 100644
--- a/src/Utilities/GooglePayHelpers.res
+++ b/src/Utilities/GooglePayHelpers.res
@@ -53,17 +53,13 @@ let getGooglePayBodyFromResponse = (
     )
   }
 
-  gPayBody
-  ->getJsonFromArrayOfJson
-  ->flattenObject(true)
-  ->mergeTwoFlattenedJsonDicts(requiredFieldsBody)
-  ->getArrayOfTupleFromDict
+  gPayBody->mergeAndFlattenToTuples(requiredFieldsBody)
 }
 
 let processPayment = (
   ~body: array<(string, JSON.t)>,
   ~isThirdPartyFlow=false,
-  ~intent: PaymentHelpers.paymentIntent,
+  ~intent: PaymentHelpersTypes.paymentIntent,
   ~options: PaymentType.options,
   ~publishableKey,
   ~isManualRetryEnabled,
@@ -123,11 +119,7 @@ let useHandleGooglePayResponse = (
         let googlePayBody = if isWallet {
           body
         } else {
-          body
-          ->getJsonFromArrayOfJson
-          ->flattenObject(true)
-          ->mergeTwoFlattenedJsonDicts(requiredFieldsBody)
-          ->getArrayOfTupleFromDict
+          body->mergeAndFlattenToTuples(requiredFieldsBody)
         }
 
         processPayment(
@@ -151,12 +143,7 @@ let useHandleGooglePayResponse = (
   }, (paymentMethodTypes, stateJson, isManualRetryEnabled, requiredFieldsBody, isWallet))
 }
 
-let handleGooglePayClicked = (
-  ~sessionObj,
-  ~componentName,
-  ~iframeId,
-  ~readOnly,
-) => {
+let handleGooglePayClicked = (~sessionObj, ~componentName, ~iframeId, ~readOnly) => {
   let paymentDataRequest = GooglePayType.getPaymentDataFromSession(~sessionObj, ~componentName)
   messageParentWindow([
     ("fullscreen", true->JSON.Encode.bool),
@@ -183,12 +170,7 @@ let useSubmitCallback = (~isWallet, ~sessionObj, ~componentName) => {
       let json = ev.data->safeParse
       let confirm = json->getDictFromJson->ConfirmType.itemToObjMapper
       if confirm.doSubmit && areRequiredFieldsValid && !areRequiredFieldsEmpty {
-        handleGooglePayClicked(
-          ~sessionObj,
-          ~componentName,
-          ~iframeId,
-          ~readOnly=options.readOnly,
-        )
+        handleGooglePayClicked(~sessionObj, ~componentName, ~iframeId, ~readOnly=options.readOnly)
       } else if areRequiredFieldsEmpty {
         postFailedSubmitResponse(
           ~errortype="validation_error",
diff --git a/src/Utilities/PaymentBody.res b/src/Utilities/PaymentBody.res
index 2a5a8e75e..eaa5c76bb 100644
--- a/src/Utilities/PaymentBody.res
+++ b/src/Utilities/PaymentBody.res
@@ -654,21 +654,6 @@ let epsBody = (~name, ~bankName) => [
   ),
 ]
 
-let achBankTransferBody = (~email, ~connectors) => [
-  ("payment_method", "bank_transfer"->JSON.Encode.string),
-  ("connector", connectors->Utils.getArrofJsonString->JSON.Encode.array),
-  ("payment_method_type", "ach"->JSON.Encode.string),
-  (
-    "payment_method_data",
-    [
-      ("billing", [("email", email->JSON.Encode.string)]->Utils.getJsonFromArrayOfJson),
-      (
-        "bank_transfer",
-        [("ach_bank_transfer", Dict.make()->JSON.Encode.object)]->Utils.getJsonFromArrayOfJson,
-      ),
-    ]->Utils.getJsonFromArrayOfJson,
-  ),
-]
 let bacsBankTransferBody = (~email, ~name, ~connectors) => {
   let (firstName, lastName) = name->Utils.getFirstAndLastNameFromFullName
 
@@ -698,38 +683,6 @@ let bacsBankTransferBody = (~email, ~name, ~connectors) => {
   ]
 }
 
-let sepaBankTransferBody = (~email, ~name, ~country, ~connectors) => {
-  let (firstName, lastName) = name->Utils.getFirstAndLastNameFromFullName
-
-  [
-    ("payment_method", "bank_transfer"->JSON.Encode.string),
-    ("connector", connectors->Utils.getArrofJsonString->JSON.Encode.array),
-    ("payment_method_type", "sepa"->JSON.Encode.string),
-    (
-      "payment_method_data",
-      [
-        (
-          "billing",
-          [
-            ("email", email->JSON.Encode.string),
-            (
-              "address",
-              [
-                ("first_name", firstName),
-                ("last_name", lastName),
-                ("country", country->JSON.Encode.string),
-              ]->Utils.getJsonFromArrayOfJson,
-            ),
-          ]->Utils.getJsonFromArrayOfJson,
-        ),
-        (
-          "bank_transfer",
-          [("sepa_bank_transfer", Dict.make()->JSON.Encode.object)]->Utils.getJsonFromArrayOfJson,
-        ),
-      ]->Utils.getJsonFromArrayOfJson,
-    ),
-  ]
-}
 let blikBody = (~blikCode) => [
   ("payment_method", "bank_redirect"->JSON.Encode.string),
   ("payment_method_type", "blik"->JSON.Encode.string),
@@ -977,16 +930,30 @@ let appendRedirectPaymentMethods = [
 ]
 
 let appendBankeDebitMethods = ["sepa"]
+let appendBankTransferMethods = ["sepa", "ach"]
 
-let appendPaymentMethodExperience = (paymentMethodType, isQrPaymentMethod) =>
+let getPaymentMethodSuffix = (~paymentMethodType, ~paymentMethod, ~isQrPaymentMethod) => {
   if isQrPaymentMethod {
-    paymentMethodType ++ "_qr"
+    Some("qr")
   } else if appendRedirectPaymentMethods->Array.includes(paymentMethodType) {
-    paymentMethodType ++ "_redirect"
-  } else if appendBankeDebitMethods->Array.includes(paymentMethodType) {
-    paymentMethodType ++ "_bank_debit"
+    Some("redirect")
+  } else if (
+    appendBankeDebitMethods->Array.includes(paymentMethodType) && paymentMethod == "bank_debit"
+  ) {
+    Some("bank_debit")
+  } else if (
+    appendBankTransferMethods->Array.includes(paymentMethodType) && paymentMethod == "bank_transfer"
+  ) {
+    Some("bank_transfer")
   } else {
-    paymentMethodType
+    None
+  }
+}
+
+let appendPaymentMethodExperience = (~paymentMethod, ~paymentMethodType, ~isQrPaymentMethod) =>
+  switch getPaymentMethodSuffix(~paymentMethodType, ~paymentMethod, ~isQrPaymentMethod) {
+  | Some(suffix) => `${paymentMethodType}_${suffix}`
+  | None => paymentMethodType
   }
 
 let paymentExperiencePaymentMethods = ["affirm"]
@@ -1010,7 +977,7 @@ let dynamicPaymentBody = (paymentMethod, paymentMethodType, ~isQrPaymentMethod=f
           paymentMethod,
           [
             (
-              paymentMethodType->appendPaymentMethodExperience(isQrPaymentMethod),
+              appendPaymentMethodExperience(~paymentMethod, ~paymentMethodType, ~isQrPaymentMethod),
               Dict.make()->JSON.Encode.object,
             ),
           ]->Utils.getJsonFromArrayOfJson,
diff --git a/src/Utilities/PaymentHelpers.res b/src/Utilities/PaymentHelpers.res
index 08ce312c5..86dc02bc4 100644
--- a/src/Utilities/PaymentHelpers.res
+++ b/src/Utilities/PaymentHelpers.res
@@ -1,15 +1,8 @@
 open Utils
 open Identity
-
-@val @scope(("window", "parent", "location")) external href: string = "href"
-
-type searchParams = {set: (string, string) => unit}
-type url = {searchParams: searchParams, href: string}
-@new external urlSearch: string => url = "URL"
-
+open PaymentHelpersTypes
 open LoggerUtils
-type payment =
-  Card | BankTransfer | BankDebits | KlarnaRedirect | Gpay | Applepay | Paypal | Paze | Other
+open URLModule
 
 let getPaymentType = paymentMethodType =>
   switch paymentMethodType {
@@ -25,23 +18,6 @@ let getPaymentType = paymentMethodType =>
 
 let closePaymentLoaderIfAny = () => messageParentWindow([("fullscreen", false->JSON.Encode.bool)])
 
-type paymentIntent = (
-  ~handleUserError: bool=?,
-  ~bodyArr: array<(string, JSON.t)>,
-  ~confirmParam: ConfirmType.confirmParams,
-  ~iframeId: string=?,
-  ~isThirdPartyFlow: bool=?,
-  ~intentCallback: Core__JSON.t => unit=?,
-  ~manualRetry: bool=?,
-) => unit
-
-type completeAuthorize = (
-  ~handleUserError: bool=?,
-  ~bodyArr: array<(string, JSON.t)>,
-  ~confirmParam: ConfirmType.confirmParams,
-  ~iframeId: string=?,
-) => unit
-
 let retrievePaymentIntent = (
   clientSecret,
   headers,
@@ -359,10 +335,10 @@ let rec intentCall = (
   )
   ->then(res => {
     let statusCode = res->Fetch.Response.status->Int.toString
-    let url = urlSearch(confirmParam.return_url)
+    let url = makeUrl(confirmParam.return_url)
     url.searchParams.set("payment_intent_client_secret", clientSecret)
     url.searchParams.set("status", "failed")
-    messageParentWindow([("confirmParams", confirmParam->Identity.anyTypeToJson)])
+    messageParentWindow([("confirmParams", confirmParam->anyTypeToJson)])
 
     if statusCode->String.charAt(0) !== "2" {
       res
@@ -504,7 +480,7 @@ let rec intentCall = (
             | _ => intent.payment_method_type
             }
 
-            let url = urlSearch(confirmParam.return_url)
+            let url = makeUrl(confirmParam.return_url)
             url.searchParams.set("payment_intent_client_secret", clientSecret)
             url.searchParams.set("status", intent.status)
 
@@ -516,7 +492,7 @@ let rec intentCall = (
               | (Paypal, false) =>
                 if !isPaymentSession {
                   if isCallbackUsedVal->Option.getOr(false) {
-                    Utils.handleOnCompleteDoThisMessage()
+                    handleOnCompleteDoThisMessage()
                   } else {
                     closePaymentLoaderIfAny()
                   }
@@ -524,7 +500,7 @@ let rec intentCall = (
                   postSubmitResponse(~jsonData=data, ~url=url.href)
                 } else if confirmParam.redirect === Some("always") {
                   if isCallbackUsedVal->Option.getOr(false) {
-                    Utils.handleOnCompleteDoThisMessage()
+                    handleOnCompleteDoThisMessage()
                   } else {
                     handleOpenUrl(url.href)
                   }
@@ -534,7 +510,7 @@ let rec intentCall = (
               | _ =>
                 if isCallbackUsedVal->Option.getOr(false) {
                   closePaymentLoaderIfAny()
-                  Utils.handleOnCompleteDoThisMessage()
+                  handleOnCompleteDoThisMessage()
                 } else {
                   handleOpenUrl(url.href)
                 }
@@ -719,7 +695,7 @@ let rec intentCall = (
                         ->getString("open_banking_session_token", "")
                         ->JSON.Encode.string,
                       ),
-                      ("pmAuthConnectorArray", ["plaid"]->Identity.anyTypeToJson),
+                      ("pmAuthConnectorArray", ["plaid"]->anyTypeToJson),
                       ("publishableKey", confirmParam.publishableKey->JSON.Encode.string),
                       ("clientSecret", clientSecret->JSON.Encode.string),
                       ("isForceSync", true->JSON.Encode.bool),
@@ -846,7 +822,7 @@ let rec intentCall = (
   ->catch(err => {
     Promise.make((resolve, _) => {
       try {
-        let url = urlSearch(confirmParam.return_url)
+        let url = makeUrl(confirmParam.return_url)
         url.searchParams.set("payment_intent_client_secret", clientSecret)
         url.searchParams.set("status", "failed")
         let exceptionMessage = err->formatException
@@ -982,7 +958,7 @@ let rec maskPayload = payloadJson => {
       let (key, value) = entry
       (key, maskPayload(value))
     })
-    ->Utils.getJsonFromArrayOfJson
+    ->getJsonFromArrayOfJson
 
   | Array(arr) => arr->Array.map(maskPayload)->JSON.Encode.array
   | String(valueStr) => valueStr->maskStr->JSON.Encode.string
@@ -1049,10 +1025,10 @@ let usePaymentIntent = (optLogger, paymentType) => {
                 let (key, value) = header
                 (key, value->JSON.Encode.string)
               })
-              ->Utils.getJsonFromArrayOfJson,
+              ->getJsonFromArrayOfJson,
             ),
           ]
-          ->Utils.getJsonFromArrayOfJson
+          ->getJsonFromArrayOfJson
           ->JSON.stringify
         switch paymentType {
         | Card =>
@@ -1115,7 +1091,7 @@ let usePaymentIntent = (optLogger, paymentType) => {
             bodyArr->Array.concat(broswerInfo()),
             mandatePaymentType->PaymentBody.paymentTypeBody,
           ])
-          ->Utils.getJsonFromArrayOfJson
+          ->getJsonFromArrayOfJson
           ->JSON.stringify
         callIntent(bodyStr)
       }
@@ -1126,7 +1102,7 @@ let usePaymentIntent = (optLogger, paymentType) => {
           ->Array.concat(
             bodyArr->Array.concatMany([PaymentBody.mandateBody(mandatePaymentType), broswerInfo()]),
           )
-          ->Utils.getJsonFromArrayOfJson
+          ->getJsonFromArrayOfJson
           ->JSON.stringify
         callIntent(bodyStr)
       }
@@ -1206,7 +1182,7 @@ let useCompleteAuthorize = (optLogger: option<HyperLogger.loggerMake>, paymentTy
       let bodyStr =
         [("client_secret", clientSecret->JSON.Encode.string)]
         ->Array.concatMany([bodyArr, browserInfo()])
-        ->Utils.getJsonFromArrayOfJson
+        ->getJsonFromArrayOfJson
         ->JSON.stringify
 
       let completeAuthorize = () => {
@@ -1738,7 +1714,7 @@ let callAuthLink = (
         let metaData =
           [
             ("linkToken", data->getDictFromJson->getString("link_token", "")->JSON.Encode.string),
-            ("pmAuthConnectorArray", pmAuthConnectorsArr->Identity.anyTypeToJson),
+            ("pmAuthConnectorArray", pmAuthConnectorsArr->anyTypeToJson),
             ("publishableKey", publishableKey->JSON.Encode.string),
             ("clientSecret", clientSecret->Option.getOr("")->JSON.Encode.string),
             ("isForceSync", false->JSON.Encode.bool),
@@ -2157,10 +2133,10 @@ let usePostSessionTokens = (
                 let (key, value) = header
                 (key, value->JSON.Encode.string)
               })
-              ->Utils.getJsonFromArrayOfJson,
+              ->getJsonFromArrayOfJson,
             ),
           ]
-          ->Utils.getJsonFromArrayOfJson
+          ->getJsonFromArrayOfJson
           ->JSON.stringify
         switch paymentType {
         | Card =>
@@ -2218,7 +2194,7 @@ let usePostSessionTokens = (
             bodyArr->Array.concat(broswerInfo()),
             mandatePaymentType->PaymentBody.paymentTypeBody,
           ])
-          ->Utils.getJsonFromArrayOfJson
+          ->getJsonFromArrayOfJson
           ->JSON.stringify
         callIntent(bodyStr)
       }
@@ -2229,7 +2205,7 @@ let usePostSessionTokens = (
           ->Array.concat(
             bodyArr->Array.concatMany([PaymentBody.mandateBody(mandatePaymentType), broswerInfo()]),
           )
-          ->Utils.getJsonFromArrayOfJson
+          ->getJsonFromArrayOfJson
           ->JSON.stringify
         callIntent(bodyStr)
       }
diff --git a/src/Utilities/PaymentHelpersTypes.res b/src/Utilities/PaymentHelpersTypes.res
new file mode 100644
index 000000000..64ff04258
--- /dev/null
+++ b/src/Utilities/PaymentHelpersTypes.res
@@ -0,0 +1,19 @@
+type payment =
+  Card | BankTransfer | BankDebits | KlarnaRedirect | Gpay | Applepay | Paypal | Paze | Other
+
+type paymentIntent = (
+  ~handleUserError: bool=?,
+  ~bodyArr: array<(string, JSON.t)>,
+  ~confirmParam: ConfirmType.confirmParams,
+  ~iframeId: string=?,
+  ~isThirdPartyFlow: bool=?,
+  ~intentCallback: Core__JSON.t => unit=?,
+  ~manualRetry: bool=?,
+) => unit
+
+type completeAuthorize = (
+  ~handleUserError: bool=?,
+  ~bodyArr: array<(string, JSON.t)>,
+  ~confirmParam: ConfirmType.confirmParams,
+  ~iframeId: string=?,
+) => unit
diff --git a/src/Utilities/URLModule.res b/src/Utilities/URLModule.res
new file mode 100644
index 000000000..f956b52e9
--- /dev/null
+++ b/src/Utilities/URLModule.res
@@ -0,0 +1,5 @@
+type match
+type pathname = {match: match}
+type searchParams = {set: (string, string) => unit}
+type url = {searchParams: searchParams, href: string, pathname: pathname}
+@new external makeUrl: string => url = "URL"
diff --git a/src/Utilities/Utils.res b/src/Utilities/Utils.res
index 50f09d979..45c43cc0d 100644
--- a/src/Utilities/Utils.res
+++ b/src/Utilities/Utils.res
@@ -257,7 +257,7 @@ let useWindowSize = () => {
   let (size, setSize) = React.useState(_ => (0, 0))
   React.useLayoutEffect1(() => {
     let updateSize = () => {
-      setSize(_ => (Window.windowInnerWidth, Window.windowInnerHeight))
+      setSize(_ => (Window.innerWidth, Window.innerHeight))
     }
     Window.addEventListener("resize", updateSize)
     updateSize()
@@ -1419,6 +1419,14 @@ let getFirstAndLastNameFromFullName = fullName => {
   (firstName, lastNameJson)
 }
 
+let isKeyPresentInDict = (dict, key) => dict->Dict.get(key)->Option.isSome
 let checkIsTestCardWildcard = val => ["1111222233334444"]->Array.includes(val)
 
 let minorUnitToString = val => (val->Int.toFloat /. 100.)->Float.toString
+
+let mergeAndFlattenToTuples = (body, requiredFieldsBody) =>
+  body
+  ->getJsonFromArrayOfJson
+  ->flattenObject(true)
+  ->mergeTwoFlattenedJsonDicts(requiredFieldsBody)
+  ->getArrayOfTupleFromDict
diff --git a/src/Window.res b/src/Window.res
index ebb0570d6..f2a17a768 100644
--- a/src/Window.res
+++ b/src/Window.res
@@ -1,33 +1,7 @@
 type window
 type parent
 type document
-@val external window: window = "window"
-@val @scope("window") external windowInnerHeight: int = "innerHeight"
-@val @scope("window") external windowInnerWidth: int = "innerWidth"
-
-@val @scope("window")
-external windowParent: window = "parent"
 type style
-
-@val external parent: window = "parent"
-@get external cardNumberElement: window => option<window> = "cardNumber"
-@get external cardCVCElement: window => option<window> = "cardCvc"
-@get external cardExpiryElement: window => option<window> = "cardExpiry"
-@get external value: Dom.element => 'a = "value"
-
-@val @scope("document") external createElement: string => Dom.element = "createElement"
-@set external windowOnload: (window, unit => unit) => unit = "onload"
-
-@get external fullscreen: window => option<window> = "fullscreen"
-
-@get external document: window => document = "document"
-@get external parentNode: Dom.element => Dom.element = "parentNode"
-@val @scope("document")
-external querySelector: string => Nullable.t<Dom.element> = "querySelector"
-@val @scope("document")
-external querySelectorAll: string => array<Dom.element> = "querySelectorAll"
-@send external getAttribute: (Dom.element, string) => option<string> = "getAttribute"
-
 type eventData = {
   elementType: string,
   clickTriggered: bool,
@@ -38,76 +12,62 @@ type eventData = {
   oneClickConfirmTriggered: bool,
 }
 type loaderEvent = {key: string, data: eventData}
-@set external innerHTML: (Dom.element, string) => unit = "innerHTML"
 type event = {key: string, data: string, origin: string}
-@val @scope("window")
-external addEventListener: (string, _ => unit) => unit = "addEventListener"
+type date = {now: unit => string}
+type body
+type packageJson = {version: string}
+
+/* External Declarations */
+@val external window: window = "window"
+@val @scope("window") external innerHeight: int = "innerHeight"
+@val @scope("window") external innerWidth: int = "innerWidth"
+@val @scope("window") external windowParent: window = "parent"
+@val external parent: window = "parent"
+@val @scope("document") external createElement: string => Dom.element = "createElement"
+@val @scope("document") external querySelector: string => Nullable.t<Dom.element> = "querySelector"
+@val @scope("document") external querySelectorAll: string => array<Dom.element> = "querySelectorAll"
+@module("/package.json") @val external packageJson: packageJson = "default"
+@val @scope("document") external body: body = "body"
+@val @scope("window") external getHyper: Nullable.t<Types.hyperInstance> = "HyperMethod"
+@val @scope("window") external addEventListener: (string, _ => unit) => unit = "addEventListener"
 @val @scope("window")
 external removeEventListener: (string, 'ev => unit) => unit = "removeEventListener"
+@val @scope("window") external btoa: string => string = "btoa"
+@new external date: date = "Date"
+@get external value: Dom.element => 'a = "value"
+
+/* External Methods */
+@scope("window") @get external cardNumberElement: window => option<window> = "cardNumber"
+@get external cardCVCElement: window => option<window> = "cardCvc"
+@get external cardExpiryElement: window => option<window> = "cardExpiry"
+@get external document: window => document = "document"
+@get external fullscreen: window => option<window> = "fullscreen"
+@get external frames: window => {..} = "frames"
+@get external name: window => string = "name"
+@get external contentWindow: Dom.element => Dom.element = "contentWindow"
+@get external style: Dom.element => style = "style"
+@send external getAttribute: (Dom.element, string) => option<string> = "getAttribute"
 @send external postMessage: (Dom.element, string, string) => unit = "postMessage"
 @send external postMessageJSON: (Dom.element, JSON.t, string) => unit = "postMessage"
-@send
-external getElementById: (document, string) => Nullable.t<Dom.element> = "getElementById"
-@get
-external frames: window => {..} = "frames"
-@get external name: window => string = "name"
-@get
-external contentWindow: Dom.element => Dom.element = "contentWindow"
-@get
-external style: Dom.element => style = "style"
-@set external setTransition: (style, string) => unit = "transition"
-@set external setHeight: (style, string) => unit = "height"
+@send external getElementById: (document, string) => Nullable.t<Dom.element> = "getElementById"
+@send external preventDefault: (event, unit) => unit = "preventDefault"
+@send external appendChild: (body, Dom.element) => unit = "appendChild"
+@send external remove: Dom.element => unit = "remove"
+@send external setAttribute: (Dom.element, string, string) => unit = "setAttribute"
 @send external paymentRequest: (JSON.t, JSON.t, JSON.t) => JSON.t = "PaymentRequest"
 @send external click: Dom.element => unit = "click"
-
-let sendPostMessage = (element, message) => {
-  element->postMessage(message->JSON.Encode.object->JSON.stringify, GlobalVars.targetOrigin)
-}
-
-let sendPostMessageJSON = (element, message) => {
-  element->postMessageJSON(message, GlobalVars.targetOrigin)
-}
-
-let iframePostMessage = (iframeRef: nullable<Dom.element>, message) => {
-  switch iframeRef->Nullable.toOption {
-  | Some(ref) =>
-    try {
-      ref
-      ->contentWindow
-      ->sendPostMessage(message)
-    } catch {
-    | _ => ()
-    }
-  | None => Console.error("This element does not exist or is not mounted yet.")
-  }
-}
-
-@send external preventDefault: (event, unit) => unit = "preventDefault"
-
-type date = {now: unit => string}
-@new external date: date = "Date"
+@set external innerHTML: (Dom.element, string) => unit = "innerHTML"
 @set external className: (Dom.element, string) => unit = "className"
 @set external id: (Dom.element, string) => unit = "id"
-@send external setAttribute: (Dom.element, string, string) => unit = "setAttribute"
 @set external elementSrc: (Dom.element, string) => unit = "src"
-type body
-
-@val @scope("document")
-external body: body = "body"
-@send external appendChild: (body, Dom.element) => unit = "appendChild"
-@send external remove: Dom.element => unit = "remove"
-
 @set external elementOnload: (Dom.element, unit => unit) => unit = "onload"
 @set external elementOnerror: (Dom.element, exn => unit) => unit = "onerror"
-@val @scope("window")
-external getHyper: Nullable.t<Types.hyperInstance> = "HyperMethod"
-@set
-external setHyper: (window, Types.hyperInstance) => unit = "HyperMethod"
-
-type packageJson = {version: string}
-@module("/package.json") @val external packageJson: packageJson = "default"
-let version = packageJson.version
+@set external setTransition: (style, string) => unit = "transition"
+@set external setHeight: (style, string) => unit = "height"
+@set external windowOnload: (window, unit => unit) => unit = "onload"
+@set external setHyper: (window, Types.hyperInstance) => unit = "HyperMethod"
 
+/* Module Definitions */
 module Navigator = {
   @val @scope("navigator")
   external browserName: string = "appName"
@@ -174,17 +134,41 @@ module Element = {
   @get external clientWidth: Dom.element => int = "clientWidth"
 }
 
-@val @scope("window")
-external btoa: string => string = "btoa"
+/* Helper Functions */
+let sendPostMessage = (element, message) => {
+  element->postMessage(message->JSON.Encode.object->JSON.stringify, GlobalVars.targetOrigin)
+}
+
+let sendPostMessageJSON = (element, message) => {
+  element->postMessageJSON(message, GlobalVars.targetOrigin)
+}
+
+let iframePostMessage = (iframeRef: nullable<Dom.element>, message) => {
+  switch iframeRef->Nullable.toOption {
+  | Some(ref) =>
+    try {
+      ref
+      ->contentWindow
+      ->sendPostMessage(message)
+    } catch {
+    | _ => ()
+    }
+  | None => Console.error("This element does not exist or is not mounted yet.")
+  }
+}
+
+/* Version Handling */
+let version = packageJson.version
 
+/* URL Handling */
 let hrefWithoutSearch = Location.origin ++ Location.pathname
 
+/* Environment Flags */
 let isSandbox = Location.hostname === "beta.hyperswitch.io"
-
 let isInteg = Location.hostname === "dev.hyperswitch.io"
-
 let isProd = Location.hostname === "checkout.hyperswitch.io"
 
+/* iFrame Detection */
 let isIframed = () =>
   try {
     Location.href !== Top.Location.href
@@ -200,6 +184,7 @@ let isIframed = () =>
     }
   }
 
+/* Root Hostname Retrieval */
 let getRootHostName = () =>
   switch isIframed() {
   | true =>
@@ -219,22 +204,5 @@ let getRootHostName = () =>
   | false => Location.hostname
   }
 
-let replaceRootHref = (href: string) => {
-  Location.replace(href)
-  // switch isIframed() {
-  // | true =>
-  //   try {
-  //     Top.Location.replace(href)
-  //   } catch {
-  //   | e => {
-  //       Js.Console.error3(
-  //         "Failed to redirect root document",
-  //         e,
-  //         `Using [window.location.replace] for redirection`,
-  //       )
-  //       Location.replace(href)
-  //     }
-  //   }
-  // | false => Location.replace(href)
-  // }
-}
+/* Redirect Handling */
+let replaceRootHref = (href: string) => Location.replace(href)