From bcc755ee61e10483b260cac2ebda061b07d75cbd Mon Sep 17 00:00:00 2001 From: dwjanus Date: Thu, 11 Dec 2025 13:44:03 -0500 Subject: [PATCH 1/2] add initial rewards reminder to useNotificationTypes --- src/hooks/useNotificationTypes.tsx | 56 ++++++++++++++++++++++++++++++ src/state/dismissable.ts | 6 ++++ src/state/dismissableSelectors.ts | 3 ++ 3 files changed, 65 insertions(+) diff --git a/src/hooks/useNotificationTypes.tsx b/src/hooks/useNotificationTypes.tsx index 370be2e84..9a59e898a 100644 --- a/src/hooks/useNotificationTypes.tsx +++ b/src/hooks/useNotificationTypes.tsx @@ -57,6 +57,8 @@ import { } from '@/state/accountSelectors'; import { useAppDispatch, useAppSelector } from '@/state/appTypes'; import { openDialog } from '@/state/dialogs'; +import { setHasDismissedTradingLeagueRewardsNotification } from '@/state/dismissable'; +import { getHasDismissedTradingLeagueRewardsNotification } from '@/state/dismissableSelectors'; import { getLocalCancelAlls, getLocalCancelOrders, @@ -574,6 +576,7 @@ export const notificationTypes: NotificationTypeConfig[] = [ type: NotificationType.RewardsProgramUpdates, useTrigger: ({ trigger }) => { const stringGetter = useStringGetter(); + const dispatch = useAppDispatch(); const dydxAddress = useAppSelector(getUserWalletAddress); const currentSeason = CURRENT_REWARDS_SEASON; @@ -729,6 +732,59 @@ export const notificationTypes: NotificationTypeConfig[] = [ updateKey: [`pump-trading-competition-base`], }); }, [stringGetter, trigger]); + + const hasDismissedTradingLeagueRewardsNotification = useAppSelector( + getHasDismissedTradingLeagueRewardsNotification + ); + const hasShownRewardNotificationThisSession = useRef(false); + + useEffect(() => { + const now = new Date().getTime(); + const seasonEnd = new Date(CURRENT_REWARDS_SEASON_EXPIRATION).getTime(); + + if ( + now < seasonEnd && + dydxAddress != null && + !hasDismissedTradingLeagueRewardsNotification && + !hasShownRewardNotificationThisSession.current + ) { + hasShownRewardNotificationThisSession.current = true; + + // TODO: localize notification strings + trigger({ + id: `trading-league-rewards-notification`, + displayData: { + icon: , + title: 'Rewards Reminder', + body: 'Have you claimed your Trading League rewards yet?', + toastSensitivity: 'foreground', + groupKey: NotificationType.RewardsProgramUpdates, + actionAltText: 'Go to Rewards', + renderActionSlot: () => ( + // TODO: replace with official trading league rewards page + { + dispatch(setHasDismissedTradingLeagueRewardsNotification(true)); + }} + > + Go to Rewards + + ), + }, + updateKey: [`trading-league-rewards-notification`], + }); + } + }, [ + currentSeason, + dispatch, + dydxAddress, + hasDismissedTradingLeagueRewardsNotification, + hasShownRewardNotificationThisSession, + stringGetter, + trigger, + ]); }, }, { diff --git a/src/state/dismissable.ts b/src/state/dismissable.ts index 0894cb9c9..211806edb 100644 --- a/src/state/dismissable.ts +++ b/src/state/dismissable.ts @@ -12,6 +12,7 @@ export interface DismissableState { hasDismissedRebateBanner: boolean; hasDismissedTradingLeagueBanner: boolean; hasDismissedNoFeeBanner: boolean; + hasDismissedTradingLeagueRewardsNotification: boolean; } const initialState: DismissableState = { @@ -24,6 +25,7 @@ const initialState: DismissableState = { hasDismissedRebateBanner: false, hasDismissedTradingLeagueBanner: false, hasDismissedNoFeeBanner: false, + hasDismissedTradingLeagueRewardsNotification: false, }; export const dismissableSlice = createSlice({ @@ -54,6 +56,9 @@ export const dismissableSlice = createSlice({ setHasDismissedNoFeeBanner: (state, action: PayloadAction) => { state.hasDismissedNoFeeBanner = action.payload; }, + setHasDismissedTradingLeagueRewardsNotification: (state, action: PayloadAction) => { + state.hasDismissedTradingLeagueRewardsNotification = action.payload; + }, }, }); @@ -66,4 +71,5 @@ export const { setHasDismissedRebateBanner, setHasDismissedTradingLeagueBanner, setHasDismissedNoFeeBanner, + setHasDismissedTradingLeagueRewardsNotification, } = dismissableSlice.actions; diff --git a/src/state/dismissableSelectors.ts b/src/state/dismissableSelectors.ts index 720182b91..f673a9232 100644 --- a/src/state/dismissableSelectors.ts +++ b/src/state/dismissableSelectors.ts @@ -23,3 +23,6 @@ export const getHasDismissedTradingLeagueBanner = (state: RootState) => export const getHasDismissedNoFeeBanner = (state: RootState) => state.dismissable.hasDismissedNoFeeBanner; + +export const getHasDismissedTradingLeagueRewardsNotification = (state: RootState) => + state.dismissable.hasDismissedTradingLeagueRewardsNotification; From 30da65443db79d74266d4316d5d946256ac81498 Mon Sep 17 00:00:00 2001 From: dwjanus Date: Fri, 12 Dec 2025 14:25:28 -0500 Subject: [PATCH 2/2] add reward claim notification --- package.json | 2 +- pnpm-lock.yaml | 8 +++---- src/hooks/useNotificationTypes.tsx | 38 +++++++++--------------------- 3 files changed, 16 insertions(+), 32 deletions(-) diff --git a/package.json b/package.json index 00f01d0c1..39789be41 100644 --- a/package.json +++ b/package.json @@ -55,7 +55,7 @@ "@cosmjs/tendermint-rpc": "^0.32.1", "@datadog/browser-logs": "^5.23.3", "@dydxprotocol/v4-client-js": "3.2.0", - "@dydxprotocol/v4-localization": "1.1.365", + "@dydxprotocol/v4-localization": "1.1.366", "@dydxprotocol/v4-proto": "^7.0.0-dev.0", "@emotion/is-prop-valid": "^1.3.0", "@hugocxl/react-to-image": "^0.0.9", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 37275b055..6baec84b7 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -33,8 +33,8 @@ dependencies: specifier: 3.2.0 version: 3.2.0 '@dydxprotocol/v4-localization': - specifier: 1.1.365 - version: 1.1.365 + specifier: 1.1.366 + version: 1.1.366 '@dydxprotocol/v4-proto': specifier: ^7.0.0-dev.0 version: 7.0.5 @@ -1702,8 +1702,8 @@ packages: - utf-8-validate dev: false - /@dydxprotocol/v4-localization@1.1.365: - resolution: {integrity: sha512-ea+HKdKlInDCgIVtaWhZrviDvAqSsbEBKo3aqrXWM2cpS0RV9VK0/SPO/NSru+tQJuBCeTji1yByR0gCHACFbg==} + /@dydxprotocol/v4-localization@1.1.366: + resolution: {integrity: sha512-UWCGIsZ2exE4W8OhR8IfBrbiXD3Y8+2WLemzBY8kT/6QPvP5Lgz4NymxNvS9L6hbkUbjXUXHdCP8AfvuaPw/Nw==} dev: false /@dydxprotocol/v4-proto@7.0.5: diff --git a/src/hooks/useNotificationTypes.tsx b/src/hooks/useNotificationTypes.tsx index 9a59e898a..1db6e1c2f 100644 --- a/src/hooks/useNotificationTypes.tsx +++ b/src/hooks/useNotificationTypes.tsx @@ -736,55 +736,39 @@ export const notificationTypes: NotificationTypeConfig[] = [ const hasDismissedTradingLeagueRewardsNotification = useAppSelector( getHasDismissedTradingLeagueRewardsNotification ); - const hasShownRewardNotificationThisSession = useRef(false); - useEffect(() => { const now = new Date().getTime(); const seasonEnd = new Date(CURRENT_REWARDS_SEASON_EXPIRATION).getTime(); - if ( - now < seasonEnd && - dydxAddress != null && - !hasDismissedTradingLeagueRewardsNotification && - !hasShownRewardNotificationThisSession.current - ) { - hasShownRewardNotificationThisSession.current = true; - - // TODO: localize notification strings + if (now < seasonEnd && rewards != null && !hasDismissedTradingLeagueRewardsNotification) { trigger({ id: `trading-league-rewards-notification`, displayData: { - icon: , - title: 'Rewards Reminder', - body: 'Have you claimed your Trading League rewards yet?', + icon: , + title: stringGetter({ key: STRING_KEYS.TRADING_LEAGUES }), + body: stringGetter({ key: STRING_KEYS.CLAIM_TRADING_LEAGUE_REWARD_BODY }), toastSensitivity: 'foreground', groupKey: NotificationType.RewardsProgramUpdates, - actionAltText: 'Go to Rewards', + actionAltText: stringGetter({ key: STRING_KEYS.CHECK_ELIGIBILITY }), renderActionSlot: () => ( - // TODO: replace with official trading league rewards page { dispatch(setHasDismissedTradingLeagueRewardsNotification(true)); }} > - Go to Rewards + {stringGetter({ key: STRING_KEYS.CHECK_ELIGIBILITY })} ), }, updateKey: [`trading-league-rewards-notification`], }); } - }, [ - currentSeason, - dispatch, - dydxAddress, - hasDismissedTradingLeagueRewardsNotification, - hasShownRewardNotificationThisSession, - stringGetter, - trigger, - ]); + }, [currentSeason, rewards, stringGetter, trigger]); + }, + useNotificationAction: () => { + return () => {}; }, }, {