@@ -100,8 +101,27 @@ export const getCountdownTimeStatus = (
startDate: Date,
endDate: Date | null
) => {
- const currentDate = new Date()
+ if (!startDate && !endDate) {
+ return {
+ currentDate: null,
+ currentTimeInSeconds: null,
+ startTimeInSeconds: null,
+ endTimeInSeconds: null,
+ totalTimeInSeconds: null,
+ totalTimeElapsedInSeconds: null,
+ totalTimeRemainingInSeconds: null,
+ totalTimeRemainingInMinutes: null,
+ daysRemaining: null,
+ hoursRemaining: null,
+ minutesRemaining: null,
+ secondsRemaining: null,
+ isStarted: false,
+ isComplete: false,
+ isPending: false,
+ }
+ }
+ const currentDate = new Date()
const currentTimeInSeconds = Math.floor(currentDate.getTime() / 1000)
const startTimeInSeconds = Math.floor(startDate.getTime() / 1000)
@@ -164,9 +184,7 @@ export const getCountdownTimeStatus = (
const calculateTimeUntilTarget = (targetDate: Date) => {
const currentDate = new Date()
-
const timeDifference = targetDate.getTime() - currentDate.getTime()
-
const isComplete = timeDifference <= 0
const daysRemaining = Math.floor(timeDifference / (1000 * 60 * 60 * 24))
diff --git a/packages/synapse-interface/components/Maintenance/components/useMaintenanceCountdownProgress.tsx b/packages/synapse-interface/components/Maintenance/components/useMaintenanceCountdownProgress.tsx
deleted file mode 100644
index 94e883c917..0000000000
--- a/packages/synapse-interface/components/Maintenance/components/useMaintenanceCountdownProgress.tsx
+++ /dev/null
@@ -1,38 +0,0 @@
-import { useEventCountdownProgressBar } from './EventCountdownProgressBar'
-import { isChainIncluded } from '@/utils/isChainIncluded'
-
-export const useMaintenanceCountdownProgress = ({
- fromChainId,
- toChainId,
- startDate,
- endDate,
- pausedFromChains,
- pausedToChains,
- progressBarMessage,
- disabled = false,
-}: {
- fromChainId: number
- toChainId: number
- startDate: Date
- endDate: Date | null
- pausedFromChains: number[]
- pausedToChains: number[]
- progressBarMessage: any
- disabled?: boolean
-}) => {
- const isCurrentChain =
- isChainIncluded([fromChainId], pausedFromChains) ||
- isChainIncluded([toChainId], pausedToChains)
-
- const {
- isPending: isMaintenancePending,
- EventCountdownProgressBar: MaintenanceCountdownProgressBar,
- } = useEventCountdownProgressBar(progressBarMessage, startDate, endDate)
-
- return {
- isMaintenancePending,
- isCurrentChainDisabled: isCurrentChain && isMaintenancePending,
- MaintenanceCountdownProgressBar:
- isCurrentChain && !disabled ? MaintenanceCountdownProgressBar : null,
- }
-}
diff --git a/packages/synapse-interface/components/Maintenance/functions/fetchJsonData.ts b/packages/synapse-interface/components/Maintenance/functions/fetchJsonData.ts
new file mode 100644
index 0000000000..ec8c05ea86
--- /dev/null
+++ b/packages/synapse-interface/components/Maintenance/functions/fetchJsonData.ts
@@ -0,0 +1,7 @@
+export const fetchJSONData = async (url: string): Promise
=> {
+ const response = await fetch(url)
+ if (!response.ok) {
+ throw new Error(`HTTP error! status: ${response.status}`)
+ }
+ return response.json()
+}
diff --git a/packages/synapse-interface/components/Maintenance/functions/getSynapsePauseData.ts b/packages/synapse-interface/components/Maintenance/functions/getSynapsePauseData.ts
new file mode 100644
index 0000000000..da144f1c90
--- /dev/null
+++ b/packages/synapse-interface/components/Maintenance/functions/getSynapsePauseData.ts
@@ -0,0 +1,39 @@
+import { useAppDispatch } from '@/store/hooks'
+import {
+ setPausedChainsData,
+ setPausedModulesData,
+} from '@/slices/maintenance/reducer'
+import { fetchJSONData } from './fetchJsonData'
+
+export const PAUSED_CHAINS_URL =
+ 'https://raw.githubusercontent.com/synapsecns/sanguine/test/maintenance/packages/synapse-interface/public/pauses/v1/paused-chains.json'
+export const PAUSED_MODULES_URL =
+ 'https://raw.githubusercontent.com/synapsecns/sanguine/test/maintenance/packages/synapse-interface/public/pauses/v1/paused-bridge-modules.json'
+
+let isFetching = false
+
+export const getSynapsePauseData = () => {
+ const dispatch = useAppDispatch()
+
+ const fetchAndStoreData = async () => {
+ if (isFetching) {
+ return
+ }
+ try {
+ isFetching = true
+ const pausedChainsData = await fetchJSONData(PAUSED_CHAINS_URL)
+ const pausedModulesData = await fetchJSONData(PAUSED_MODULES_URL)
+
+ dispatch(setPausedChainsData(pausedChainsData))
+ dispatch(setPausedModulesData(pausedModulesData))
+ } catch (error) {
+ console.error('Failed to fetch paused chains/modules: ', error)
+ } finally {
+ setTimeout(() => {
+ isFetching = false
+ }, 1000)
+ }
+ }
+
+ return fetchAndStoreData
+}
diff --git a/packages/synapse-interface/components/layouts/LandingPageWrapper/index.tsx b/packages/synapse-interface/components/layouts/LandingPageWrapper/index.tsx
index 7c033f624c..2873bd781c 100644
--- a/packages/synapse-interface/components/layouts/LandingPageWrapper/index.tsx
+++ b/packages/synapse-interface/components/layouts/LandingPageWrapper/index.tsx
@@ -25,7 +25,10 @@ import { NAVIGATION } from '@/constants/routes'
import { MoreButton } from './MoreButton'
import { PageFooter } from './PageFooter'
import { joinClassNames } from '@/utils/joinClassNames'
-import { MaintenanceBanners } from '@/components/Maintenance/Maintenance'
+import {
+ MaintenanceBanners,
+ useMaintenance,
+} from '@/components/Maintenance/Maintenance'
import { AnnouncementBanner } from '@/components/Maintenance/components/AnnouncementBanner'
const wrapperClassName = joinClassNames({
diff --git a/packages/synapse-interface/contexts/MaintenanceProvider.tsx b/packages/synapse-interface/contexts/MaintenanceProvider.tsx
new file mode 100644
index 0000000000..b377d1feca
--- /dev/null
+++ b/packages/synapse-interface/contexts/MaintenanceProvider.tsx
@@ -0,0 +1,18 @@
+import { createContext } from 'react'
+import { getSynapsePauseData } from '@/components/Maintenance/functions/getSynapsePauseData'
+import { useIntervalTimer } from '@/utils/hooks/useIntervalTimer'
+
+const MaintenanceContext = createContext(null)
+
+export const MaintenanceProvider = ({ children }) => {
+ const time = useIntervalTimer(60000)
+ const fetchMaintenanceData = getSynapsePauseData()
+
+ fetchMaintenanceData()
+
+ return (
+
+ {children}
+
+ )
+}
diff --git a/packages/synapse-interface/pages/_app.tsx b/packages/synapse-interface/pages/_app.tsx
index fd4f1d8c57..77f4959753 100644
--- a/packages/synapse-interface/pages/_app.tsx
+++ b/packages/synapse-interface/pages/_app.tsx
@@ -13,6 +13,7 @@ import setupLogRocketReact from 'logrocket-react'
import { SegmentAnalyticsProvider } from '@/contexts/SegmentAnalyticsProvider'
import { UserProvider } from '@/contexts/UserProvider'
+import { MaintenanceProvider } from '@/contexts/MaintenanceProvider'
import { BackgroundListenerProvider } from '@/contexts/BackgroundListenerProvider'
import CustomToaster from '@/components/toast'
import { SynapseProvider } from '@/utils/providers/SynapseProvider'
@@ -51,10 +52,12 @@ function App({ Component, pageProps }: AppProps) {
-
-
-
-
+
+
+
+
+
+
diff --git a/packages/synapse-interface/pages/state-managed-bridge/index.tsx b/packages/synapse-interface/pages/state-managed-bridge/index.tsx
index 46befb6311..458a528ca7 100644
--- a/packages/synapse-interface/pages/state-managed-bridge/index.tsx
+++ b/packages/synapse-interface/pages/state-managed-bridge/index.tsx
@@ -1,4 +1,5 @@
import toast from 'react-hot-toast'
+import { isEmpty } from 'lodash'
import { useEffect, useRef, useState } from 'react'
import { commify } from '@ethersproject/units'
import { Address, zeroAddress, isAddress } from 'viem'
@@ -63,14 +64,8 @@ import { RootState } from '@/store/store'
import { getTimeMinutesFromNow } from '@/utils/time'
import { isTransactionReceiptError } from '@/utils/isTransactionReceiptError'
import { isTransactionUserRejectedError } from '@/utils/isTransactionUserRejectedError'
-import {
- MaintenanceWarningMessages,
- useMaintenanceCountdownProgresses,
-} from '@/components/Maintenance/Maintenance'
-import {
- PAUSED_MODULES,
- getBridgeModuleNames,
-} from '@/components/Maintenance/Maintenance'
+import { useMaintenance } from '@/components/Maintenance/Maintenance'
+import { getBridgeModuleNames } from '@/components/Maintenance/Maintenance'
import { wagmiConfig } from '@/wagmiConfig'
import { useStaleQuoteUpdater } from '@/utils/hooks/useStaleQuoteUpdater'
@@ -99,6 +94,14 @@ const StateManagedBridge = () => {
(state: RootState) => state.bridgeDisplay
)
+ const {
+ isBridgePaused,
+ pausedChainsList,
+ pausedModulesList,
+ BridgeMaintenanceProgressBar,
+ BridgeMaintenanceWarningMessage,
+ } = useMaintenance()
+
const [isApproved, setIsApproved] = useState(false)
const dispatch = useAppDispatch()
@@ -165,9 +168,11 @@ const StateManagedBridge = () => {
)
const pausedBridgeModules = new Set(
- PAUSED_MODULES.filter((module) =>
- module.chainId ? module.chainId === fromChainId : true
- ).flatMap(getBridgeModuleNames)
+ pausedModulesList
+ .filter((module) =>
+ module.chainId ? module.chainId === fromChainId : true
+ )
+ .flatMap(getBridgeModuleNames)
)
const activeQuotes = allQuotes.filter(
@@ -534,13 +539,6 @@ const StateManagedBridge = () => {
}
}
- const maintenanceCountdownProgressInstances =
- useMaintenanceCountdownProgresses({ type: 'Bridge' })
-
- const isBridgePaused = maintenanceCountdownProgressInstances.some(
- (instance) => instance.isCurrentChainDisabled
- )
-
return (
@@ -572,9 +570,7 @@ const StateManagedBridge = () => {
- {maintenanceCountdownProgressInstances.map((instance) => (
- <>{instance.MaintenanceCountdownProgressBar}>
- ))}
+
{showSettingsSlideOver && (
@@ -594,7 +590,7 @@ const StateManagedBridge = () => {
/>
-
+
{
const { address } = useAccount()
@@ -62,6 +59,14 @@ const StateManagedSwap = () => {
const { swapChainId, swapFromToken, swapToToken, swapFromValue, swapQuote } =
useSwapState()
+ const {
+ isSwapPaused,
+ pausedChainsList,
+ pausedModulesList,
+ SwapMaintenanceProgressBar,
+ SwapMaintenanceWarningMessage,
+ } = useMaintenance()
+
const [isApproved, setIsApproved] = useState(false)
const dispatch = useAppDispatch()
@@ -345,13 +350,6 @@ const StateManagedSwap = () => {
}
}
- const maintenanceCountdownProgressInstances =
- useMaintenanceCountdownProgresses({ type: 'Swap' })
-
- const isSwapPaused = maintenanceCountdownProgressInstances.some(
- (instance) => instance.isCurrentChainDisabled
- )
-
return (
@@ -360,10 +358,7 @@ const StateManagedSwap = () => {
- {maintenanceCountdownProgressInstances.map((instance) => (
- <>{instance.MaintenanceCountdownProgressBar}>
- ))}
-
+
{
@@ -372,7 +367,7 @@ const StateManagedSwap = () => {
}}
/>
-
+
{
+ return useAppSelector((state) => state.maintenance)
+}
diff --git a/packages/synapse-interface/slices/maintenance/reducer.ts b/packages/synapse-interface/slices/maintenance/reducer.ts
new file mode 100644
index 0000000000..da6829001b
--- /dev/null
+++ b/packages/synapse-interface/slices/maintenance/reducer.ts
@@ -0,0 +1,29 @@
+import { createSlice, PayloadAction } from '@reduxjs/toolkit'
+
+export interface MaintenanceState {
+ pausedChainsData: any
+ pausedModulesData: any
+}
+
+const initialState: MaintenanceState = {
+ pausedChainsData: null,
+ pausedModulesData: null,
+}
+
+export const maintenanceSlice = createSlice({
+ name: 'maintenance',
+ initialState,
+ reducers: {
+ setPausedChainsData: (state, action: PayloadAction) => {
+ state.pausedChainsData = action.payload
+ },
+ setPausedModulesData: (state, action: PayloadAction) => {
+ state.pausedModulesData = action.payload
+ },
+ },
+})
+
+export const { setPausedChainsData, setPausedModulesData } =
+ maintenanceSlice.actions
+
+export default maintenanceSlice.reducer
diff --git a/packages/synapse-interface/store/reducer.ts b/packages/synapse-interface/store/reducer.ts
index 6c41870f92..a76bdde417 100644
--- a/packages/synapse-interface/store/reducer.ts
+++ b/packages/synapse-interface/store/reducer.ts
@@ -8,6 +8,7 @@ import bridge from '@/slices/bridge/reducer'
import portfolio from '@/slices/portfolio/reducer'
import swap from '@/slices/swap/reducer'
import transactions from '@/slices/transactions/reducer'
+import maintenance from '@/slices/maintenance/reducer'
import bridgeDisplay from '@/slices/bridgeDisplaySlice'
import poolData from '@/slices/poolDataSlice'
import poolDeposit from '@/slices/poolDepositSlice'
@@ -37,6 +38,7 @@ export const appReducer = combineReducers({
bridge,
portfolio,
swap,
+ maintenance,
bridgeDisplay,
poolData,
poolDeposit,
diff --git a/packages/synapse-interface/utils/isChainIncluded.tsx b/packages/synapse-interface/utils/isChainIncluded.tsx
index 6aa54f3bd3..aa942d6d5f 100644
--- a/packages/synapse-interface/utils/isChainIncluded.tsx
+++ b/packages/synapse-interface/utils/isChainIncluded.tsx
@@ -7,5 +7,5 @@
*/
export const isChainIncluded = (chainList: number[], hasChains: number[]) => {
- return hasChains.some((chainId) => chainList.includes(chainId))
+ return hasChains?.some((chainId) => chainList.includes(chainId))
}