Repository: dokwallet/dokwallet_web
Pull request #4: Divyang/google site verification
Author: login: divyangkhatri
Created: 2025-05-02T15:01:05Z | Merged: 2025-05-02T15:26:50Z



<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit

- **New Features**
  - The app now dynamically fetches and applies white label configuration based on the request host, including locale, branding, and metadata such as site verification, title, and favicon.
- **Improvements**
  - Enhanced error handling for white label and locale loading to ensure a smoother user experience.
  - Streamlined internal data flow by passing white label data as a prop, improving performance and reliability.
- **Refactor**
  - Simplified header logic by removing dynamic document title and favicon updates from the component.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->


Diff:
diff --git a/dok-wallet-blockchain-networks b/dok-wallet-blockchain-networks
index d0fe0a8..e9afeb4 160000
--- a/dok-wallet-blockchain-networks
+++ b/dok-wallet-blockchain-networks
@@ -1 +1 @@
-Subproject commit d0fe0a83bba65e660c2414abce59c3c97e805ef9
+Subproject commit e9afeb419a7db3ca258277df003a50ecaf547d27
diff --git a/src/app/layout.js b/src/app/layout.js
index 4307b72..cd7f5b0 100644
--- a/src/app/layout.js
+++ b/src/app/layout.js
@@ -6,6 +6,9 @@ import ThemeProvider from 'theme/ThemeContext';
 import React from 'react';
 import {NextIntlClientProvider} from 'next-intl';
 import {getLocale, getMessages} from 'next-intl/server';
