Skip to content

Conversation

@AMIRKHANEF
Copy link
Member

@AMIRKHANEF AMIRKHANEF commented Oct 12, 2025

Summary by CodeRabbit

  • New Features

    • In-app notifications: grouped feed for funds, staking rewards and referenda; unread badge, background fetching, auto-mark-as-read; popup and fullscreen views, new /notification and /notification/settings routes.
    • Notification settings: enable/disable, select accounts and chains, per-type controls, dedicated settings screens and pickers.
  • Style

    • Action cards accept nested content and optional color ball/chevron; dashboard header shows Notifications button; buttons can include end icons.
  • Chores

    • Version bumped to 1.13.3 and English translations expanded for notification flows.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 12, 2025

Walkthrough

Adds a notifications subsystem: route entries and start path, popup and fullscreen UIs, popup/fullscreen settings, notification types/constants, Subscan fetch helpers, utilities for formatting/grouping, a reducer-driven useNotifications hook with storage persistence, various UI components/toggles, localization keys, and a package version bump.

Changes

Cohort / File(s) Summary
Routing & defaults
packages/extension-base/src/defaults.ts, packages/extension-ui/src/Popup/routes/featuresRoutes.ts, packages/extension-polkagate/src/util/constants.ts
Registers /notification/ and /notification/settings routes; adds '/notification/' to START_WITH_PATH; extends ExtensionPopups enum (new members/reordering) and adds STORAGE_KEY entries for notifications.
Notification core: hooks, types, utils, helpers
packages/extension-polkagate/src/hooks/useNotifications.ts, packages/extension-polkagate/src/hooks/index.ts, packages/extension-polkagate/src/popup/notification/types.ts, packages/extension-polkagate/src/popup/notification/util.ts, packages/extension-polkagate/src/popup/notification/helpers.ts, packages/extension-polkagate/src/hooks/useChainInfo.ts, packages/extension-polkagate/src/hooks/useTokenPriceBySymbol.ts
New useNotifications hook (reducer, persistence, batching, Subscan fetches); re-exported useNotifications; new notification types and public ChainInfo/Price interface exports; utilities for timestamping, formatting, grouping, and notification generation; Subscan fetch helpers with retry/backoff.
Notification UI — popup
packages/extension-polkagate/src/popup/notification/index.tsx, packages/extension-polkagate/src/popup/notification/NotificationSettings.tsx, packages/extension-polkagate/src/popup/notification/constant.ts, packages/extension-polkagate/src/popup/notification/partials/*, packages/extension-polkagate/src/popup/settings/accountSettings/index.tsx, packages/extension-polkagate/src/popup/settings/index.tsx
Adds popup Notification page and popup settings UI, constants, and numerous partial components (AccountToggle, ChainToggle, NotificationGroup, Partial status components, SelectAccount, SelectChain); wires account settings to notification settings; exports SETTING_PAGES.
Notification UI — fullscreen
packages/extension-polkagate/src/fullscreen/components/layout/Notifications.tsx, packages/extension-polkagate/src/fullscreen/notification/index.tsx, packages/extension-polkagate/src/fullscreen/notification/NotificationSettingsFS.tsx, packages/extension-polkagate/src/fullscreen/notification/partials/*
Adds fullscreen Notification page and fullscreen settings modal with subviews; replaces prior direct button behavior with navigation vs popup opening and integrates ExtensionPopups popup handling and notification button state.
Shared component updates
packages/extension-polkagate/src/components/ActionCard.tsx, packages/extension-polkagate/src/components/TwoToneText.tsx, packages/extension-polkagate/src/partials/UserDashboardHeader.tsx, packages/extension-polkagate/src/components/ActionButton.tsx
ActionCard adds children, showColorBall, showChevron; TwoToneText forwards style when no colored part; header shows Notifications beside fullscreen toggle; ActionButton adds EndIcon prop and centralizes icon rendering.
Popup background integration
packages/extension-ui/src/Popup/contexts/AccountAssetProvider.tsx
Invokes useNotifications(false) within background provider to load/save notifications.
Routing config
packages/extension-ui/src/Popup/routes/featuresRoutes.ts
Adds route entries for /notification/ and /notification/settings.
Package/version & locales
packages/extension/package.json, packages/extension/src/packageInfo.ts, packages/extension/public/locales/en/translation.json
Bumps extension version to 1.13.3 and adds extensive English translation strings for notification features.
Minor style reorder
packages/extension-polkagate/src/fullscreen/settings/NetworkSettings.tsx
Reordered style object property order only (no behavioral change).

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor User
  participant UI as Header / Settings UI
  participant Router as Router / Popups
  participant Page as Notification Page/Popup
  participant Hook as useNotifications
  participant Storage as Storage

  User->>UI: Click Notifications
  UI->>Router: navigate("/notification/") or open popup
  Router->>Page: render Notification UI
  Page->>Hook: initialize/useNotifications()
  Hook->>Storage: load settings & saved notifications
  Hook-->>Page: notifications, grouped items, status flags
  Page->>Hook: markAsRead() / openSettings()
  Hook->>Storage: persist updates
Loading
sequenceDiagram
  autonumber
  participant Hook as useNotifications
  participant Fetch as SubscanHelpers
  participant Utils as util.generate*/group
  participant Storage as Storage

  Hook->>Storage: load saved state
  alt notifications enabled
    Hook->>Fetch: getReceivedFundsInformation(...)
    Hook->>Fetch: getPayoutsInformation(...)
    Hook->>Fetch: getReferendasInformation(...)
    Fetch-->>Hook: data
    Hook->>Utils: generate*Notifications(data)
    Utils-->>Hook: messages
    Hook->>Utils: groupNotificationsByDay(messages)
    Utils-->>Hook: groupedNotifications
    Hook->>Storage: enqueue save(state)
  end
Loading

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120 minutes

Possibly related PRs

Suggested reviewers

  • Nick-1979

Poem

"I hop through code, a tiny sprite,
I gather pings from day and night.
Routes and toggles, lights that blink,
I tuck each notice in a wink.
Hooray — notifications take flight! 🥕"

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The pull request title "feat: introducing new feature 'Notifications'" directly and accurately reflects the primary changes in the changeset. The raw summary demonstrates a comprehensive introduction of a new notifications system, including new notification components, hooks, settings management, data fetchers, UI integrations, and supporting types and constants across multiple files and packages. The title is concise, clear, and uses descriptive language that effectively communicates the main change without being vague or misleading. A developer reviewing the commit history would immediately understand that this PR introduces a new notifications feature to the extension.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 12

🧹 Nitpick comments (1)
packages/extension-polkagate/src/components/TwoToneText.tsx (1)

16-16: Consider removing unnecessary object spread.

Both lines use { ...style }, but React's style attribute accepts the object directly. The spread creates a new object on each render with no benefit here.

Apply this diff to simplify:

 if (!textPartInColor) {
-  return <span style={{ ...style }}>{text}</span>;
+  return <span style={style}>{text}</span>;
 }

 return (
   <span
     dangerouslySetInnerHTML={{
       __html: text.replace(
         textPartInColor,
         `<span style="color: ${color}; ${
           backgroundColor ? `background-color: ${backgroundColor}; border-radius: 6px; padding: 0 5px 0` : ''
         }">${textPartInColor}</span>`
       )
     }}
-    style={{ ...style }}
+    style={style}
   />
 );

Also applies to: 29-29

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2b7aa23 and a97258e.