+import {getWhiteLabelInfo} from 'dok-wallet-blockchain-networks/service/dokApi';
+import {headers} from 'next/headers';
+import {isLocaleSet} from 'utils/updateLocale';
 
 const roboto = Roboto({
   weight: ['400', '500', '700'],
@@ -18,27 +21,63 @@ const roboto = Roboto({
 export default async function RootLayout({children}) {
   let locale;
   let messages;
+  let wlData;
 
   try {
-    locale = await getLocale();
-    messages = await getMessages();
+    const headersList = await headers();
+    const host = headersList.get('x-forwarded-host') ?? headersList.get('host');
+    const firstHost = host.split(':')[0];
+    const resp = await getWhiteLabelInfo(firstHost);
+    wlData = resp?.data;
+  } catch (error) {
+    console.error('Error in getting white label:', error);
+  }
+
+  try {
+    const isLocalExist = await isLocaleSet();
+    if (isLocalExist) {
+      locale = await getLocale();
+    } else {
+      locale = wlData?.defaultLocale || 'en';
+    }
+    messages = await getMessages({locale});
   } catch (error) {
     console.error('Error loading locale or messages:', error);
     locale = 'en';
     messages = {};
   }
 
+  const googleSiteVerification = wlData?.metadata?.google_site_verification;
+  const title = wlData?.title || 'Dok Wallet';
+  const appIcon = wlData?.appIcon?.light ?? '/dokwallet.ico';
   return (
     <html lang={locale}>
-      <ThemeProvider>
-        <body className={roboto.variable}>
-          <NextIntlClientProvider locale={locale} messages={messages}>
-            <StateProvider>
-              <AppRouting>{children}</AppRouting>
-            </StateProvider>
-          </NextIntlClientProvider>
+      <head>
+        {typeof googleSiteVerification === 'string' &&
+          !!googleSiteVerification && (
+            <meta
+              name='google-site-verification'
+              content={googleSiteVerification}
+            />
+          )}
+        <link rel='icon' href={appIcon} />
+        <title>{title}</title>
+      </head>
+      {wlData ? (
+        <ThemeProvider>
+          <body className={roboto.variable}>
+            <NextIntlClientProvider locale={locale} messages={messages}>
+              <StateProvider>
+                <AppRouting wlData={wlData}>{children}</AppRouting>
+              </StateProvider>
+            </NextIntlClientProvider>
+          </body>
+        </ThemeProvider>
+      ) : (
+        <body>
+          <h3 style={{textAlign: 'center', flex: 1}}>Something went wrong</h3>
         </body>
-      </ThemeProvider>
+      )}
     </html>
   );
 }
diff --git a/src/components/AppRouting/index.jsx b/src/components/AppRouting/index.jsx
index c248ff6..d0fdee2 100644
--- a/src/components/AppRouting/index.jsx
+++ b/src/components/AppRouting/index.jsx
@@ -22,7 +22,6 @@ import {
   createAIDIfNotExists,
 } from 'utils/localStorageData';
 import Loading from '../Loading';
-import {getWhiteLabelInfo} from 'dok-wallet-blockchain-networks/service/dokApi';
 import {
   getWalletConnectDetails,
   setWhiteLabelInfo,
@@ -35,7 +34,6 @@ import {
 import {
   getDisableMessage,
   getGoogleAnalyticsKey,
-  getGoogleSiteVerification,
 } from 'dok-wallet-blockchain-networks/redux/cryptoProviders/cryptoProvidersSelectors';
 import DisabledView from 'components/DisabledView';
 import {MainNavigation} from 'utils/navigation';
@@ -47,9 +45,8 @@ import {
 } from 'dok-wallet-blockchain-networks/redux/wallets/walletsSlice';
 import {isLocaleSet, setUserLocale} from 'src/utils/updateLocale';
 import {masterClickHost, publicRoutes} from 'utils/common';
-import Head from 'next/head';
 
-function AppRouting({children}) {
+function AppRouting({children, wlData}) {
   const password = useSelector(getUserPassword);
   const routing = useRouter();
   const dispatch = useDispatch();
@@ -62,11 +59,9 @@ function AppRouting({children}) {
     shallowEqual,
   );
   const [rountingDone, setRoutingDone] = useState(false);
-  const [isWhiteLabelInfoFetching, setIsWhiteLabelInfoFetching] =
-    useState(true);
+
   const disableMessage = useSelector(getDisableMessage);
   const googleAnalyticsKey = useSelector(getGoogleAnalyticsKey);
-  const googleSiteVerification = useSelector(getGoogleSiteVerification);
 
   useEffect(() => {
     if (googleAnalyticsKey) {
@@ -101,7 +96,7 @@ function AppRouting({children}) {
   }, []);
 
   useEffect(() => {
-    if (isReduxStoreLoad && !isWhiteLabelInfoFetching) {
+    if (isReduxStoreLoad) {
       dispatch(resetIsAdding50MoreAddresses());
       dispatch(createIfNotExistsMasterClientId());
       let searchString = searchParams?.toString();
@@ -175,39 +170,25 @@ function AppRouting({children}) {
       }
     }
     // eslint-disable-next-line react-hooks/exhaustive-deps
-  }, [isReduxStoreLoad, isWhiteLabelInfoFetching]);
+  }, [isReduxStoreLoad]);
 
   useEffect(() => {
-    getWhiteLabelInfo()
-      .then(async resp => {
-        setIsWhiteLabelInfoFetching(false);
-        if (resp?.data) {
-          setWhiteLabelInfo(resp?.data);
-          const localeSetCheck = await isLocaleSet();
-          if (!localeSetCheck) {
-            setUserLocale(resp?.data?.defaultLocale || 'en');
-          }
+    setWhiteLabelInfo(wlData);
+    (async () => {
+      try {
+        const localeSetCheck = await isLocaleSet();
+        if (!localeSetCheck) {
+          setUserLocale(wlData.defaultLocale || 'en');
         }
-      })
-      .catch(e => {
-        console.error('Error in fetching white label info');
-        setIsWhiteLabelInfoFetching(false);
-      });
-    // eslint-disable-next-line react-hooks/exhaustive-deps
-  }, []);
+      } catch {
+        console.error('error in set local', e);
+      }
+    })();
+  }, [wlData]);
 
   return (
     <>
       <div>
-        {typeof googleSiteVerification === 'string' &&
-          !!googleSiteVerification && (
-            <Head>
-              <meta
-                name='google-site-verification'
-                content={googleSiteVerification}
-              />
-            </Head>
-          )}
         {rountingDone && !disableMessage ? (
           <div className={s.container}>
             <div className={s.navbarWrapper}>{<Header />}</div>
diff --git a/src/components/Header/index.jsx b/src/components/Header/index.jsx
index c657906..cc94c76 100644
--- a/src/components/Header/index.jsx
+++ b/src/components/Header/index.jsx
@@ -3,12 +3,7 @@
 import Link from 'next/link';
 import s from './Header.module.css';
 
-import {
-  getAppTitle,
-  getAppIcon,
-  getAppAssets,
-  getAppLogo,
-} from 'whitelabel/whiteLabelInfo';
+import {getAppLogo} from 'whitelabel/whiteLabelInfo';
 const icons = require(`assets/images/icons`).default;
 import React, {useContext, useEffect} from 'react';
 import {ThemeContext} from 'theme/ThemeContext';
@@ -21,17 +16,6 @@ const Header = () => {
   const path = usePathname();
   const pathname = `/${path.split('/')[1]}`;
 
-  useEffect(() => {
-    document.title = getAppTitle();
-    let link = document.querySelector("link[rel~='icon']");
-    if (!link) {
-      link = document.createElement('link');
-      link.rel = 'icon';
-      document.head.appendChild(link);
-    }
-    link.href = getAppIcon();
-  }, []);
-
   if (publicRoutes.includes(pathname)) {
     return null;
   }


Reviews:
user: login: coderabbitai[bot]
body: **Actionable comments posted: 4**

<details>
<summary>🔭 Outside diff range comments (1)</summary><blockquote>

<details>
<summary>src/components/AppRouting/index.jsx (1)</summary><blockquote>

`98-174`: _🛠️ Refactor suggestion_

**Long-running intervals are never cleared**

Inside the `useEffect` guarded by `isReduxStoreLoad`, several `setInterval` calls are created but not cleaned up on unmount. Navigating away or doing an HMR update will leave orphaned timers increasing memory usage.

```diff
useEffect(() => {
  …
-  setInterval(() => compareRpcUrls(), 1000 * 60 * 10);
+  const rpcInterval = setInterval(compareRpcUrls, 1000 * 60 * 10);
  …
-  setInterval(() => fetchFeesInfo(), 1000 * 60 * 60 * 8);
+  const feeInterval = setInterval(fetchFeesInfo, 1000 * 60 * 60 * 8);

  return () => {
+    clearInterval(rpcInterval);
+    clearInterval(feeInterval);
  };
}, [isReduxStoreLoad]);
```

</blockquote></details>

</blockquote></details>

<details>
<summary>🧹 Nitpick comments (3)</summary><blockquote>

<details>
<summary>src/app/layout.js (2)</summary><blockquote>

`53-68`: **Move dynamic `<head>` work to the `metadata` API**

Injecting `<title>` and `<meta>` tags manually inside `<head>` works, but Next 13+ provides the [`export const metadata = …`] API which:

* avoids duplicate titles when nested pages add their own `<title>`
* enables automatic caching & streaming
* keeps Layout JSX cleaner

Refactor when convenient.

---

`69-83`: **Conditional `<body>` blocks duplicate structural elements**

When `wlData` is falsy you render a second `<body>` element; browsers tolerate it, but the HTML spec allows just one. An easier pattern:

```jsx
<body className={roboto.variable}>
  {wlData ? (
    /* app */
  ) : (
    <h3 style={{textAlign: 'center', flex: 1}}>Something went wrong</h3>
  )}
</body>
```

</blockquote></details>
<details>
<summary>src/components/AppRouting/index.jsx (1)</summary><blockquote>

`49-49`: **Prop validation missing after signature change**

`AppRouting` now expects a new `wlData` prop but the component doesn’t document the requirement.  
Add runtime validation (e.g. with `prop-types`) or a TS interface to avoid accidental `undefined`.

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between f7321e9c22fe10d83f809ad1a4208979fa84bf89 and d8cbe3e8aaa33675b38975fb5c2461338fd49563.

</details>

<details>
<summary>📒 Files selected for processing (4)</summary>

* `dok-wallet-blockchain-networks` (1 hunks)
* `src/app/layout.js` (2 hunks)
* `src/components/AppRouting/index.jsx` (4 hunks)
* `src/components/Header/index.jsx` (1 hunks)

</details>

<details>
<summary>🔇 Additional comments (2)</summary><blockquote>

<details>
<summary>dok-wallet-blockchain-networks (1)</summary>

`1-1`: **Approve submodule reference update**

The subproject pointer has been updated to commit `e9afeb419a7db3ca258277df003a50ecaf547d27`. This aligns with the broader refactoring and introduces no immediate issues.

</details>
<details>
<summary>src/components/Header/index.jsx (1)</summary>

`6-6`: **Import looks good**

The unused helpers were removed; only `getAppLogo` remains. No issues spotted.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: NONE
submitted_at: 2025-05-02T15:05:59Z
user: login: divyangkhatri
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-02T15:08:29Z
user: login: coderabbitai[bot]
state: COMMENTED
author_association: NONE
submitted_at: 2025-05-02T15:08:47Z
user: login: divyangkhatri
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-02T15:10:56Z
user: login: coderabbitai[bot]
state: COMMENTED
author_association: NONE
submitted_at: 2025-05-02T15:11:55Z
user: login: divyangkhatri
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-02T15:12:28Z
user: login: coderabbitai[bot]
state: COMMENTED
author_association: NONE
submitted_at: 2025-05-02T15:12:52Z
user: login: divyangkhatri
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-02T15:15:50Z
user: login: coderabbitai[bot]
state: COMMENTED
author_association: NONE
submitted_at: 2025-05-02T15:16:52Z
user: login: mklakers
state: APPROVED
author_association: NONE
submitted_at: 2025-05-02T15:25:01Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 1**

<details>
<summary>♻️ Duplicate comments (1)</summary><blockquote>

<details>
<summary>src/app/layout.js (1)</summary><blockquote>

`27-34`: _🛠️ Refactor suggestion_

**Improve host header handling**

While you've correctly implemented the fix to use `x-forwarded-host` as a fallback for the host header, there's still a potential issue if both headers are missing. If `host` is null or undefined, `host.split(':')` will throw an error.


```diff
    const headersList = await headers();
    const host = headersList.get('x-forwarded-host') ?? headersList.get('host');
+   if (!host) {
+     throw new Error('Missing host header');
+   }
    const firstHost = host.split(':')[0];
```

</blockquote></details>

</blockquote></details>

<details>
<summary>🧹 Nitpick comments (1)</summary><blockquote>

<details>
<summary>src/app/layout.js (1)</summary><blockquote>

`55-65`: **Consider using Next.js Metadata API instead of direct head elements**

Next.js 13+ provides a Metadata API that's preferred over directly defining head elements.


Consider using the Metadata API:

```javascript
// At the top level of layout.js
export async function generateMetadata({ params }) {
  // Fetch white label data (or reuse if already fetched)
  const wlData = // ...
  
  return {
    title: wlData?.title || 'Dok Wallet',
    verification: {
      google: wlData?.metadata?.google_site_verification,
    },
    icons: {
      icon: wlData?.appIcon?.light ?? '/dokwallet.ico',
    },
  };
}
```

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro (Legacy)**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between d8cbe3e8aaa33675b38975fb5c2461338fd49563 and a4db519349742488e0fbbf1ca068a2306fd9312b.

</details>

<details>
<summary>📒 Files selected for processing (2)</summary>

* `src/app/layout.js` (2 hunks)
* `src/components/AppRouting/index.jsx` (4 hunks)

</details>

<details>
<summary>🚧 Files skipped from review as they are similar to previous changes (1)</summary>

* src/components/AppRouting/index.jsx

</details>

<details>
<summary>🔇 Additional comments (3)</summary><blockquote>

<details>
<summary>src/app/layout.js (3)</summary>

`36-43`: **LGTM - Proper locale handling**

The locale fallback mechanism is properly implemented, prioritizing an existing locale, then the white label default, and finally 'en'. You've also correctly passed the locale to `getMessages({locale})`.

---

`50-52`: **Good use of optional chaining and fallbacks**

Appropriate use of optional chaining and fallback values for metadata properties.

---

`71-71`: **LGTM - Passing wlData as prop instead of fetching internally**

Good job passing the white label data as a prop to AppRouting instead of having it fetch the data internally. This centralizes the data fetching logic and improves component responsibility separation.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: NONE
submitted_at: 2025-05-02T15:29:22Z

Review comments:
diff_hunk: @@ -6,6 +6,10 @@ import ThemeProvider from 'theme/ThemeContext';
 import React from 'react';
 import {NextIntlClientProvider} from 'next-intl';
 import {getLocale, getMessages} from 'next-intl/server';
+import {getWhiteLabelInfo} from 'dok-wallet-blockchain-networks/service/dokApi';
+import {headers} from 'next/headers';
+import {setWhiteLabelInfo} from 'whitelabel/whiteLabelInfo';
+import {isLocaleSet} from 'utils/updateLocale';
 
path: src/app/layout.js
user: login: coderabbitai[bot]
body: _⚠️ Potential issue_

**Global white-label state can leak between requests**

`setWhiteLabelInfo` writes the fetched object into a module-level singleton.  
Because `app/layout.js` is a _server component_, its module is **shared across concurrent requests** while the process is warm. When two hosts hit the same instance, host-A’s data can be served to host-B until the next request mutates the singleton again — a classic cross-tenant data-leak.

Prefer a pure functional flow:

1. Return the fetched `wlData` through props (as you already do) **only**.  
2. If the client still needs the data, hydrate it with a React context/provider instead of a Node-side singleton.  
3. Remove the server-side `setWhiteLabelInfo` call.

<!-- This is an auto-generated reply by CodeRabbit -->
created_at: 2025-05-02T15:05:58Z
author_association: NONE
diff_hunk: @@ -18,27 +22,65 @@ const roboto = Roboto({
 export default async function RootLayout({children}) {
   let locale;
   let messages;
+  let wlData;
 
   try {
-    locale = await getLocale();
+    const headersList = await headers();
+    const host = headersList.get('host');
+    const firstHost = host.split(':')[0];
+    const resp = await getWhiteLabelInfo(firstHost);
+    wlData = resp?.data;
+    setWhiteLabelInfo(wlData);
+  } catch (error) {
+    console.error('Error in getting white label:', error);
+  }
+
+  try {
+    const isLocalExist = await isLocaleSet();
+    console.log('isLocalExist', isLocalExist);
+    if (isLocalExist) {
+      locale = await getLocale();
+    } else {
+      locale = wlData?.defaultLocale || 'en';
+    }
     messages = await getMessages();
path: src/app/layout.js
user: login: coderabbitai[bot]
body: _🛠️ Refactor suggestion_

**Locale fall-back can silently break translations**

`getMessages()` loads messages for the _current request locale_ (set via `getLocale()` or `unstable_setRequestLocale`).  
Here you override the locale **after** the framework already derived it (`getLocale()`), but you don’t pass the chosen locale to `getMessages()`. If `wlData.defaultLocale` differs from what Next-Intl expects, the file system lookup will fail silently and return `{}`.

Consider passing the locale explicitly:

```diff
- messages = await getMessages();
+ messages = await getMessages({locale});
```




<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

`````suggestion
  try {
    const isLocalExist = await isLocaleSet();
    console.log('isLocalExist', isLocalExist);
    if (isLocalExist) {
      locale = await getLocale();
    } else {
      locale = wlData?.defaultLocale || 'en';
    }
    messages = await getMessages({locale});
`````

</details>

<!-- suggestion_end -->

<!-- This is an auto-generated reply by CodeRabbit -->
created_at: 2025-05-02T15:05:58Z
author_association: NONE
diff_hunk: @@ -18,27 +22,65 @@ const roboto = Roboto({
 export default async function RootLayout({children}) {
   let locale;
   let messages;
+  let wlData;
 
   try {
-    locale = await getLocale();
+    const headersList = await headers();
+    const host = headersList.get('host');
+    const firstHost = host.split(':')[0];
+    const resp = await getWhiteLabelInfo(firstHost);
+    wlData = resp?.data;
+    setWhiteLabelInfo(wlData);
+  } catch (error) {
+    console.error('Error in getting white label:', error);
+  }
path: src/app/layout.js
user: login: coderabbitai[bot]
body: _💡 Verification agent_

<details>
<summary>❓ Verification inconclusive</summary>

**Host parsing is brittle & mis-uses `headers()`**

* `headers()` is synchronous; `await` is unnecessary.
* `host` might be `undefined` (e.g. behind certain proxies) – calling `split` would crash the request.
* Relying solely on the raw `Host` header is susceptible to spoofing. Consider `x-forwarded-host` or a trusted list.

```diff
-const headersList = await headers();
-const host = headersList.get('host');
-const firstHost = host.split(':')[0];
+const hdrs = headers();
+const hostHeader = hdrs.get('x-forwarded-host') ?? hdrs.get('host') ?? '';
+if (!hostHeader) {
+  throw new Error('Missing host header');
+}
+const firstHost = hostHeader.split(':')[0];
```

---



</details>

**Harden host header parsing & remove unnecessary await**

- File: src/app/layout.js (lines 28–36)
- `headers()` from next/headers is synchronous—drop the `await`.
- `.get('host')` can return `null`, causing `.split` to throw.
- Raw `Host` can be spoofed; prefer `x-forwarded-host` or validate against an allow‐list.

```diff
-   const headersList = await headers();
-   const host = headersList.get('host');
-   const firstHost = host.split(':')[0];
+   const hdrs = headers();
+   const hostHeader = hdrs.get('x-forwarded-host') ?? hdrs.get('host');
+   if (!hostHeader) {
+     throw new Error('Missing host header');
+   }
+   const firstHost = hostHeader.split(':')[0];
```



<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

`````suggestion
    const hdrs = headers();
    const hostHeader = hdrs.get('x-forwarded-host') ?? hdrs.get('host');
    if (!hostHeader) {
      throw new Error('Missing host header');
    }
    const firstHost = hostHeader.split(':')[0];
    const resp = await getWhiteLabelInfo(firstHost);
    wlData = resp?.data;
    setWhiteLabelInfo(wlData);
  } catch (error) {
    console.error('Error in getting white label:', error);
  }
`````

</details>

<!-- suggestion_end -->

<!-- This is an auto-generated reply by CodeRabbit -->
created_at: 2025-05-02T15:05:58Z
author_association: NONE
diff_hunk: @@ -175,39 +170,25 @@ function AppRouting({children}) {
       }
     }
     // eslint-disable-next-line react-hooks/exhaustive-deps
-  }, [isReduxStoreLoad, isWhiteLabelInfoFetching]);
+  }, [isReduxStoreLoad]);
 
   useEffect(() => {
-    getWhiteLabelInfo()
-      .then(async resp => {
-        setIsWhiteLabelInfoFetching(false);
-        if (resp?.data) {
-          setWhiteLabelInfo(resp?.data);
-          const localeSetCheck = await isLocaleSet();
-          if (!localeSetCheck) {
-            setUserLocale(resp?.data?.defaultLocale || 'en');
-          }
+    setWhiteLabelInfo(wlData);
+    (async () => {
+      try {
+        const localeSetCheck = await isLocaleSet();
+        if (!localeSetCheck) {
+          setUserLocale(resp?.data?.defaultLocale || 'en');
         }
-      })
-      .catch(e => {
-        console.error('Error in fetching white label info');
-        setIsWhiteLabelInfoFetching(false);
-      });
-    // eslint-disable-next-line react-hooks/exhaustive-deps
-  }, []);
+      } catch {
+        console.error('error in set local', e);
+      }
+    })();
+  }, [wlData]);
 
path: src/components/AppRouting/index.jsx
user: login: coderabbitai[bot]
body: _⚠️ Potential issue_

**`resp` & `e` are undefined – effect throws on every render**

Two small but fatal typos:

1. `resp` is not declared; you meant to use `wlData`.
2. `catch { … e … }` uses `e` without binding it.

```diff
-useEffect(() => {
-  setWhiteLabelInfo(wlData);
-  (async () => {
-    try {
-      const localeSetCheck = await isLocaleSet();
-      if (!localeSetCheck) {
-        setUserLocale(resp?.data?.defaultLocale || 'en');
-      }
-    } catch {
-      console.error('error in set local', e);
-    }
-  })();
-}, [wlData]);
+useEffect(() => {
+  setWhiteLabelInfo(wlData);
+  (async () => {
+    try {
+      const localeSetCheck = await isLocaleSet();
+      if (!localeSetCheck) {
+        setUserLocale(wlData?.defaultLocale || 'en');
+      }
+    } catch (err) {
+      console.error('Error setting locale', err);
+    }
+  })();
+}, [wlData]);
```

<!-- This is an auto-generated reply by CodeRabbit -->
created_at: 2025-05-02T15:05:58Z
author_association: NONE
diff_hunk: @@ -175,39 +170,25 @@ function AppRouting({children}) {
       }
     }
     // eslint-disable-next-line react-hooks/exhaustive-deps
-  }, [isReduxStoreLoad, isWhiteLabelInfoFetching]);
+  }, [isReduxStoreLoad]);
 
   useEffect(() => {
-    getWhiteLabelInfo()
-      .then(async resp => {
-        setIsWhiteLabelInfoFetching(false);
-        if (resp?.data) {
-          setWhiteLabelInfo(resp?.data);
-          const localeSetCheck = await isLocaleSet();
-          if (!localeSetCheck) {
-            setUserLocale(resp?.data?.defaultLocale || 'en');
-          }
+    setWhiteLabelInfo(wlData);
+    (async () => {
+      try {
+        const localeSetCheck = await isLocaleSet();
+        if (!localeSetCheck) {
+          setUserLocale(resp?.data?.defaultLocale || 'en');
         }
-      })
-      .catch(e => {
-        console.error('Error in fetching white label info');
-        setIsWhiteLabelInfoFetching(false);
-      });
-    // eslint-disable-next-line react-hooks/exhaustive-deps
-  }, []);
+      } catch {
+        console.error('error in set local', e);
+      }
+    })();
+  }, [wlData]);
 
path: src/components/AppRouting/index.jsx
user: login: divyangkhatri
body: fixed
created_at: 2025-05-02T15:08:29Z
author_association: CONTRIBUTOR
diff_hunk: @@ -175,39 +170,25 @@ function AppRouting({children}) {
       }
     }
     // eslint-disable-next-line react-hooks/exhaustive-deps
-  }, [isReduxStoreLoad, isWhiteLabelInfoFetching]);
+  }, [isReduxStoreLoad]);
 
   useEffect(() => {
-    getWhiteLabelInfo()
-      .then(async resp => {
-        setIsWhiteLabelInfoFetching(false);
-        if (resp?.data) {
-          setWhiteLabelInfo(resp?.data);
-          const localeSetCheck = await isLocaleSet();
-          if (!localeSetCheck) {
-            setUserLocale(resp?.data?.defaultLocale || 'en');
-          }
+    setWhiteLabelInfo(wlData);
+    (async () => {
+      try {
+        const localeSetCheck = await isLocaleSet();
+        if (!localeSetCheck) {
+          setUserLocale(resp?.data?.defaultLocale || 'en');
         }
-      })
-      .catch(e => {
-        console.error('Error in fetching white label info');
-        setIsWhiteLabelInfoFetching(false);
-      });
-    // eslint-disable-next-line react-hooks/exhaustive-deps
-  }, []);
+      } catch {
+        console.error('error in set local', e);
+      }
+    })();
+  }, [wlData]);
 
path: src/components/AppRouting/index.jsx
user: login: coderabbitai[bot]
body: @divyangkhatri Great! Thanks for addressing those issues. The code should work correctly now.

<!-- This is an auto-generated reply by CodeRabbit -->
created_at: 2025-05-02T15:08:47Z
author_association: NONE
diff_hunk: @@ -6,6 +6,10 @@ import ThemeProvider from 'theme/ThemeContext';
 import React from 'react';
 import {NextIntlClientProvider} from 'next-intl';
 import {getLocale, getMessages} from 'next-intl/server';
+import {getWhiteLabelInfo} from 'dok-wallet-blockchain-networks/service/dokApi';
+import {headers} from 'next/headers';
+import {setWhiteLabelInfo} from 'whitelabel/whiteLabelInfo';
+import {isLocaleSet} from 'utils/updateLocale';
 
path: src/app/layout.js
user: login: divyangkhatri
body: removed
created_at: 2025-05-02T15:10:55Z
author_association: CONTRIBUTOR
diff_hunk: @@ -6,6 +6,10 @@ import ThemeProvider from 'theme/ThemeContext';
 import React from 'react';
 import {NextIntlClientProvider} from 'next-intl';
 import {getLocale, getMessages} from 'next-intl/server';
+import {getWhiteLabelInfo} from 'dok-wallet-blockchain-networks/service/dokApi';
+import {headers} from 'next/headers';
+import {setWhiteLabelInfo} from 'whitelabel/whiteLabelInfo';
+import {isLocaleSet} from 'utils/updateLocale';
 
path: src/app/layout.js
user: login: coderabbitai[bot]
body: @divyangkhatri Great! Removing the `setWhiteLabelInfo` call in the server component was the right approach to prevent potential cross-tenant data leakage. Passing the data via props as you're doing maintains proper request isolation.

---

<details>
<summary>✏️ Learnings added</summary>

```
Learnt from: divyangkhatri
PR: dokwallet/dokwallet_web#4
File: src/app/layout.js:0-0
Timestamp: 2025-05-02T15:11:44.093Z
Learning: In Next.js server components, avoid using mutable global state (like calling functions that modify module-level singletons) as they can cause cross-tenant data leakage between concurrent requests. Server components are shared across requests while the server process is warm. Instead, use a pure functional approach by passing data through props and React context providers.
```

> Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure [review instructions](https://docs.coderabbit.ai/guides/review-instructions). You can manage existing learnings in the [app](https://app.coderabbit.ai/learnings).

</details>



<!-- This is an auto-generated reply by CodeRabbit -->
created_at: 2025-05-02T15:11:55Z
author_association: NONE
diff_hunk: @@ -18,27 +22,65 @@ const roboto = Roboto({
 export default async function RootLayout({children}) {
   let locale;
   let messages;
+  let wlData;
 
   try {
-    locale = await getLocale();
+    const headersList = await headers();
+    const host = headersList.get('host');
+    const firstHost = host.split(':')[0];
+    const resp = await getWhiteLabelInfo(firstHost);
+    wlData = resp?.data;
+    setWhiteLabelInfo(wlData);
+  } catch (error) {
+    console.error('Error in getting white label:', error);
+  }
+
+  try {
+    const isLocalExist = await isLocaleSet();
+    console.log('isLocalExist', isLocalExist);
+    if (isLocalExist) {
+      locale = await getLocale();
+    } else {
+      locale = wlData?.defaultLocale || 'en';
+    }
     messages = await getMessages();
path: src/app/layout.js
user: login: divyangkhatri
body: fixed
created_at: 2025-05-02T15:12:28Z
author_association: CONTRIBUTOR
diff_hunk: @@ -18,27 +22,65 @@ const roboto = Roboto({
 export default async function RootLayout({children}) {
   let locale;
   let messages;
+  let wlData;
 
   try {
-    locale = await getLocale();
+    const headersList = await headers();
+    const host = headersList.get('host');
+    const firstHost = host.split(':')[0];
+    const resp = await getWhiteLabelInfo(firstHost);
+    wlData = resp?.data;
+    setWhiteLabelInfo(wlData);
+  } catch (error) {
+    console.error('Error in getting white label:', error);
+  }
+
+  try {
+    const isLocalExist = await isLocaleSet();
+    console.log('isLocalExist', isLocalExist);
+    if (isLocalExist) {
+      locale = await getLocale();
+    } else {
+      locale = wlData?.defaultLocale || 'en';
+    }
     messages = await getMessages();
path: src/app/layout.js
user: login: coderabbitai[bot]
body: @divyangkhatri Thanks for fixing that! This ensures your translations will work correctly with your locale fallback mechanism.

(／^.^)／ ~🥕

<!-- This is an auto-generated reply by CodeRabbit -->
created_at: 2025-05-02T15:12:52Z
author_association: NONE
diff_hunk: @@ -18,27 +22,65 @@ const roboto = Roboto({
 export default async function RootLayout({children}) {
   let locale;
   let messages;
+  let wlData;
 
   try {
-    locale = await getLocale();
+    const headersList = await headers();
+    const host = headersList.get('host');
+    const firstHost = host.split(':')[0];
+    const resp = await getWhiteLabelInfo(firstHost);
+    wlData = resp?.data;
+    setWhiteLabelInfo(wlData);
+  } catch (error) {
+    console.error('Error in getting white label:', error);
+  }
path: src/app/layout.js
user: login: divyangkhatri
body: fixed
in new version next-js headers() require await because it return promise
created_at: 2025-05-02T15:15:50Z
author_association: CONTRIBUTOR
diff_hunk: @@ -18,27 +22,65 @@ const roboto = Roboto({
 export default async function RootLayout({children}) {
   let locale;
   let messages;
+  let wlData;
 
   try {
-    locale = await getLocale();
+    const headersList = await headers();
+    const host = headersList.get('host');
+    const firstHost = host.split(':')[0];
+    const resp = await getWhiteLabelInfo(firstHost);
+    wlData = resp?.data;
+    setWhiteLabelInfo(wlData);
+  } catch (error) {
+    console.error('Error in getting white label:', error);
+  }
path: src/app/layout.js
user: login: coderabbitai[bot]
body: <details>
<summary>🧩 Analysis chain</summary>

@divyangkhatri You're absolutely right. In Next.js 14.2.0+ (released April 18, 2024), the `headers()` function now returns a Promise that resolves to a Headers object, so `await` is indeed required. Thank you for the correction!

I see you've also implemented the suggestion to check for `x-forwarded-host` first, which is a good security practice. Nice work on the fixes.



---

🌐 Web query:

```web
Does Next.js headers() function return a promise in newer versions?
```

💡 Result:

Yes, in Next.js 15, the `headers()` function has been changed to an asynchronous function that returns a promise. This is a significant change from previous versions (14 and earlier) where it was a synchronous function[1].

## Changes in Next.js 15

In Next.js 15, you must now use `async/await` or React's `use` function when working with the `headers()` function. Here's how it should be implemented:

```javascript
import { headers } from 'next/headers'

export default async function Page() {
  const headersList = await headers()
  const userAgent = headersList.get('user-agent')
  
  // Use the headers data
}
```

To help with backwards compatibility, Next.js 15 still supports accessing it synchronously, but this behavior will be deprecated in the future[1]. This means code that doesn't await the headers function might still work for now, but will break in future versions.

## Why This Change Was Made

The change to an asynchronous API was made to better support Next.js's rendering model and to enable more optimization opportunities, particularly with features like `dynamicIO`[6]. This allows Next.js to better determine which parts of your application should be prerendered and which should be rendered dynamically.

## Migration Issues

This change has created some compatibility issues with libraries that haven't yet been updated to work with the new Promise-based API. For example, some users have reported issues with next-auth, which was still using the synchronous approach shortly after Next.js 15 was released[2].

If you're seeing warnings or errors about synchronous access to request information, you'll need to:

1. Update your own code to use `await headers()`
2. Check if third-party libraries you're using have published Next.js 15-compatible versions[6]
3. As a last resort, you can use `await connection()` from 'next/server' before calling functions that use the old API pattern[6]

## Version History

The change to an async function was introduced in version 15.0.0-RC[1]. If you're using Next.js 14.x or earlier, the `headers()` function is still synchronous.

Citations:

- 1: https://nextjs.org/docs-wip/app/api-reference/functions/headers
- 2: https://github.com/vercel/next.js/discussions/70633
- 3: https://nextjs.org/docs/pages/api-reference/config/next-config-js/headers
- 4: https://nextjs.org/docs/messages/promise-in-next-config
- 5: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then
- 6: https://nextjs.org/docs/messages/next-prerender-sync-headers
- 7: https://github.com/vercel/next.js/discussions/74255
- 8: https://www.sitepoint.com/community/t/promise-pending-when-json-has-been-returned/433729
- 9: https://www.pronextjs.dev/workshops/next-js-react-server-component-rsc-architecture-jbvxk/handling-headers-and-parameters-in-next-js-15-cafu0

---



</details>

@divyangkhatri You're absolutely right. According to the latest information, in Next.js 15, the `headers()` function has been changed to return a Promise rather than synchronously returning a Headers object. This means your approach using `await headers()` is correct for the newer versions.

Thank you for pointing this out - it's important to stay updated with these API changes.

---

<details>
<summary>✏️ Learnings added</summary>

```
Learnt from: divyangkhatri
PR: dokwallet/dokwallet_web#4
File: src/app/layout.js:0-0
Timestamp: 2025-05-02T15:16:38.156Z
Learning: In Next.js 14.2.0 and later versions, the `headers()` function from 'next/headers' returns a Promise and requires await, unlike earlier versions where it was synchronous.
```

---

```
Learnt from: divyangkhatri
PR: dokwallet/dokwallet_web#4
File: src/app/layout.js:0-0
Timestamp: 2025-05-02T15:16:38.156Z
Learning: In Next.js 15 and later versions, the `headers()` function from 'next/headers' returns a Promise and requires await, unlike earlier versions where it was synchronous. Next.js 15 still supports synchronous access for backwards compatibility, but this will be deprecated in future releases.
```

> Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure [review instructions](https://docs.coderabbit.ai/guides/review-instructions). You can manage existing learnings in the [app](https://app.coderabbit.ai/learnings).

</details>



<!-- This is an auto-generated reply by CodeRabbit -->
created_at: 2025-05-02T15:16:52Z
author_association: NONE
diff_hunk: @@ -18,27 +21,63 @@ const roboto = Roboto({
 export default async function RootLayout({children}) {
   let locale;
   let messages;
+  let wlData;
 
   try {
-    locale = await getLocale();
-    messages = await getMessages();
+    const headersList = await headers();
+    const host = headersList.get('x-forwarded-host') ?? headersList.get('host');
+    const firstHost = host.split(':')[0];
+    const resp = await getWhiteLabelInfo(firstHost);
+    wlData = resp?.data;
+  } catch (error) {
+    console.error('Error in getting white label:', error);
+  }
+
+  try {
+    const isLocalExist = await isLocaleSet();
+    if (isLocalExist) {
+      locale = await getLocale();
+    } else {
+      locale = wlData?.defaultLocale || 'en';
+    }
+    messages = await getMessages({locale});
   } catch (error) {
     console.error('Error loading locale or messages:', error);
     locale = 'en';
     messages = {};
   }
 
+  const googleSiteVerification = wlData?.metadata?.google_site_verification;
+  const title = wlData?.title || 'Dok Wallet';
+  const appIcon = wlData?.appIcon?.light ?? '/dokwallet.ico';
   return (
     <html lang={locale}>
-      <ThemeProvider>
-        <body className={roboto.variable}>
-          <NextIntlClientProvider locale={locale} messages={messages}>
-            <StateProvider>
-              <AppRouting>{children}</AppRouting>
-            </StateProvider>
-          </NextIntlClientProvider>
+      <head>
+        {typeof googleSiteVerification === 'string' &&
+          !!googleSiteVerification && (
+            <meta
+              name='google-site-verification'
+              content={googleSiteVerification}
+            />
+          )}
+        <link rel='icon' href={appIcon} />
+        <title>{title}</title>
+      </head>
+      {wlData ? (
+        <ThemeProvider>
+          <body className={roboto.variable}>
+            <NextIntlClientProvider locale={locale} messages={messages}>
+              <StateProvider>
+                <AppRouting wlData={wlData}>{children}</AppRouting>
+              </StateProvider>
+            </NextIntlClientProvider>
+          </body>
+        </ThemeProvider>
+      ) : (
+        <body>
+          <h3 style={{textAlign: 'center', flex: 1}}>Something went wrong</h3>
         </body>
-      </ThemeProvider>
+      )}
path: src/app/layout.js
user: login: coderabbitai[bot]
body: _🛠️ Refactor suggestion_

**Avoid multiple body tags in conditional renders**

In Next.js, having multiple `<body>` tags in a conditional render is not recommended. It's better to conditionally render content inside a single `<body>`.


```diff
-      {wlData ? (
-        <ThemeProvider>
-          <body className={roboto.variable}>
-            <NextIntlClientProvider locale={locale} messages={messages}>
-              <StateProvider>
-                <AppRouting wlData={wlData}>{children}</AppRouting>
-              </StateProvider>
-            </NextIntlClientProvider>
-          </body>
-        </ThemeProvider>
-      ) : (
-        <body>
-          <h3 style={{textAlign: 'center', flex: 1}}>Something went wrong</h3>
-        </body>
-      )}
+      <body className={wlData ? roboto.variable : ''}>
+        {wlData ? (
+          <ThemeProvider>
+            <NextIntlClientProvider locale={locale} messages={messages}>
+              <StateProvider>
+                <AppRouting wlData={wlData}>{children}</AppRouting>
+              </StateProvider>
+            </NextIntlClientProvider>
+          </ThemeProvider>
+        ) : (
+          <h3 style={{textAlign: 'center', flex: 1}}>Something went wrong</h3>
+        )}
+      </body>
```


<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

`````suggestion
      <body className={wlData ? roboto.variable : ''}>
        {wlData ? (
          <ThemeProvider>
            <NextIntlClientProvider locale={locale} messages={messages}>
              <StateProvider>
                <AppRouting wlData={wlData}>{children}</AppRouting>
              </StateProvider>
            </NextIntlClientProvider>
          </ThemeProvider>
        ) : (
          <h3 style={{textAlign: 'center', flex: 1}}>Something went wrong</h3>
        )}
      </body>
`````

</details>

<!-- suggestion_end -->

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-05-02T15:29:21Z
author_association: NONE

PR comments:
user: login: coderabbitai[bot]
created_at: 2025-05-02T15:01:13Z
body: <!-- This is an auto-generated comment: summarize by coderabbit.ai -->
<!-- walkthrough_start -->

## Walkthrough

This update refactors how white label configuration data is fetched and managed in the application. The logic for retrieving white label info based on the request host is moved from the `AppRouting` component to the `RootLayout` component, which now handles setting global white label data, locale determination, and dynamic metadata in the HTML `<head>`. The `AppRouting` component is updated to receive white label data as a prop instead of fetching it internally. Additionally, unused imports and head-manipulating side effects are removed from the `Header` component.

## Changes

| File(s)                                               | Change Summary |
|-------------------------------------------------------|---------------|
| `src/app/layout.js`                                   | Refactored to fetch white label info based on request host, set it globally, determine locale, extract metadata, and render dynamic `<head>` content; passes white label data to `AppRouting` and adds error handling for data fetching and locale/messages loading. |
| `src/components/AppRouting/index.jsx`                 | Refactored to accept `wlData` as a prop instead of fetching white label info internally; removed related state, effects, and imports; simplified routing logic and dependencies. |
| `src/components/Header/index.jsx`                     | Removed unused imports and the effect that updated document title and favicon; retained only the necessary import for logo retrieval. |
| `dok-wallet-blockchain-networks` (subproject ref)     | Updated commit reference from `d0fe0a8...` to `e9afeb4...`; no other changes. |

## Sequence Diagram(s)

```mermaid
sequenceDiagram
    participant Client
    participant RootLayout
    participant WhiteLabelService
    participant AppRouting

    Client->>RootLayout: Request page
    RootLayout->>WhiteLabelService: getWhiteLabelInfo(hostname)
    WhiteLabelService-->>RootLayout: wlData
    RootLayout->>RootLayout: Set global white label info
    RootLayout->>RootLayout: Determine locale, extract metadata
    RootLayout->>AppRouting: Render with wlData prop
    AppRouting->>AppRouting: Use wlData for routing and locale
```

## Possibly related PRs

- [dokwallet/dokwallet_web#2](https://github.com/dokwallet/dokwallet_web/pull/2): Updates the commit reference of the `dok-wallet-blockchain-networks` subproject, similar to this PR but to a different commit.
- [dokwallet/dokwallet_web#3](https://github.com/dokwallet/dokwallet_web/pull/3): Adds Google site verification meta tags in `AppRouting`, which this PR removes and relocates to `RootLayout`, making them directly related.

## Poem

> In the warren of code, a new path we found,  
> White label secrets fetched from the ground.  
> No more chasing info in every nook,  
> Now RootLayout’s the chef, with a single look.  
> AppRouting’s lighter, Header’s clean—  
> A rabbit’s delight, neat and serene!  
> 🥕✨

<!-- walkthrough_end -->
<!-- This is an auto-generated comment: all tool run failures by coderabbit.ai -->

> [!WARNING]
> There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.
> 
> <details>
> <summary>🔧 ESLint</summary>
> 
> > If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.
> 
> yarn install v1.22.22
> [1/4] Resolving packages...
> warning Lockfile has incorrect entry for "elliptic@6.5.4". Ignoring it.
> [2/4] Fetching packages...
> info There appears to be trouble with your network connection. Retrying...
> info There appears to be trouble with your network connection. Retrying...
> info There appears to be trouble with your network connection. Retrying...
> info There appears to be trouble with your network connection. Retrying...
> info There appears to be trouble with your network connection. Retrying...
> info There appears to be trouble with your network connection. Retrying...
> info There appears to be trouble with your network connection. Retrying...
> info There appears to be trouble with your network connection. Retrying...
> error Error: https://registry.yarnpkg.com/@mui/icons-material/-/icons-material-6.4.8.tgz: ESOCKETTIMEDOUT
>     at ClientRequest.<anonymous> (/opt/yarn-v1.22.22/lib/cli.js:142042:19)
>     at Object.onceWrapper (node:events:633:28)
>     at ClientRequest.emit (node:events:519:28)
>     at TLSSocket.emitRequestTimeout (node:_http_client:851:9)
>     at Object.onceWrapper (node:events:633:28)
>     at TLSSocket.emit (node:events:531:35)
>     at Socket._onTimeout (node:net:595:8)
>     at listOnTimeout (node:internal/timers:594:17)
>     at process.processTimers (node:internal/timers:529:7)
> info Visit https://yarnpkg.com/en/docs/cli/install for documentation about this command.
> info There appears to be trouble with your network connection. Retrying...
> info There appears to be trouble with your network connection. Retrying...
> 
> 
> 
> </details>

<!-- end of auto-generated comment: all tool run failures by coderabbit.ai -->
<!-- internal state start -->


<!-- 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 -->

<!-- internal state end -->
<!-- tips_start -->

---



<details>
<summary>🪧 Tips</summary>

### Chat

There are 3 ways to chat with [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=dokwallet/dokwallet_web&utm_content=4):

- Review comments: Directly reply to a review comment made by CodeRabbit. Example:
  - `I pushed a fix in commit <commit_id>, please review it.`
  - `Generate unit testing code for this file.`
  - `Open a follow-up GitHub issue for this discussion.`
- Files and specific lines of code (under the "Files changed" tab): Tag `@coderabbitai` in a new review comment at the desired location with your query. Examples:
  - `@coderabbitai generate unit testing code for this file.`
  -	`@coderabbitai modularize this function.`
- PR comments: Tag `@coderabbitai` in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
  - `@coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.`
  - `@coderabbitai read src/utils.ts and generate unit testing code.`
  - `@coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.`
  - `@coderabbitai help me debug CodeRabbit configuration file.`

### Support

Need help? Create a ticket on our [support page](https://www.coderabbit.ai/contact-us/support) for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

### CodeRabbit Commands (Invoked using PR comments)

- `@coderabbitai pause` to pause the reviews on a PR.
- `@coderabbitai resume` to resume the paused reviews.
- `@coderabbitai review` to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
- `@coderabbitai full review` to do a full review from scratch and review all the files again.
- `@coderabbitai summary` to regenerate the summary of the PR.
- `@coderabbitai generate sequence diagram` to generate a sequence diagram of the changes in this PR.
- `@coderabbitai resolve` resolve all the CodeRabbit review comments.
- `@coderabbitai configuration` to show the current CodeRabbit configuration for the repository.
- `@coderabbitai help` to get help.

### Other keywords and placeholders

- Add `@coderabbitai ignore` anywhere in the PR description to prevent this PR from being reviewed.
- Add `@coderabbitai summary` to generate the high-level summary at a specific location in the PR description.
- Add `@coderabbitai` anywhere in the PR title to generate the title automatically.

### CodeRabbit Configuration File (`.coderabbit.yaml`)

- You can programmatically configure CodeRabbit by adding a `.coderabbit.yaml` file to the root of your repository.
- Please see the [configuration documentation](https://docs.coderabbit.ai/guides/configure-coderabbit) for more information.
- If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: `# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json`

### Documentation and Community

- Visit our [Documentation](https://docs.coderabbit.ai) for detailed information on how to use CodeRabbit.
- Join our [Discord Community](http://discord.gg/coderabbit) to get help, request features, and share feedback.
- Follow us on [X/Twitter](https://twitter.com/coderabbitai) for updates and announcements.

</details>

<!-- tips_end -->
author_association: NONE
user: login: sonarqubecloud[bot]
created_at: 2025-05-02T15:15:36Z
body: ## [![Quality Gate Passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-passed-20px.png 'Quality Gate Passed')](https://sonarcloud.io/dashboard?id=dokwallet_dokwallet_web&pullRequest=4) **Quality Gate passed**  
Issues  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [4 New issues](https://sonarcloud.io/project/issues?id=dokwallet_dokwallet_web&pullRequest=4&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/accepted-16px.png '') [0 Accepted issues](https://sonarcloud.io/project/issues?id=dokwallet_dokwallet_web&pullRequest=4&issueStatuses=ACCEPTED)

Measures  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=dokwallet_dokwallet_web&pullRequest=4&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Coverage on New Code](https://sonarcloud.io/component_measures?id=dokwallet_dokwallet_web&pullRequest=4&metric=new_coverage&view=list)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Duplication on New Code](https://sonarcloud.io/component_measures?id=dokwallet_dokwallet_web&pullRequest=4&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarQube Cloud](https://sonarcloud.io/dashboard?id=dokwallet_dokwallet_web&pullRequest=4)


author_association: NONE