📒 Files selected for processing (36)
  • packages/extension-base/src/defaults.ts (1 hunks)
  • packages/extension-polkagate/src/components/ActionCard.tsx (4 hunks)
  • packages/extension-polkagate/src/components/TwoToneText.tsx (1 hunks)
  • packages/extension-polkagate/src/fullscreen/components/layout/Notifications.tsx (1 hunks)
  • packages/extension-polkagate/src/fullscreen/notification/NotificationSettingsFS.tsx (1 hunks)
  • packages/extension-polkagate/src/fullscreen/notification/index.tsx (1 hunks)
  • packages/extension-polkagate/src/fullscreen/notification/partials/SelectAccount.tsx (1 hunks)
  • packages/extension-polkagate/src/fullscreen/notification/partials/SelectChain.tsx (1 hunks)
  • packages/extension-polkagate/src/fullscreen/settings/AccountSettings.tsx (4 hunks)
  • packages/extension-polkagate/src/fullscreen/settings/NetworkSettings.tsx (1 hunks)
  • packages/extension-polkagate/src/hooks/index.ts (1 hunks)
  • packages/extension-polkagate/src/hooks/useChainInfo.ts (1 hunks)
  • packages/extension-polkagate/src/hooks/useNotifications.ts (1 hunks)
  • packages/extension-polkagate/src/hooks/useTokenPriceBySymbol.ts (1 hunks)
  • packages/extension-polkagate/src/partials/UserDashboardHeader.tsx (2 hunks)
  • packages/extension-polkagate/src/popup/notification/NotificationSettings.tsx (1 hunks)
  • packages/extension-polkagate/src/popup/notification/constant.ts (1 hunks)
  • packages/extension-polkagate/src/popup/notification/helpers.ts (1 hunks)
  • packages/extension-polkagate/src/popup/notification/hook/useNotificationSettings.ts (1 hunks)
  • packages/extension-polkagate/src/popup/notification/index.tsx (1 hunks)
  • packages/extension-polkagate/src/popup/notification/partials/AccountToggle.tsx (1 hunks)
  • packages/extension-polkagate/src/popup/notification/partials/ChainToggle.tsx (1 hunks)
  • packages/extension-polkagate/src/popup/notification/partials/NotificationGroup.tsx (1 hunks)
  • packages/extension-polkagate/src/popup/notification/partials/Partial.tsx (1 hunks)
  • packages/extension-polkagate/src/popup/notification/partials/SelectAccount.tsx (1 hunks)
  • packages/extension-polkagate/src/popup/notification/partials/SelectChain.tsx (1 hunks)
  • packages/extension-polkagate/src/popup/notification/types.ts (1 hunks)
  • packages/extension-polkagate/src/popup/notification/util.ts (1 hunks)
  • packages/extension-polkagate/src/popup/settings/accountSettings/index.tsx (2 hunks)
  • packages/extension-polkagate/src/popup/settings/index.tsx (1 hunks)
  • packages/extension-polkagate/src/util/constants.ts (2 hunks)
  • packages/extension-ui/src/Popup/contexts/AccountAssetProvider.tsx (2 hunks)
  • packages/extension-ui/src/Popup/routes/featuresRoutes.ts (2 hunks)
  • packages/extension/package.json (1 hunks)
  • packages/extension/public/locales/en/translation.json (1 hunks)
  • packages/extension/src/packageInfo.ts (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (22)
packages/extension-polkagate/src/fullscreen/notification/partials/SelectAccount.tsx (2)
packages/extension-polkagate/src/components/translate.ts (1)
  • useTranslation (8-10)
packages/extension-polkagate/src/popup/notification/constant.ts (1)
  • MAX_ACCOUNT_COUNT_NOTIFICATION (19-19)
packages/extension-polkagate/src/hooks/useNotifications.ts (10)
packages/extension-polkagate/src/popup/notification/types.ts (2)
  • NotificationsType (146-153)
  • NotificationActionType (155-161)
packages/extension-polkagate/src/popup/notification/util.ts (6)
  • markMessagesAsRead (220-227)
  • generateReferendaNotifications (86-141)
  • updateReferendas (235-290)
  • generateReceivedFundNotifications (184-213)
  • generateStakingRewardNotifications (148-177)
  • groupNotificationsByDay (304-364)
packages/extension-polkagate/src/popup/notification/hook/useNotificationSettings.ts (1)
  • useNotificationSettings (65-176)
packages/extension-polkagate/src/hooks/useSelectedChains.ts (1)
  • useSelectedChains (14-31)
packages/extension-polkagate/src/hooks/useGenesisHashOptions.ts (1)
  • useGenesisHashOptions (14-63)
packages/extension-polkagate/src/util/types.ts (1)
  • DropdownOption (877-880)
packages/extension-polkagate/src/util/constants.ts (1)
  • STORAGE_KEY (310-325)
packages/extension-polkagate/src/popup/notification/constant.ts (2)
  • AUTO_MARK_AS_READ_DELAY (29-29)
  • SUBSCAN_SUPPORTED_CHAINS (50-78)
packages/extension-polkagate/src/util/chain.ts (1)
  • sanitizeChainName (7-26)
packages/extension-polkagate/src/popup/notification/helpers.ts (3)
  • getReceivedFundsInformation (111-179)
  • getPayoutsInformation (187-266)
  • getReferendasInformation (273-336)
packages/extension-polkagate/src/fullscreen/components/layout/Notifications.tsx (3)
packages/extension-polkagate/src/hooks/useIsExtensionPopup.ts (1)
  • useIsExtensionPopup (4-21)
packages/extension-polkagate/src/util/handleExtensionPopup.ts (1)
  • useExtensionPopups (11-18)
packages/extension-polkagate/src/hooks/useNotifications.ts (1)
  • useNotifications (107-301)
packages/extension-polkagate/src/popup/notification/index.tsx (2)
packages/extension-polkagate/src/hooks/useNotifications.ts (1)
  • useNotifications (107-301)
packages/extension-polkagate/src/components/translate.ts (1)
  • useTranslation (8-10)
packages/extension-polkagate/src/fullscreen/notification/NotificationSettingsFS.tsx (5)
packages/extension-polkagate/src/popup/notification/hook/useNotificationSettings.ts (2)
  • NotificationSettingType (12-18)
  • useNotificationSettings (65-176)
packages/extension-polkagate/src/components/translate.ts (1)
  • useTranslation (8-10)
packages/extension-polkagate/src/fullscreen/notification/partials/SelectChain.tsx (1)
  • SelectChain (20-71)
packages/extension-polkagate/src/popup/notification/constant.ts (2)
  • SUPPORTED_GOVERNANCE_NOTIFICATION_CHAIN (47-47)
  • SUPPORTED_STAKING_NOTIFICATION_CHAIN (48-48)
packages/extension-polkagate/src/fullscreen/components/DraggableModal.tsx (1)
  • DraggableModal (30-172)
packages/extension-polkagate/src/fullscreen/notification/partials/SelectChain.tsx (3)
packages/extension-polkagate/src/popup/notification/NotificationSettings.tsx (1)
  • TextValuePair (21-24)
packages/extension-polkagate/src/components/translate.ts (1)
  • useTranslation (8-10)
packages/extension-polkagate/src/util/chain.ts (1)
  • sanitizeChainName (7-26)
packages/extension/src/packageInfo.ts (5)
packages/extension-base/src/packageInfo.ts (1)
  • packageInfo (6-6)
packages/extension-chains/src/packageInfo.ts (1)
  • packageInfo (6-6)
packages/extension-compat-metamask/src/packageInfo.ts (1)
  • packageInfo (6-6)
packages/extension-dapp/src/packageInfo.ts (1)
  • packageInfo (6-6)
packages/extension-inject/src/packageInfo.ts (1)
  • packageInfo (6-6)
packages/extension-polkagate/src/fullscreen/notification/index.tsx (3)
packages/extension-polkagate/src/components/translate.ts (1)
  • useTranslation (8-10)
packages/extension-polkagate/src/hooks/useNotifications.ts (1)
  • useNotifications (107-301)
packages/extension-polkagate/src/fullscreen/components/DraggableModal.tsx (1)
  • DraggableModal (30-172)
packages/extension-polkagate/src/popup/notification/hook/useNotificationSettings.ts (3)
packages/extension-polkagate/src/components/contexts.tsx (1)
  • AccountContext (34-34)
packages/extension-polkagate/src/util/constants.ts (1)
  • STORAGE_KEY (310-325)
packages/extension-polkagate/src/popup/notification/constant.ts (3)
  • DEFAULT_NOTIFICATION_SETTING (31-37)
  • MAX_ACCOUNT_COUNT_NOTIFICATION (19-19)
  • SET_UP_NOTIFICATION_SETTING (39-45)
packages/extension-polkagate/src/popup/notification/constant.ts (1)
packages/extension-polkagate/src/util/constants.ts (4)
  • POLKADOT_GENESIS_HASH (58-58)
  • KUSAMA_GENESIS_HASH (59-59)
  • WESTEND_GENESIS_HASH (60-60)
  • PASEO_GENESIS_HASH (61-61)
packages/extension-ui/src/Popup/routes/featuresRoutes.ts (1)
packages/extension-polkagate/src/popup/notification/NotificationSettings.tsx (1)
  • NotificationSettings (28-145)
packages/extension-polkagate/src/popup/notification/helpers.ts (9)
packages/extension-polkagate/src/popup/notification/types.ts (10)
  • TransferSubscan (14-38)
  • TransfersProp (78-87)
  • PayoutSubscan (40-50)
  • PayoutsProp (89-94)
  • ReferendaSubscan (52-62)
  • ReferendaProp (96-107)
  • ReceivedFundInformation (109-113)
  • ApiResponse (7-12)
  • StakingRewardInformation (115-119)
  • ReferendaInformation (121-124)
packages/extension-polkagate/src/util/types.ts (1)
  • DropdownOption (877-880)
packages/extension-polkagate/src/util/address.ts (1)
  • getSubstrateAddress (40-59)
packages/extension-polkagate/src/popup/notification/util.ts (1)
  • timestampToDate (16-51)
packages/extension-polkagate/src/popup/notification/constant.ts (5)
  • ReferendaStatus (6-6)
  • BATCH_SIZE (17-17)
  • MAX_RETRIES (16-16)
  • REFERENDA_COUNT_TO_TRACK_DOT (10-10)
  • REFERENDA_COUNT_TO_TRACK_KSM (11-11)
packages/extension-polkagate/src/util/getChainName.ts (1)
  • getChainName (15-29)
packages/extension-polkagate/src/util/chain.ts (1)
  • getSubscanChainName (32-54)
packages/extension-polkagate/src/util/api/postData.ts (1)
  • postData (6-25)
packages/extension-polkagate/src/util/constants.ts (2)
  • POLKADOT_GENESIS_HASH (58-58)
  • KUSAMA_GENESIS_HASH (59-59)
packages/extension-polkagate/src/popup/notification/partials/Partial.tsx (3)
packages/extension-polkagate/src/components/translate.ts (1)
  • useTranslation (8-10)
packages/extension-polkagate/src/components/ActionButton.tsx (1)
  • ActionButton (30-124)
packages/extension-polkagate/src/util/constants.ts (1)
  • EXTENSION_NAME (6-6)
packages/extension-polkagate/src/popup/notification/types.ts (2)
packages/extension-polkagate/src/popup/notification/constant.ts (1)
  • ReferendaStatus (6-6)
packages/extension-polkagate/src/util/types.ts (1)
  • DropdownOption (877-880)
packages/extension-polkagate/src/popup/notification/partials/SelectChain.tsx (4)
packages/extension-polkagate/src/util/handleExtensionPopup.ts (1)
  • ExtensionPopupCloser (9-9)
packages/extension-polkagate/src/popup/notification/NotificationSettings.tsx (1)
  • TextValuePair (21-24)
packages/extension-polkagate/src/fullscreen/notification/partials/SelectChain.tsx (1)
  • SelectChain (20-71)
packages/extension-polkagate/src/util/chain.ts (1)
  • sanitizeChainName (7-26)
packages/extension-polkagate/src/popup/notification/util.ts (5)
packages/extension-polkagate/src/popup/notification/types.ts (6)
  • ReferendaInformation (121-124)
  • NotificationMessageType (135-144)
  • StakingRewardInformation (115-119)
  • ReceivedFundInformation (109-113)
  • NotificationType (133-133)
  • ReferendaProp (96-107)
packages/extension-polkagate/src/components/translate.ts (1)
  • useTranslation (8-10)
packages/extension-polkagate/src/hooks/useChainInfo.ts (1)
  • ChainInfo (25-32)
packages/extension-polkagate/src/hooks/useTokenPriceBySymbol.ts (1)
  • Price (17-20)
packages/extension-polkagate/src/fullscreen/home/partials/type.ts (1)
  • CurrencyItemType (4-9)
packages/extension-polkagate/src/popup/notification/partials/NotificationGroup.tsx (8)
packages/extension-polkagate/src/popup/notification/util.ts (5)
  • isToday (373-382)
  • getNotificationItemTitle (473-502)
  • getTimeOfDay (390-400)
  • getNotificationDescription (504-559)
  • getNotificationIcon (561-585)
packages/extension-polkagate/src/components/translate.ts (1)
  • useTranslation (8-10)
packages/extension-polkagate/src/hooks/useAccount.ts (1)
  • useAccount (12-28)
packages/extension-polkagate/src/util/address.ts (1)
  • toShortAddress (61-69)
packages/extension-polkagate/src/popup/notification/types.ts (1)
  • NotificationMessageType (135-144)
packages/extension-polkagate/src/hooks/useCurrency.ts (1)
  • useCurrency (17-33)
packages/extension-polkagate/src/hooks/useChainInfo.ts (1)
  • useChainInfo (42-73)
packages/extension-polkagate/src/hooks/useTokenPriceBySymbol.ts (1)
  • useTokenPriceBySymbol (31-54)
packages/extension-polkagate/src/popup/notification/NotificationSettings.tsx (4)
packages/extension-polkagate/src/components/translate.ts (1)
  • useTranslation (8-10)
packages/extension-polkagate/src/popup/notification/hook/useNotificationSettings.ts (1)
  • useNotificationSettings (65-176)
packages/extension-polkagate/src/fullscreen/notification/partials/SelectChain.tsx (1)
  • SelectChain (20-71)
packages/extension-polkagate/src/popup/notification/constant.ts (2)
  • SUPPORTED_GOVERNANCE_NOTIFICATION_CHAIN (47-47)
  • SUPPORTED_STAKING_NOTIFICATION_CHAIN (48-48)
packages/extension-ui/src/Popup/contexts/AccountAssetProvider.tsx (1)
packages/extension-polkagate/src/hooks/useNotifications.ts (1)
  • useNotifications (107-301)
packages/extension-polkagate/src/popup/notification/partials/SelectAccount.tsx (3)
packages/extension-polkagate/src/util/handleExtensionPopup.ts (1)
  • ExtensionPopupCloser (9-9)
packages/extension-polkagate/src/components/translate.ts (1)
  • useTranslation (8-10)
packages/extension-polkagate/src/popup/notification/constant.ts (1)
  • MAX_ACCOUNT_COUNT_NOTIFICATION (19-19)
packages/extension-polkagate/src/popup/notification/partials/AccountToggle.tsx (1)
packages/extension-polkagate/src/util/constants.ts (1)
  • POLKADOT_GENESIS_HASH (58-58)
packages/extension-polkagate/src/hooks/useChainInfo.ts (1)
packages/extension-polkagate/src/util/types.ts (1)
  • ChainInfo (317-324)
🔇 Additional comments (5)
packages/extension-polkagate/src/hooks/useTokenPriceBySymbol.ts (1)

17-20: LGTM!

Exporting the Price interface is correct and enables the notification modules to import and reuse this type consistently across the codebase.

packages/extension-polkagate/src/partials/UserDashboardHeader.tsx (2)

45-48: LGTM! Clean horizontal layout implementation.

The Stack wrapper effectively arranges the Notifications and FullscreenModeButton controls side-by-side with appropriate alignment and spacing. The implementation follows Material-UI best practices.

Please verify that:

  1. The layout works correctly in both popup and fullscreen modes (considering the different available widths)
  2. Keyboard navigation flows naturally between the two controls
  3. The 4px gap provides sufficient visual separation between the notification icon and fullscreen button

10-10: No action needed: Notifications is correctly imported and requires no props, handling both popup and fullscreen contexts internally.

packages/extension-polkagate/src/components/TwoToneText.tsx (2)

16-16: Good fix—now consistently respects the style prop.

Previously, passing style without textPartInColor had no effect. This change ensures the prop is always honored.


19-31: Verify safety of text and textPartInColor inputs
Ensure every value passed into TwoToneText is sanitized or comes from a trusted source to prevent XSS via dangerouslySetInnerHTML.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (4)
packages/extension-polkagate/src/popup/notification/constant.ts (1)

6-13: Fix ReferendaStatus casing to align with Subscan data
The union still exposes 'timeout', but every consumer (and Subscan’s payload) uses 'timedOut'. Because of this mismatch we end up storing 'timedOut' while the type only allows 'timeout', so the value never lines up with the constant list or downstream comparisons. Please switch the literal to 'timedOut' to keep the type, constants, and fetched data consistent.

-export type ReferendaStatus = 'ongoing' | 'approved' | 'timeout' | 'rejected' | 'cancelled';
+export type ReferendaStatus = 'ongoing' | 'approved' | 'timedOut' | 'rejected' | 'cancelled';
packages/extension-polkagate/src/hooks/useNotifications.ts (1)

140-230: Persist reducer output instead of stale snapshots

Line 148 persists the pre-dispatch notifications object because saveNotifications() closes over the old state and you invoke it immediately after each dispatchNotifications on Lines 195, 212, and 229. React hasn’t flushed yet, so storage misses the freshly fetched messages/read flags, and the MARK_AS_READ reducer result is never saved either. Persist after the reducer settles (or pass the computed next state into the queue) and drop the direct calls so storage always reflects the reducer output.

-  const saveNotifications = useCallback(() => {
+  const enqueueSave = useCallback((next: NotificationsType) => {
     // Queue saves to ensure they happen sequentially, not in parallel
     saveQueue.current = saveQueue.current.then(async () => {
       if (isSavingRef.current) {
         return;
       }
 
       isSavingRef.current = true;
-      const dataToSave = { ...notifications, latestLoggedIn: Math.floor(Date.now() / 1000) };
+      const dataToSave = { ...next, latestLoggedIn: Math.floor(Date.now() / 1000) };
 
       try {
         await setStorage(STORAGE_KEY.NOTIFICATIONS, dataToSave);
         // console.log('✅ Notifications saved after fetch completion.');
       } catch (error) {
         console.error('❌ Failed to save notifications:', error);
       } finally {
         isSavingRef.current = false;
       }
     });
-  }, [notifications]);
+  }, []);
+
+  useEffect(() => {
+    if (!initializedRef.current) {
+      return;
+    }
+
+    enqueueSave(notifications);
+  }, [enqueueSave, notifications]);
-      dispatchNotifications({
-        payload: receivedFunds,
-        type: 'SET_RECEIVED_FUNDS'
-      });
-
-      saveNotifications();
+      dispatchNotifications({
+        payload: receivedFunds,
+        type: 'SET_RECEIVED_FUNDS'
+      });
-      dispatchNotifications({
-        payload: payouts,
-        type: 'SET_STAKING_REWARDS'
-      });
-
-      saveNotifications();
+      dispatchNotifications({
+        payload: payouts,
+        type: 'SET_STAKING_REWARDS'
+      });
-      dispatchNotifications({
-        payload: referendas,
-        type: 'SET_REFERENDA'
-      });
-
-      saveNotifications();
+      dispatchNotifications({
+        payload: referendas,
+        type: 'SET_REFERENDA'
+      });
packages/extension-polkagate/src/popup/notification/util.ts (2)

149-214: Emit a notification for every new payout/transfer

Line 155 relies on Array.find, so each account produces at most one staking reward ≥ latestLoggedIn - offset; the rest are silently ignored. The same pattern on Line 191 drops received-fund transfers. Users miss notifications whenever more than one event arrives between polls. Iterate all qualifying entries instead.

-  const newPayouts = payouts.map(({ address, data, network }) => {
-    const payout = data.find(({ timestamp }) => timestamp >= latestLoggedIn - NOTIFICATION_TIMESTAMP_OFFSET);
-
-    return payout
-      ? {
-        address,
-        network,
-        payout
-      }
-      : undefined;
-  }).filter((item) => !!item);
-
-  // Generate notifications for new payouts
-  newPayouts.forEach(({ address, network, payout }) => {
-    newMessages.push({
-      chain: network,
-      forAccount: address,
-      payout,
-      read: false,
-      type: 'stakingReward'
-    });
-  });
+  payouts.forEach(({ address, data, network }) => {
+    data
+      .filter(({ timestamp }) => timestamp >= latestLoggedIn - NOTIFICATION_TIMESTAMP_OFFSET)
+      .forEach((payout) => {
+        newMessages.push({
+          chain: network,
+          forAccount: address,
+          payout,
+          read: false,
+          type: 'stakingReward'
+        });
+      });
+  });
-  const newReceivedFunds = transfers.map(({ address, data, network }) => {
-    const receivedFund = data.find(({ timestamp }) => timestamp >= latestLoggedIn - NOTIFICATION_TIMESTAMP_OFFSET);
-
-    return receivedFund
-      ? {
-        address,
-        network,
-        receivedFund
-      }
-      : undefined;
-  }).filter((item) => !!item);
-
-  // Generate notifications for new payouts
-  newReceivedFunds.forEach(({ address, network, receivedFund }) => {
-    newMessages.push({
-      chain: network,
-      forAccount: address,
-      read: false,
-      receivedFund,
-      type: 'receivedFund'
-    });
-  });
+  transfers.forEach(({ address, data, network }) => {
+    data
+      .filter(({ timestamp }) => timestamp >= latestLoggedIn - NOTIFICATION_TIMESTAMP_OFFSET)
+      .forEach((receivedFund) => {
+        newMessages.push({
+          chain: network,
+          forAccount: address,
+          read: false,
+          receivedFund,
+          type: 'receivedFund'
+        });
+      });
+  });

14-503: Stop calling hooks from plain utilities

Line 475 calls useTranslation() inside getNotificationItemTitle, which is neither a component nor a custom hook. React throws “Invalid hook call” the first time this helper runs. Thread the translator from the caller and drop the hook here; remember to update call sites to pass their t.

-import { useTranslation } from '@polkadot/extension-polkagate/src/hooks';
...
-export function getNotificationItemTitle (type: NotificationType, referenda?: ReferendaProp) {
-  const { t } = useTranslation();
+export function getNotificationItemTitle (t: TFunction, type: NotificationType, referenda?: ReferendaProp) {
🧹 Nitpick comments (1)
packages/extension-polkagate/src/components/ActionCard.tsx (1)

50-50: Consider using 'block' instead of 'initial' for display.

Using 'initial' for the display property may be less predictable than explicitly setting 'block'. Since this is a div element, 'block' would be more explicit and clearer in intent.

Apply this diff if you prefer more explicit styling:

-    display: showColorBall ? 'initial' : 'none',
+    display: showColorBall ? 'block' : 'none',
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a97258e and d8595f3.

📒 Files selected for processing (11)
  • packages/extension-polkagate/src/components/ActionButton.tsx (4 hunks)
  • packages/extension-polkagate/src/components/ActionCard.tsx (3 hunks)
  • packages/extension-polkagate/src/fullscreen/notification/NotificationSettingsFS.tsx (1 hunks)
  • packages/extension-polkagate/src/fullscreen/notification/partials/SelectAccount.tsx (1 hunks)
  • packages/extension-polkagate/src/fullscreen/notification/partials/SelectChain.tsx (1 hunks)
  • packages/extension-polkagate/src/hooks/useNotifications.ts (1 hunks)
  • packages/extension-polkagate/src/popup/notification/NotificationSettings.tsx (1 hunks)
  • packages/extension-polkagate/src/popup/notification/constant.ts (1 hunks)
  • packages/extension-polkagate/src/popup/notification/hook/useNotificationSettings.ts (1 hunks)
  • packages/extension-polkagate/src/popup/notification/partials/Partial.tsx (1 hunks)
  • packages/extension-polkagate/src/popup/notification/util.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/extension-polkagate/src/popup/notification/NotificationSettings.tsx
🧰 Additional context used
🧬 Code graph analysis (8)
packages/extension-polkagate/src/hooks/useNotifications.ts (10)
packages/extension-polkagate/src/popup/notification/types.ts (2)
  • NotificationsType (146-153)
  • NotificationActionType (155-161)
packages/extension-polkagate/src/popup/notification/util.ts (6)
  • markMessagesAsRead (221-228)
  • generateReferendaNotifications (87-142)
  • updateReferendas (236-291)
  • generateReceivedFundNotifications (185-214)
  • generateStakingRewardNotifications (149-178)
  • groupNotificationsByDay (305-365)
packages/extension-polkagate/src/popup/notification/hook/useNotificationSettings.ts (1)
  • useNotificationSettings (65-197)
packages/extension-polkagate/src/hooks/useSelectedChains.ts (1)
  • useSelectedChains (14-31)
packages/extension-polkagate/src/hooks/useGenesisHashOptions.ts (1)
  • useGenesisHashOptions (14-63)
packages/extension-polkagate/src/util/types.ts (1)
  • DropdownOption (877-880)
packages/extension-polkagate/src/util/constants.ts (1)
  • STORAGE_KEY (310-325)
packages/extension-polkagate/src/popup/notification/constant.ts (2)
  • AUTO_MARK_AS_READ_DELAY (30-30)
  • SUBSCAN_SUPPORTED_CHAINS (51-79)
packages/extension-polkagate/src/util/chain.ts (1)
  • sanitizeChainName (7-26)
packages/extension-polkagate/src/popup/notification/helpers.ts (3)
  • getReceivedFundsInformation (111-179)
  • getPayoutsInformation (187-266)
  • getReferendasInformation (273-336)
packages/extension-polkagate/src/popup/notification/util.ts (5)
packages/extension-polkagate/src/popup/notification/types.ts (6)
  • ReferendaInformation (121-124)
  • NotificationMessageType (135-144)
  • StakingRewardInformation (115-119)
  • ReceivedFundInformation (109-113)
  • NotificationType (133-133)
  • ReferendaProp (96-107)
packages/extension-polkagate/src/popup/notification/constant.ts (1)
  • NOTIFICATION_TIMESTAMP_OFFSET (18-18)
packages/extension-polkagate/src/hooks/useChainInfo.ts (1)
  • ChainInfo (25-32)
packages/extension-polkagate/src/hooks/useTokenPriceBySymbol.ts (1)
  • Price (17-20)
packages/extension-polkagate/src/fullscreen/home/partials/type.ts (1)
  • CurrencyItemType (4-9)
packages/extension-polkagate/src/fullscreen/notification/partials/SelectAccount.tsx (3)
packages/extension-polkagate/src/components/translate.ts (1)
  • useTranslation (8-10)
packages/extension-polkagate/src/components/contexts.tsx (1)
  • AccountContext (34-34)
packages/extension-polkagate/src/popup/notification/constant.ts (1)
  • MAX_ACCOUNT_COUNT_NOTIFICATION (20-20)
packages/extension-polkagate/src/fullscreen/notification/NotificationSettingsFS.tsx (6)
packages/extension-polkagate/src/popup/notification/hook/useNotificationSettings.ts (2)
  • NotificationSettingType (12-18)
  • useNotificationSettings (65-197)
packages/extension-polkagate/src/components/translate.ts (1)
  • useTranslation (8-10)
packages/extension-polkagate/src/fullscreen/home/SelectAccount.tsx (1)
  • SelectAccount (104-146)
packages/extension-polkagate/src/fullscreen/notification/partials/SelectChain.tsx (1)
  • SelectChain (20-71)
packages/extension-polkagate/src/popup/notification/constant.ts (2)
  • SUPPORTED_GOVERNANCE_NOTIFICATION_CHAIN (48-48)
  • SUPPORTED_STAKING_NOTIFICATION_CHAIN (49-49)
packages/extension-polkagate/src/fullscreen/components/DraggableModal.tsx (1)
  • DraggableModal (30-172)
packages/extension-polkagate/src/popup/notification/hook/useNotificationSettings.ts (2)
packages/extension-polkagate/src/util/constants.ts (1)
  • STORAGE_KEY (310-325)
packages/extension-polkagate/src/popup/notification/constant.ts (3)
  • DEFAULT_NOTIFICATION_SETTING (32-38)
  • MAX_ACCOUNT_COUNT_NOTIFICATION (20-20)
  • SET_UP_NOTIFICATION_SETTING (40-46)
packages/extension-polkagate/src/popup/notification/constant.ts (1)
packages/extension-polkagate/src/util/constants.ts (4)
  • POLKADOT_GENESIS_HASH (58-58)
  • KUSAMA_GENESIS_HASH (59-59)
  • WESTEND_GENESIS_HASH (60-60)
  • PASEO_GENESIS_HASH (61-61)
packages/extension-polkagate/src/fullscreen/notification/partials/SelectChain.tsx (3)
packages/extension-polkagate/src/popup/notification/NotificationSettings.tsx (1)
  • TextValuePair (21-24)
packages/extension-polkagate/src/components/translate.ts (1)
  • useTranslation (8-10)
packages/extension-polkagate/src/util/chain.ts (1)
  • sanitizeChainName (7-26)
packages/extension-polkagate/src/popup/notification/partials/Partial.tsx (3)
packages/extension-polkagate/src/components/translate.ts (1)
  • useTranslation (8-10)
packages/extension-polkagate/src/components/ActionButton.tsx (1)
  • ActionButton (65-174)
packages/extension-polkagate/src/util/constants.ts (1)
  • EXTENSION_NAME (6-6)
🔇 Additional comments (3)
packages/extension-polkagate/src/components/ActionCard.tsx (3)

22-24: LGTM! Well-designed prop additions.

The new optional props enhance component flexibility while maintaining backward compatibility through proper typing and default values.


27-27: LGTM! Function signature properly updated.

The signature correctly includes all new props with sensible defaults (showChevron = true, showColorBall = true), preserving existing behavior for components that don't pass these props.


94-94: LGTM! Layout changes support flexible card content.

The Grid xs prop enables horizontal expansion, conditional chevron rendering provides UI flexibility, and children placement after the main content allows for extended card content—all aligned with the notification UI requirements.

Also applies to: 99-99, 105-105

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (7)
packages/extension-polkagate/src/fullscreen/components/layout/Notifications.tsx (1)

63-69: Unread badge predicate is correct now

The unread check is fixed to use !read. LGTM.

packages/extension-polkagate/src/hooks/useNotifications.ts (1)

140-172: Persistence after reducer updates: LGTM

Moving saves into a useEffect with a queue avoids stale state writes. This resolves the earlier persistence bug.

packages/extension-polkagate/src/popup/notification/helpers.ts (2)

94-97: Normalize referenda status strings (e.g., “TimedOut” → “timeout”)

Lowercasing alone yields “timedout”, which doesn’t match “timeout”. Normalize before casting.

-      status: referenda.status.toLowerCase() as ReferendaStatus,
+      status: normalizeReferendaStatus(referenda.status),

Add this helper near the top of the file:

const normalizeReferendaStatus = (status: string): ReferendaStatus => {
  const s = status.replace(/[_\s-]/g, '').toLowerCase();
  if (s === 'timedout') return 'timeout';
  // Fallback to allowed set; unknown → 'rejected'
  return (['ongoing','approved','timeout','rejected','cancelled'].includes(s) ? s : 'rejected') as ReferendaStatus;
};

179-182: Fix batching cooldown: compare against networks, not addresses

Sleep condition should check remaining network batches; using addresses.length throttles incorrectly.

-      if (i + BATCH_SIZE < addresses.length) {
+      if (i + BATCH_SIZE < networks.length) {
         await new Promise((resolve) => setTimeout(resolve, 1000));
       }

Apply at both locations shown.

Also applies to: 267-269

packages/extension-polkagate/src/popup/notification/util.ts (3)

150-180: Emit a notification for every qualifying staking payout

Using find limits to one payout per account; iterate all >= latestLoggedIn.

-  const newPayouts = payouts.map(({ address, data, network }) => {
-    const payout = data.find(({ timestamp }) => timestamp >= (latestLoggedIn - NOTIFICATION_TIMESTAMP_OFFSET));
-    return payout ? { address, network, payout } : undefined;
-  }).filter((item) => !!item);
-
-  newPayouts.forEach(({ address, network, payout }) => {
-    newMessages.push({
-      chain: network,
-      forAccount: address,
-      payout,
-      read: false,
-      type: 'stakingReward'
-    });
-  });
+  payouts.forEach(({ address, data, network }) => {
+    data
+      .filter(({ timestamp }) => timestamp >= (latestLoggedIn - NOTIFICATION_TIMESTAMP_OFFSET))
+      .forEach((payout) => {
+        newMessages.push({
+          chain: network,
+          forAccount: address,
+          payout,
+          read: false,
+          type: 'stakingReward'
+        });
+      });
+  });

187-216: Emit a notification for every qualifying received fund

Same issue: find emits only one; iterate all transfers since last login.

-  const newReceivedFunds = transfers.map(({ address, data, network }) => {
-    const receivedFund = data.find(({ timestamp }) => timestamp >= (latestLoggedIn - NOTIFICATION_TIMESTAMP_OFFSET));
-    return receivedFund ? { address, network, receivedFund } : undefined;
-  }).filter((item) => !!item);
-
-  newReceivedFunds.forEach(({ address, network, receivedFund }) => {
-    newMessages.push({
-      chain: network,
-      forAccount: address,
-      read: false,
-      receivedFund,
-      type: 'receivedFund'
-    });
-  });
+  transfers.forEach(({ address, data, network }) => {
+    data
+      .filter(({ timestamp }) => timestamp >= (latestLoggedIn - NOTIFICATION_TIMESTAMP_OFFSET))
+      .forEach((receivedFund) => {
+        newMessages.push({
+          chain: network,
+          forAccount: address,
+          read: false,
+          receivedFund,
+          type: 'receivedFund'
+        });
+      });
+  });

498-527: Don’t call hooks in utilities; pass t from the caller

useTranslation inside a plain function violates rules-of-hooks; this will fail lint/build. Pass t as a parameter.

-export function getNotificationItemTitle (type: NotificationType, referenda?: ReferendaProp) {
-  const { t } = useTranslation();
+export function getNotificationItemTitle (t: TFunction, type: NotificationType, referenda?: ReferendaProp) {
   switch (type) {

Update call sites to pass t obtained in a component/hook.

🧹 Nitpick comments (3)
packages/extension-polkagate/src/hooks/useNotifications.ts (1)

241-261: Consider loading from storage even when notifications are off

Blocking LOAD_FROM_STORAGE when notificationIsOff prevents showing old items/status. Suggest drop that guard for load-only.

Apply this diff:

-  useEffect(() => {
-    if (notificationIsOff || initializedRef.current) {
+  useEffect(() => {
+    if (initializedRef.current) {
       return;
     }
packages/extension-polkagate/src/popup/notification/util.ts (2)

533-545: Scale received fund amount with chain decimals

Amounts from Subscan are integer strings; use chainInfo.decimal to scale for display, like staking payouts.

-      const assetAmount = formatNumber(item.receivedFund?.amount);
+      const assetAmount = formatNumber(item.receivedFund?.amount, 2, decimal);

320-337: Deduplicate independent of read flag to avoid duplicates post mark-as-read

Including read in uniqueKey can show duplicates of the same event before/after mark-as-read.

-        uniqueKey = `${item.read}-${JSON.stringify(item.payout ?? '')}`;
+        uniqueKey = JSON.stringify(item.payout ?? '');
@@
-        uniqueKey = `${item.read}-${JSON.stringify(item.receivedFund ?? '')}`;
+        uniqueKey = JSON.stringify(item.receivedFund ?? '');
@@
-        uniqueKey = `${item.read}-${JSON.stringify(item.referenda ?? '')}`;
+        uniqueKey = JSON.stringify(item.referenda ?? '');
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d8595f3 and 33f5369.

📒 Files selected for processing (4)
  • packages/extension-polkagate/src/fullscreen/components/layout/Notifications.tsx (1 hunks)
  • packages/extension-polkagate/src/hooks/useNotifications.ts (1 hunks)
  • packages/extension-polkagate/src/popup/notification/helpers.ts (1 hunks)
  • packages/extension-polkagate/src/popup/notification/util.ts (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (4)
packages/extension-polkagate/src/fullscreen/components/layout/Notifications.tsx (3)
packages/extension-polkagate/src/hooks/useIsExtensionPopup.ts (1)
  • useIsExtensionPopup (4-21)
packages/extension-polkagate/src/util/handleExtensionPopup.ts (1)
  • useExtensionPopups (11-18)
packages/extension-polkagate/src/hooks/useNotifications.ts (1)
  • useNotifications (107-308)
packages/extension-polkagate/src/popup/notification/helpers.ts (10)
packages/extension-polkagate/src/popup/notification/types.ts (10)
  • TransferSubscan (14-38)
  • TransfersProp (78-87)
  • PayoutSubscan (40-50)
  • PayoutsProp (89-94)
  • ReferendaSubscan (52-62)
  • ReferendaProp (96-107)
  • ReceivedFundInformation (109-113)
  • ApiResponse (7-12)
  • StakingRewardInformation (115-119)
  • ReferendaInformation (121-124)
packages/extension-polkagate/src/util/types.ts (1)
  • DropdownOption (877-880)
packages/extension-polkagate/src/util/address.ts (1)
  • getSubstrateAddress (40-59)
packages/extension-polkagate/src/popup/notification/util.ts (1)
  • timestampToDate (18-53)
packages/extension-polkagate/src/popup/notification/constant.ts (5)
  • ReferendaStatus (6-6)
  • BATCH_SIZE (17-17)
  • MAX_RETRIES (16-16)
  • REFERENDA_COUNT_TO_TRACK_DOT (10-10)
  • REFERENDA_COUNT_TO_TRACK_KSM (11-11)
packages/extension-polkagate/src/util/migrateHubUtils.ts (1)
  • isMigratedRelay (103-105)
packages/extension-polkagate/src/util/getChainName.ts (1)
  • getChainName (15-29)
packages/extension-polkagate/src/util/chain.ts (1)
  • getSubscanChainName (32-54)
packages/extension-polkagate/src/util/api/postData.ts (1)
  • postData (6-25)
packages/extension-polkagate/src/util/constants.ts (2)
  • POLKADOT_GENESIS_HASH (58-58)
  • KUSAMA_GENESIS_HASH (59-59)
packages/extension-polkagate/src/hooks/useNotifications.ts (10)
packages/extension-polkagate/src/popup/notification/types.ts (2)
  • NotificationsType (146-153)
  • NotificationActionType (155-161)
packages/extension-polkagate/src/popup/notification/util.ts (6)
  • markMessagesAsRead (223-230)
  • generateReferendaNotifications (88-143)
  • updateReferendas (238-293)
  • generateReceivedFundNotifications (187-216)
  • generateStakingRewardNotifications (150-180)
  • groupNotificationsByDay (307-389)
packages/extension-polkagate/src/popup/notification/hook/useNotificationSettings.ts (1)
  • useNotificationSettings (65-197)
packages/extension-polkagate/src/hooks/useSelectedChains.ts (1)
  • useSelectedChains (14-31)
packages/extension-polkagate/src/hooks/useGenesisHashOptions.ts (1)
  • useGenesisHashOptions (14-63)
packages/extension-polkagate/src/util/types.ts (1)
  • DropdownOption (877-880)
packages/extension-polkagate/src/util/constants.ts (1)
  • STORAGE_KEY (310-325)
packages/extension-polkagate/src/popup/notification/constant.ts (2)
  • AUTO_MARK_AS_READ_DELAY (30-30)
  • SUBSCAN_SUPPORTED_CHAINS (51-79)
packages/extension-polkagate/src/util/chain.ts (1)
  • sanitizeChainName (7-26)
packages/extension-polkagate/src/popup/notification/helpers.ts (3)
  • getReceivedFundsInformation (112-187)
  • getPayoutsInformation (195-274)
  • getReferendasInformation (281-344)
packages/extension-polkagate/src/popup/notification/util.ts (6)
packages/extension-polkagate/src/popup/notification/types.ts (6)
  • ReferendaInformation (121-124)
  • NotificationMessageType (135-144)
  • StakingRewardInformation (115-119)
  • ReceivedFundInformation (109-113)
  • NotificationType (133-133)
  • ReferendaProp (96-107)
packages/extension-polkagate/src/popup/notification/constant.ts (1)
  • NOTIFICATION_TIMESTAMP_OFFSET (18-18)
packages/extension-polkagate/src/components/translate.ts (1)
  • useTranslation (8-10)
packages/extension-polkagate/src/hooks/useChainInfo.ts (1)
  • ChainInfo (25-32)
packages/extension-polkagate/src/hooks/useTokenPriceBySymbol.ts (1)
  • Price (17-20)
packages/extension-polkagate/src/fullscreen/home/partials/type.ts (1)
  • CurrencyItemType (4-9)
🔇 Additional comments (1)
packages/extension-polkagate/src/fullscreen/components/layout/Notifications.tsx (1)

58-79: react-router-dom v6+ confirmed react-router-dom ^7.4.1 is used in extension-polkagate and extension-ui, so useNavigate is supported.

@Nick-1979
Copy link
Member

Nick-1979 commented Oct 19, 2025

@AMIRKHANEF

please merghe main into the branch and
the issues:
1- menu position issue
2- duplicate entry (temporary)
3- seems wrong new notification alert(small red button)

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (4)
packages/extension-polkagate/src/popup/notification/util.ts (2)

148-178: Emit a notification for every new staking payout (not just the first).

Using Array.find captures only a single payout per account; additional new rewards are dropped. Iterate all qualifying payouts.

 export const generateStakingRewardNotifications = (
   latestLoggedIn: number,
   payouts: StakingRewardInformation[]
 ): NotificationMessageType[] => {
   const newMessages: NotificationMessageType[] = [];
-
-  const newPayouts = payouts.map(({ address, data, network }) => {
-    const payout = data.find(({ timestamp }) => timestamp >= (latestLoggedIn - NOTIFICATION_TIMESTAMP_OFFSET));
-
-    return payout
-      ? {
-        address,
-        network,
-        payout
-      }
-      : undefined;
-  }).filter((item) => !!item);
-
-  // Generate notifications for new payouts
-  newPayouts.forEach(({ address, network, payout }) => {
-    newMessages.push({
-      chain: network,
-      forAccount: address,
-      payout,
-      read: false,
-      type: 'stakingReward'
-    });
-  });
+  payouts.forEach(({ address, data, network }) => {
+    data
+      .filter(({ timestamp }) => timestamp >= (latestLoggedIn - NOTIFICATION_TIMESTAMP_OFFSET))
+      .forEach((payout) => {
+        newMessages.push({
+          chain: network,
+          forAccount: address,
+          payout,
+          read: false,
+          type: 'stakingReward'
+        });
+      });
+  });
 
   return newMessages;
 };

185-214: Emit a notification for every received fund event.

Same issue here: Array.find limits you to one transfer per account; others are missed. Collect all qualifying transfers.

 export const generateReceivedFundNotifications = (
   latestLoggedIn: number,
   transfers: ReceivedFundInformation[]
 ): NotificationMessageType[] => {
   const newMessages: NotificationMessageType[] = [];
-  const newReceivedFunds = transfers.map(({ address, data, network }) => {
-    const receivedFund = data.find(({ timestamp }) => timestamp >= (latestLoggedIn - NOTIFICATION_TIMESTAMP_OFFSET));
-
-    return receivedFund
-      ? {
-        address,
-        network,
-        receivedFund
-      }
-      : undefined;
-  }).filter((item) => !!item);
-
-  // Generate notifications for new payouts
-  newReceivedFunds.forEach(({ address, network, receivedFund }) => {
-    newMessages.push({
-      chain: network,
-      forAccount: address,
-      read: false,
-      receivedFund,
-      type: 'receivedFund'
-    });
-  });
+  transfers.forEach(({ address, data, network }) => {
+    data
+      .filter(({ timestamp }) => timestamp >= (latestLoggedIn - NOTIFICATION_TIMESTAMP_OFFSET))
+      .forEach((receivedFund) => {
+        newMessages.push({
+          chain: network,
+          forAccount: address,
+          read: false,
+          receivedFund,
+          type: 'receivedFund'
+        });
+      });
+  });
 
   return newMessages;
 };
packages/extension-polkagate/src/popup/notification/index.tsx (1)

21-21: Allow live fetch: pass false to useNotifications.

Without an argument, justLoadData stays true and the hook won’t fetch from network on first load. Pass false.

-  const { markAsRead, notificationItems, status } = useNotifications();
+  const { markAsRead, notificationItems, status } = useNotifications(false);
packages/extension-polkagate/src/popup/notification/partials/NotificationGroup.tsx (1)

68-70: Fix milliseconds vs seconds fallback in getTimeOfDay.

getTimeOfDay expects seconds; Date.now() is milliseconds. Convert the fallback.

-  const time = getTimeOfDay(item.payout?.timestamp ?? item.receivedFund?.timestamp ?? item.referenda?.latestTimestamp ?? Date.now());
+  const fallbackTimestamp = Math.floor(Date.now() / 1000);
+  const time = getTimeOfDay(item.payout?.timestamp ?? item.receivedFund?.timestamp ?? item.referenda?.latestTimestamp ?? fallbackTimestamp);
🧹 Nitpick comments (10)
packages/extension-polkagate/src/popup/notification/util.ts (6)

374-381: Avoid parsing formatted dates for sorting.

Sorting by new Date("15 Dec 2025") depends on locale parsing and can be brittle. Keep a numeric “day start” (e.g., UTC midnight seconds) alongside the label and sort by that.

Example approach:

  • Compute dayStart = new Date(Date.UTC(y, m, d)).getTime()
  • Store grouped as Map<number, {label: string, items: ...}>
  • Sort by numeric key, then render label.

439-494: Make decimal scaling robust for numeric inputs.

When decimal > 0 and value is a number, the BigInt branch is skipped, risking precision loss for large chain amounts. Coerce to an integer string first, then use BigInt.

-  const strValue = value.toString().replace(/,/g, '').trim();
+  const strValue = value.toString().replace(/,/g, '').trim();
@@
-  // If blockchain-style decimal division is required
-  if (decimal > 0 && /^[0-9]+$/.test(strValue)) {
+  // If blockchain-style decimal division is required
+  if (decimal > 0) {
+    // drop any fractional part before BigInt conversion
+    const intLike = strValue.split('.')[0];
+    if (!/^[0-9]+$/.test(intLike)) {
+      return 0;
+    }
     // Use BigInt division for safety
-    const bigintVal = BigInt(strValue);
+    const bigintVal = BigInt(intLike);

507-513: Fix wording: “Referendum timed out”.

“time outed” reads incorrectly.

-      } else if (referenda?.status === 'timeout') {
-        return t('Referendum time outed');
+      } else if (referenda?.status === 'timeout') {
+        return t('Referendum timed out');

Remember to align the translation key. See translation.json comment.


525-536: Guard missing currency sign.

When currency is undefined, ${currencySign}${amount} renders “undefined123”. Default to empty string.

-  const currencySign = currency?.sign;
+  const currencySign = currency?.sign ?? '';

590-601: Add icon styles for ‘submitted’ and ‘decision’ referendum statuses.

These fall back to the neutral “rejected” style today. Provide explicit mappings for visual consistency.

       const statusMap = {
         approved: { ItemIcon: Receipt2, bgcolor: '#FF4FB91A', borderColor: '#FF4FB940', color: '#FF4FB9' },
         cancelled: neutralStyle,
+        decision: { ItemIcon: Receipt2, bgcolor: '#82FFA540', borderColor: '#82FFA51A', color: '#82FFA5' },
         ongoing: { ItemIcon: Receipt2, bgcolor: '#82FFA540', borderColor: '#82FFA51A', color: '#82FFA5' },
         rejected: neutralStyle,
+        submitted: { ItemIcon: Receipt2, bgcolor: '#82FFA540', borderColor: '#82FFA51A', color: '#82FFA5' },
         timeout: neutralStyle
       };

236-241: Fix naming typos: "updateReferendas" and "preciousRefs".

Rename to updateReferenda and previousRefs for consistency with the ReferendaInformation type and to fix the apparent spelling error. One call site requires updating at packages/extension-polkagate/src/hooks/useNotifications.ts:55.

-export const updateReferendas = (preciousRefs: ReferendaInformation[] | null | undefined, newRefs: ReferendaInformation[]) => {
-  if (!preciousRefs) {
+export const updateReferenda = (previousRefs: ReferendaInformation[] | null | undefined, newRefs: ReferendaInformation[]) => {
+  if (!previousRefs) {
     return newRefs;
   }
 
   const resultMap = new Map<string | number, ReferendaInformation>();
 
   // Copy all previous data
-  for (const prev of preciousRefs) {
+  for (const prev of previousRefs) {

Update the call site in packages/extension-polkagate/src/hooks/useNotifications.ts:55:

-        referendas: updateReferendas(state.referendas, action.payload)
+        referendas: updateReferenda(state.referendas, action.payload)
packages/extension/public/locales/en/translation.json (3)

819-819: Wording: “Enable Received Funds”.

“Enable Receive Fund” is ungrammatical. Suggest “Enable Received Funds” (or “Enable Incoming Funds”).

-  "Enable Receive Fund": "",
+  "Enable Received Funds": "",

824-824: Clarify incomplete sentence.

“Select up to 3 accounts to be notified when account activity” → add missing verb.

-  "Select up to 3 accounts to be notified when account activity": "",
+  "Select up to 3 accounts to be notified of account activity": "",

835-835: Fix wording: “Referendum timed out”.

Align with util.ts change.

-  "Referendum time outed": "",
+  "Referendum timed out": "",
packages/extension-polkagate/src/popup/notification/partials/NotificationGroup.tsx (1)

68-73: Graceful chain defaults in descriptions.

When chainInfo is unresolved (e.g., missing genesisHash), description interpolations can render “undefined”. Consider falling back to item.chain?.text.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 68e8f81 and a800e53.

📒 Files selected for processing (6)
  • packages/extension-polkagate/src/popup/notification/index.tsx (1 hunks)
  • packages/extension-polkagate/src/popup/notification/partials/NotificationGroup.tsx (1 hunks)
  • packages/extension-polkagate/src/popup/notification/util.ts (1 hunks)
  • packages/extension/package.json (1 hunks)
  • packages/extension/public/locales/en/translation.json (1 hunks)
  • packages/extension/src/packageInfo.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • packages/extension/src/packageInfo.ts
  • packages/extension/package.json
🧰 Additional context used
🧬 Code graph analysis (3)
packages/extension-polkagate/src/popup/notification/index.tsx (2)
packages/extension-polkagate/src/hooks/useNotifications.ts (1)
  • useNotifications (107-308)
packages/extension-polkagate/src/components/translate.ts (1)
  • useTranslation (8-10)
packages/extension-polkagate/src/popup/notification/util.ts (5)
packages/extension-polkagate/src/popup/notification/types.ts (6)
  • ReferendaInformation (121-124)
  • NotificationMessageType (135-144)
  • StakingRewardInformation (115-119)
  • ReceivedFundInformation (109-113)
  • NotificationType (133-133)
  • ReferendaProp (96-107)
packages/extension-polkagate/src/popup/notification/constant.ts (1)
  • NOTIFICATION_TIMESTAMP_OFFSET (18-18)
packages/extension-polkagate/src/hooks/useChainInfo.ts (1)
  • ChainInfo (25-32)
packages/extension-polkagate/src/hooks/useTokenPriceBySymbol.ts (1)
  • Price (17-20)
packages/extension-polkagate/src/fullscreen/home/partials/type.ts (1)
  • CurrencyItemType (4-9)
packages/extension-polkagate/src/popup/notification/partials/NotificationGroup.tsx (7)
packages/extension-polkagate/src/popup/notification/util.ts (5)
  • isToday (396-405)
  • getNotificationItemTitle (496-523)
  • getTimeOfDay (413-423)
  • getNotificationDescription (525-580)
  • getNotificationIcon (582-606)
packages/extension-polkagate/src/components/translate.ts (1)
  • useTranslation (8-10)
packages/extension-polkagate/src/hooks/useAccount.ts (1)
  • useAccount (12-28)
packages/extension-polkagate/src/util/address.ts (1)
  • toShortAddress (61-69)
packages/extension-polkagate/src/popup/notification/types.ts (1)
  • NotificationMessageType (135-144)
packages/extension-polkagate/src/hooks/useChainInfo.ts (1)
  • useChainInfo (42-73)
packages/extension-polkagate/src/hooks/useTokenPriceBySymbol.ts (1)
  • useTokenPriceBySymbol (31-54)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: build
  • GitHub Check: Analyze (javascript)
🔇 Additional comments (1)
packages/extension/public/locales/en/translation.json (1)

1-848: i18n init already prevents empty-string UI blanks — no blocking change required

Verified packages/extension-polkagate/src/i18n/i18n.ts sets returnEmptyString: false and fallbackLng: 'en', so empty values in packages/extension/public/locales/en/translation.json will not render blank UI; populate the en file if you want readable English copy.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (4)
packages/extension-polkagate/src/fullscreen/notification/NotificationSettingsFS.tsx (4)

10-11: Consider importing from shared/centralized paths.

Importing from popup/notification/... paths in a fullscreen component creates architectural coupling. Based on the PR context, these hooks and constants should be imported from shared locations (e.g., @polkadot/extension-polkagate/src/hooks for the hook).

Apply this diff:

-import { useTranslation } from '@polkadot/extension-polkagate/src/hooks';
-import { SUPPORTED_GOVERNANCE_NOTIFICATION_CHAIN, SUPPORTED_STAKING_NOTIFICATION_CHAIN } from '@polkadot/extension-polkagate/src/popup/notification/constant';
-import useNotificationSettings, { type NotificationSettingType, Popups } from '@polkadot/extension-polkagate/src/popup/notification/hook/useNotificationSettings';
+import { useNotificationSettings, useTranslation } from '@polkadot/extension-polkagate/src/hooks';
+import { SUPPORTED_GOVERNANCE_NOTIFICATION_CHAIN, SUPPORTED_STAKING_NOTIFICATION_CHAIN } from '@polkadot/extension-polkagate/src/popup/notification/constant';
+import { type NotificationSettingType, Popups } from '@polkadot/extension-polkagate/src/popup/notification/hook/useNotificationSettings';

76-93: Consider adding count badges for Governance and Staking Rewards.

The Accounts card displays a count badge (lines 72-74), but Governance and Staking Rewards cards don't show how many chains are selected. This creates an inconsistent UX—users would benefit from seeing the selection count at a glance.

Apply this diff for Governance:

       <ActionCard
         Icon={Record}
         iconColor='#FF4FB9'
         iconSize={24}
         iconWithoutTransform
         onClick={openPopup(Popups.GOVERNANCE)}
         style={{ ...CARD_STYLE }}
         title={t('Governance')}
-      />
+      >
+        <Typography color='#AA83DC' sx={{ bgcolor: '#BFA1FF26', borderRadius: '10px', mr: '2px', p: '3px 10px' }} variant='B-3'>
+          {notificationSetting.governance?.length}
+        </Typography>
+      </ActionCard>

And for Staking Rewards:

       <ActionCard
         Icon={BuyCrypto}
         iconColor='#FF4FB9'
         iconSize={24}
         iconWithoutTransform
         onClick={openPopup(Popups.STAKING_REWARDS)}
         style={{ ...CARD_STYLE }}
         title={t('Staking Rewards')}
-      />
+      >
+        <Typography color='#AA83DC' sx={{ bgcolor: '#BFA1FF26', borderRadius: '10px', mr: '2px', p: '3px 10px' }} variant='B-3'>
+          {notificationSetting.stakingRewards?.length}
+        </Typography>
+      </ActionCard>

115-149: Add a default case for type safety.

The switch statement handling popups lacks a default case. While all current Popups enum values are covered, adding a default case improves type safety and maintainability if new popup types are added later.

Apply this diff:

       case Popups.STAKING_REWARDS:
         return (
           <SelectChain
             onChains={setStakingRewardsChains}
             options={SUPPORTED_STAKING_NOTIFICATION_CHAIN}
             previousState={notificationSetting.stakingRewards}
           />);
+
+      default:
+        return null;
     }
   }, [notificationSetting, openPopup, popups, setAccounts, setGovernanceChains, setStakingRewardsChains, toggleNotification, toggleReceivedFunds]);

184-184: Remove extra space in padding value.

The padding string has an unnecessary leading space: ' 20px 10px 10px'. While this may still work, it's cleaner to remove it.

Apply this diff:

-      style={{ backgroundColor: '#1B133C', minHeight: '600px', overflow: 'clip', padding: ' 20px 10px 10px' }}
+      style={{ backgroundColor: '#1B133C', minHeight: '600px', overflow: 'clip', padding: '20px 10px 10px' }}
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a800e53 and 998015c.

📒 Files selected for processing (2)
  • packages/extension-polkagate/src/fullscreen/notification/NotificationSettingsFS.tsx (1 hunks)
  • packages/extension-polkagate/src/popup/notification/NotificationSettings.tsx (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/extension-polkagate/src/popup/notification/NotificationSettings.tsx
🧰 Additional context used
🧬 Code graph analysis (1)
packages/extension-polkagate/src/fullscreen/notification/NotificationSettingsFS.tsx (4)
packages/extension-polkagate/src/popup/notification/hook/useNotificationSettings.ts (2)
  • NotificationSettingType (12-18)
  • useNotificationSettings (65-197)
packages/extension-polkagate/src/fullscreen/notification/partials/SelectChain.tsx (1)
  • SelectChain (20-71)
packages/extension-polkagate/src/popup/notification/constant.ts (2)
  • SUPPORTED_GOVERNANCE_NOTIFICATION_CHAIN (48-48)
  • SUPPORTED_STAKING_NOTIFICATION_CHAIN (49-49)
packages/extension-polkagate/src/fullscreen/components/DraggableModal.tsx (1)
  • DraggableModal (30-172)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Analyze (javascript)
  • GitHub Check: build

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
packages/extension-polkagate/src/fullscreen/notification/NotificationSettingsFS.tsx (2)

76-93: Consider showing selection counts for consistency.

The Accounts card (lines 72-74) displays a count badge, but the Governance and Staking Rewards cards don't show how many chains are selected. Adding similar count badges would improve consistency and user feedback.

Example for Governance card:

       <ActionCard
         Icon={Record}
         iconColor='#FF4FB9'
         iconSize={24}
         iconWithoutTransform
         onClick={openPopup(Popups.GOVERNANCE)}
         style={{ ...CARD_STYLE }}
         title={t('Governance')}
-      />
+      >
+        <Typography color='#AA83DC' sx={{ bgcolor: '#BFA1FF26', borderRadius: '10px', mr: '2px', p: '3px 10px' }} variant='B-3'>
+          {notificationSetting.governance?.length ?? 0}
+        </Typography>
+      </ActionCard>

Apply similar changes to the Staking Rewards card.


115-149: Consider adding a default case for defensive coding.

The switch statement covers all current Popups enum values but lacks a default case. If the enum is extended or an unexpected value occurs, ui will be undefined, potentially causing render issues.

Apply this diff:

       case Popups.STAKING_REWARDS:
         return (
           <SelectChain
             onChains={setStakingRewardsChains}
             options={SUPPORTED_STAKING_NOTIFICATION_CHAIN}
             previousState={notificationSetting.stakingRewards}
           />);
+
+      default:
+        return (
+          <SettingUI
+            notificationSetting={notificationSetting}
+            openPopup={openPopup}
+            toggleNotification={toggleNotification}
+            toggleReceivedFunds={toggleReceivedFunds}
+          />);
     }
   }, [notificationSetting, openPopup, popups, setAccounts, setGovernanceChains, setStakingRewardsChains, toggleNotification, toggleReceivedFunds]);
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 998015c and ffd09ef.

📒 Files selected for processing (3)
  • packages/extension-polkagate/src/fullscreen/notification/NotificationSettingsFS.tsx (1 hunks)
  • packages/extension-polkagate/src/popup/notification/NotificationSettings.tsx (1 hunks)
  • packages/extension-polkagate/src/popup/notification/util.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • packages/extension-polkagate/src/popup/notification/NotificationSettings.tsx
  • packages/extension-polkagate/src/popup/notification/util.ts
🧰 Additional context used
🧬 Code graph analysis (1)
packages/extension-polkagate/src/fullscreen/notification/NotificationSettingsFS.tsx (5)
packages/extension-polkagate/src/popup/notification/hook/useNotificationSettings.ts (2)
  • NotificationSettingType (12-18)
  • useNotificationSettings (65-197)
packages/extension-polkagate/src/components/translate.ts (1)
  • useTranslation (8-10)
packages/extension-polkagate/src/fullscreen/notification/partials/SelectChain.tsx (1)
  • SelectChain (20-71)
packages/extension-polkagate/src/popup/notification/constant.ts (2)
  • SUPPORTED_GOVERNANCE_NOTIFICATION_CHAIN (48-48)
  • SUPPORTED_STAKING_NOTIFICATION_CHAIN (49-49)
packages/extension-polkagate/src/fullscreen/components/DraggableModal.tsx (1)
  • DraggableModal (30-172)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Analyze (javascript)
  • GitHub Check: build
🔇 Additional comments (3)
packages/extension-polkagate/src/fullscreen/notification/NotificationSettingsFS.tsx (3)

1-17: LGTM!

Imports are well-organized and all are utilized. The CARD_STYLE constant appropriately centralizes shared styling.


56-56: Past review comment appears resolved.

The translation key now correctly uses "Enable Received Funds" as suggested in the previous review.


179-190: LGTM!

The DraggableModal integration is clean, with appropriate props and styling. The component structure follows React best practices with proper hook usage and TypeScript typing.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (4)
packages/extension-polkagate/src/popup/notification/helpers.ts (4)

24-28: Normalize both addresses before comparison.

The filter on Line 26 compares getSubstrateAddress(transfer.to) (normalized to SS58-42) against the raw address parameter, which may be in a different SS58 format. This asymmetry causes missed matches when address isn't already SS58-42.

Apply this diff to normalize both sides:

+  const normalizedAddress = getSubstrateAddress(address);
+
   const result = transfers.reduce((accumulator, transfer) => {
-    if (getSubstrateAddress(transfer.to) !== address) {
+    if (getSubstrateAddress(transfer.to) !== normalizedAddress) {
       return accumulator;
     }

94-94: Status normalization doesn't handle camelCase variants.

Simply lowercasing referenda.status on Line 94 won't properly map Subscan's "TimedOut" to the expected 'timedOut' union member—it produces 'timedout' instead, causing the status branch to fail.

Apply this diff to normalize correctly:

+const normalizeReferendaStatus = (status: string): ReferendaStatus => {
+  const normalized = status.replace(/_/g, '').toLowerCase();
+
+  return normalized === 'timedout'
+    ? 'timedOut'
+    : normalized as ReferendaStatus;
+};
+
 const transformReferendas = (referendas: ReferendaSubscan[], network: DropdownOption) => {
   ...
   const result = filtered.reduce((accumulator, referenda) => {
     const sanitizedReferenda = {
       ...
-      status: referenda.status.toLowerCase() as ReferendaStatus,
+      status: normalizeReferendaStatus(referenda.status),
       ...
     };

180-182: Fix throttling condition to check networks.length.

Line 180 compares i + BATCH_SIZE < addresses.length, but i indexes into the networks array. This breaks rate limiting: the code may skip necessary pauses when more network batches remain, or pause when none are queued.

Apply this diff:

-      if (i + BATCH_SIZE < addresses.length) {
+      if (i + BATCH_SIZE < networks.length) {
         await new Promise((resolve) => setTimeout(resolve, 1000));
       }

267-269: Fix throttling condition to check networks.length.

Line 267 compares i + BATCH_SIZE < addresses.length, but i indexes the networks array. This breaks rate limiting: it may skip necessary pauses when more network batches remain, or pause when none are queued.

Apply this diff:

-      if (i + BATCH_SIZE < addresses.length) {
+      if (i + BATCH_SIZE < networks.length) {
         await new Promise((resolve) => setTimeout(resolve, 1000));
       }
🧹 Nitpick comments (1)
packages/extension-polkagate/src/popup/notification/helpers.ts (1)

289-341: Consider adding throttling between network requests.

Unlike getReceivedFundsInformation and getPayoutsInformation, this function processes networks sequentially without any delay between requests. Adding a small delay (e.g., 500-1000ms) would provide consistent rate limiting and reduce the risk of hitting Subscan's throttles.

For example, add a delay after each successful network request:

 for (const network of networks) {
   ...
   const result = await promise();

   if (result) {
     results.push(result);
   }
+
+  // Optional: Add delay between networks for rate limiting
+  await new Promise((resolve) => setTimeout(resolve, 500));
 }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ffd09ef and 37150f1.

📒 Files selected for processing (2)
  • packages/extension-polkagate/src/popup/notification/constant.ts (1 hunks)
  • packages/extension-polkagate/src/popup/notification/helpers.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/extension-polkagate/src/popup/notification/constant.ts
🧰 Additional context used
🧬 Code graph analysis (1)
packages/extension-polkagate/src/popup/notification/helpers.ts (10)
packages/extension-polkagate/src/popup/notification/types.ts (10)
  • TransferSubscan (14-38)
  • TransfersProp (78-87)
  • PayoutSubscan (40-50)
  • PayoutsProp (89-94)
  • ReferendaSubscan (52-62)
  • ReferendaProp (96-107)
  • ReceivedFundInformation (109-113)
  • ApiResponse (7-12)
  • StakingRewardInformation (115-119)
  • ReferendaInformation (121-124)
packages/extension-polkagate/src/util/types.ts (1)
  • DropdownOption (877-880)
packages/extension-polkagate/src/util/address.ts (1)
  • getSubstrateAddress (40-59)
packages/extension-polkagate/src/popup/notification/util.ts (1)
  • timestampToDate (16-51)
packages/extension-polkagate/src/popup/notification/constant.ts (7)
  • ReferendaStatus (6-6)
  • BATCH_SIZE (19-19)
  • MAX_RETRIES (18-18)
  • RECEIVED_FUNDS_THRESHOLD (10-10)
  • RECEIVED_REWARDS_THRESHOLD (11-11)
  • REFERENDA_COUNT_TO_TRACK_DOT (12-12)
  • REFERENDA_COUNT_TO_TRACK_KSM (13-13)
packages/extension-polkagate/src/util/migrateHubUtils.ts (1)
  • isMigratedRelay (103-105)
packages/extension-polkagate/src/util/getChainName.ts (1)
  • getChainName (15-29)
packages/extension-polkagate/src/util/chain.ts (1)
  • getSubscanChainName (32-54)
packages/extension-polkagate/src/util/api/postData.ts (1)
  • postData (6-25)
packages/extension-polkagate/src/util/constants.ts (2)
  • POLKADOT_GENESIS_HASH (58-58)
  • KUSAMA_GENESIS_HASH (59-59)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: build
  • GitHub Check: Analyze (javascript)

Comment on lines +236 to +240
const payoutInfo = [...(soloPayoutInfo?.data?.list ?? []), ...(poolPayoutInfo?.data?.list ?? [])];

if (!payoutInfo) {
return null; // account doesn't have any history
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Remove unreachable null check.

Line 236 constructs payoutInfo by spreading two arrays, which always yields an array (possibly empty []), never null or undefined. The check on Line 238 is unreachable and should be removed.

Apply this diff:

 const payoutInfo = [...(soloPayoutInfo?.data?.list ?? []), ...(poolPayoutInfo?.data?.list ?? [])];

-if (!payoutInfo) {
-  return null; // account doesn't have any history
-}
+if (payoutInfo.length === 0) {
+  return null; // account doesn't have any history
+}

 return transformPayouts(address, payoutInfo, network);
📝 Committable suggestion

‼️ 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.

Suggested change
const payoutInfo = [...(soloPayoutInfo?.data?.list ?? []), ...(poolPayoutInfo?.data?.list ?? [])];
if (!payoutInfo) {
return null; // account doesn't have any history
}
const payoutInfo = [...(soloPayoutInfo?.data?.list ?? []), ...(poolPayoutInfo?.data?.list ?? [])];
if (payoutInfo.length === 0) {
return null; // account doesn't have any history
}
🤖 Prompt for AI Agents
In packages/extension-polkagate/src/popup/notification/helpers.ts around lines
236 to 240, the code builds payoutInfo by spreading two lists which always
produces an array (never null/undefined), so the subsequent null check is
unreachable; remove the `if (!payoutInfo) { return null }` block and any
dependent branch assuming payoutInfo can be null, leaving logic to handle an
empty array instead.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants