Skip to content

Commit

Permalink
Merge 88b7a9a into 8e30911
Browse files Browse the repository at this point in the history
  • Loading branch information
bigboydiamonds authored Jul 25, 2024
2 parents 8e30911 + 88b7a9a commit 3f33dd0
Show file tree
Hide file tree
Showing 19 changed files with 412 additions and 234 deletions.
306 changes: 158 additions & 148 deletions packages/synapse-interface/components/Maintenance/Maintenance.tsx
Original file line number Diff line number Diff line change
@@ -1,189 +1,199 @@
import { MaintenanceBanner } from './components/MaintenanceBanner'
import { MaintenanceWarningMessage } from './components/MaintenanceWarningMessage'
import { useMaintenanceCountdownProgress } from './components/useMaintenanceCountdownProgress'
import { useEventCountdownProgressBar } from './components/EventCountdownProgressBar'
import { useBridgeState } from '@/slices/bridge/hooks'
import { useSwapState } from '@/slices/swap/hooks'
import pausedChains from '@/public/pauses/v1/paused-chains.json'
import pausedBridgeModules from '@/public/pauses/v1/paused-bridge-modules.json'
import { useMaintenanceState } from '@/slices/maintenance/hooks'
import { isChainIncluded } from '@/utils/isChainIncluded'
import { isValidBridgeModule } from './functions/isValidBridgeModule'
import { getFurthestFutureDate } from './functions/getFurthestFutureDate'

/** Pause Chain Activity */
interface ChainPause {
id: string
pausedFromChains: number[]
pausedToChains: number[]
pauseBridge: boolean
pauseSwap: boolean
startTimePauseChain: Date
endTimePauseChain: Date | null // If null, pause indefinitely
endTimePauseChain: Date | null // If null, pause chain indefinitely.
startTimeBanner: Date
endTimeBanner: Date | null // If null, pause indefinitely
inputWarningMessage: JSX.Element
endTimeBanner: Date | null // If null, persist banner indefinitely.
inputWarningMessage: string
bannerMessage: JSX.Element
progressBarMessage: JSX.Element
progressBarMessage: string
disableBanner: boolean
disableWarning: boolean
disableCountdown: boolean
}

const PAUSED_CHAINS: ChainPause[] = pausedChains.map((pause) => {
interface BridgeModulePause {
chainId?: number // If undefined, pause bridge module for all chains.
bridgeModuleName: 'SynapseBridge' | 'SynapseRFQ' | 'SynapseCCTP' | 'ALL'
}

const useMaintenanceData = () => {
const { pausedChainsData, pausedModulesData } = useMaintenanceState()

const pausedChainsList: ChainPause[] = pausedChainsData
? pausedChainsData?.map((pause: ChainPause) => {
return {
...pause,
startTimeBanner: new Date(pause.startTimeBanner),
endTimeBanner: pause.endTimeBanner
? new Date(pause.endTimeBanner)
: null,
startTimePauseChain: new Date(pause.startTimePauseChain),
endTimePauseChain: pause.endTimePauseChain
? new Date(pause.endTimePauseChain)
: null,
bannerMessage: <p className="text-left">{pause.bannerMessage}</p>,
inputWarningMessage: pause.inputWarningMessage,
progressBarMessage: pause.progressBarMessage,
}
})
: []

const pausedModulesList: BridgeModulePause[] = pausedModulesData
? pausedModulesData?.map((route: BridgeModulePause) => {
if (!isValidBridgeModule(route.bridgeModuleName)) {
throw new Error(`Invalid module type: ${route.bridgeModuleName}`)
}

return {
...route,
bridgeModuleName: route.bridgeModuleName as
| 'SynapseBridge'
| 'SynapseRFQ'
| 'SynapseCCTP'
| 'ALL',
}
})
: []

return {
...pause,
startTimePauseChain: new Date(pause.startTimePauseChain),
endTimePauseChain: pause.endTimePauseChain
? new Date(pause.endTimePauseChain)
: null,
startTimeBanner: new Date(pause.startTimeBanner),
endTimeBanner: pause.endTimeBanner ? new Date(pause.endTimeBanner) : null,
inputWarningMessage: <p>{pause.inputWarningMessage}</p>,
bannerMessage: <p className="text-left">{pause.bannerMessage}</p>,
progressBarMessage: <p>{pause.progressBarMessage}</p>,
pausedChainsList,
pausedModulesList,
}
})

export const MaintenanceBanners = () => {
return (
<>
{PAUSED_CHAINS.map((event) => {
return (
<MaintenanceBanner
id={event.id}
bannerMessage={event.bannerMessage}
startDate={event.startTimeBanner}
endDate={event.endTimeBanner}
disabled={event.disableBanner}
/>
)
})}
</>
)
}

export const MaintenanceWarningMessages = ({
type,
}: {
type: 'Bridge' | 'Swap'
}) => {
export const MaintenanceBanners = () => {
const { pausedChainsList } = useMaintenanceData()
const { fromChainId: bridgeFromChainId, toChainId: bridgeToChainId } =
useBridgeState()
const { swapChainId } = useSwapState()

if (type === 'Bridge') {
return (
<>
{PAUSED_CHAINS.map((event) => {
return (
<MaintenanceWarningMessage
fromChainId={bridgeFromChainId}
toChainId={bridgeToChainId}
startDate={event.startTimePauseChain}
endDate={event.endTimePauseChain}
pausedFromChains={event.pausedFromChains}
pausedToChains={event.pausedToChains}
warningMessage={event.inputWarningMessage}
disabled={event.disableWarning || !event.pauseBridge}
/>
)
})}
</>
)
} else if (type === 'Swap') {
const activeBanner = pausedChainsList.find(
(pausedChain) =>
isChainIncluded(pausedChain?.pausedFromChains, [bridgeFromChainId]) ||
isChainIncluded(pausedChain?.pausedToChains, [bridgeToChainId]) ||
isChainIncluded(pausedChain?.pausedFromChains, [swapChainId]) ||
isChainIncluded(pausedChain?.pausedToChains, [swapChainId])
)

if (activeBanner) {
return (
<>
{PAUSED_CHAINS.map((event) => {
return (
<MaintenanceWarningMessage
fromChainId={swapChainId}
toChainId={null}
startDate={event.startTimePauseChain}
endDate={event.endTimePauseChain}
pausedFromChains={event.pausedFromChains}
pausedToChains={event.pausedToChains}
warningMessage={event.inputWarningMessage}
disabled={event.disableWarning || !event.pauseSwap}
/>
)
})}
</>
<MaintenanceBanner
id={activeBanner?.id}
bannerMessage={activeBanner?.bannerMessage}
startDate={activeBanner?.startTimeBanner}
endDate={activeBanner?.endTimeBanner}
disabled={activeBanner?.disableBanner}
/>
)
} else {
return null
}
}

/**
* Hook that maps through PAUSED_CHAINS to apply the single event countdown progress logic to each.
* @returns A list of objects containing maintenance status and components for each paused chain.
*/
export const useMaintenanceCountdownProgresses = ({
type,
}: {
type: 'Bridge' | 'Swap'
}) => {
export const useMaintenance = () => {
const { pausedChainsList, pausedModulesList } = useMaintenanceData()
const { fromChainId: bridgeFromChainId, toChainId: bridgeToChainId } =
useBridgeState()
const { swapChainId } = useSwapState()

if (type === 'Bridge') {
return PAUSED_CHAINS.map((event) => {
return useMaintenanceCountdownProgress({
fromChainId: bridgeFromChainId,
toChainId: bridgeToChainId,
startDate: event.startTimePauseChain,
endDate: event.endTimePauseChain,
pausedFromChains: event.pausedFromChains,
pausedToChains: event.pausedToChains,
progressBarMessage: event.progressBarMessage,
disabled: event.disableCountdown || !event.pauseBridge,
})
})
} else if (type === 'Swap') {
return PAUSED_CHAINS.map((event) => {
return useMaintenanceCountdownProgress({
fromChainId: swapChainId,
toChainId: null,
startDate: event.startTimePauseChain,
endDate: event.endTimePauseChain,
pausedFromChains: event.pausedFromChains,
pausedToChains: event.pausedToChains,
progressBarMessage: event.progressBarMessage,
disabled: event.disableCountdown || !event.pauseSwap,
})
})
}
}
const activeBridgePause = pausedChainsList
.filter(
(pausedChain) =>
isChainIncluded(pausedChain?.pausedFromChains, [bridgeFromChainId]) ||
isChainIncluded(pausedChain?.pausedToChains, [bridgeToChainId])
)
.reduce((furthestPauseChain, currentChain) => {
const furthestDate = furthestPauseChain?.endTimePauseChain ?? null
const currentDate = currentChain.endTimePauseChain ?? null
const furthestFutureDate = getFurthestFutureDate(
furthestDate,
currentDate
)

/** Pause Bridge Modules */
interface BridgeModulePause {
chainId?: number // Will pause for all chains if undefined
bridgeModuleName: 'SynapseBridge' | 'SynapseRFQ' | 'SynapseCCTP' | 'ALL'
}
if (!furthestDate) return currentChain
return furthestFutureDate === furthestDate
? furthestPauseChain
: currentChain
}, null)

function isValidBridgeModule(
module: any
): module is 'SynapseBridge' | 'SynapseRFQ' | 'SynapseCCTP' | 'ALL' {
return ['SynapseBridge', 'SynapseRFQ', 'SynapseCCTP', 'ALL'].includes(module)
}
const activeSwapPause = pausedChainsList.find(
(pausedChain) =>
isChainIncluded(pausedChain?.pausedFromChains, [swapChainId]) ||
isChainIncluded(pausedChain?.pausedToChains, [swapChainId])
)

export function getBridgeModuleNames(module) {
if (module.bridgeModuleName === 'ALL') {
return ['SynapseRFQ', 'SynapseCCTP', 'SynapseBridge']
}
return [module.bridgeModuleName]
}
const {
isPending: isBridgePaused,
EventCountdownProgressBar: BridgeEventCountdownProgressBar,
} = useEventCountdownProgressBar(
activeBridgePause?.progressBarMessage,
activeBridgePause?.startTimePauseChain,
activeBridgePause?.endTimePauseChain,
activeBridgePause?.disableCountdown
)

const {
isPending: isSwapPaused,
EventCountdownProgressBar: SwapEventCountdownProgressBar,
} = useEventCountdownProgressBar(
activeSwapPause?.progressBarMessage,
activeSwapPause?.startTimePauseChain,
activeSwapPause?.endTimePauseChain,
activeSwapPause?.disableCountdown
)

const BridgeMaintenanceProgressBar = () => BridgeEventCountdownProgressBar
const SwapMaintenanceProgressBar = () => SwapEventCountdownProgressBar

const BridgeMaintenanceWarningMessage = () => (
<MaintenanceWarningMessage
fromChainId={bridgeFromChainId}
toChainId={bridgeToChainId}
startDate={activeBridgePause?.startTimePauseChain}
endDate={activeBridgePause?.endTimePauseChain}
pausedFromChains={activeBridgePause?.pausedFromChains}
pausedToChains={activeBridgePause?.pausedToChains}
warningMessage={activeBridgePause?.inputWarningMessage}
disabled={
activeBridgePause?.disableWarning || !activeBridgePause?.pauseBridge
}
/>
)

const SwapMaintenanceWarningMessage = () => (
<MaintenanceWarningMessage
fromChainId={swapChainId}
toChainId={null}
startDate={activeSwapPause?.startTimePauseChain}
endDate={activeSwapPause?.endTimePauseChain}
pausedFromChains={activeSwapPause?.pausedFromChains}
pausedToChains={activeSwapPause?.pausedToChains}
warningMessage={activeSwapPause?.inputWarningMessage}
disabled={activeSwapPause?.disableWarning || !activeSwapPause?.pauseSwap}
/>
)

export const PAUSED_MODULES: BridgeModulePause[] = pausedBridgeModules.map(
(route) => {
if (!isValidBridgeModule(route.bridgeModuleName)) {
throw new Error(`Invalid module type: ${route.bridgeModuleName}`)
}

return {
...route,
bridgeModuleName: route.bridgeModuleName as
| 'SynapseBridge'
| 'SynapseRFQ'
| 'SynapseCCTP'
| 'ALL',
}
return {
isBridgePaused,
isSwapPaused,
pausedChainsList,
pausedModulesList,
BridgeMaintenanceProgressBar,
BridgeMaintenanceWarningMessage,
SwapMaintenanceProgressBar,
SwapMaintenanceWarningMessage,
}
)
}
Loading

0 comments on commit 3f33dd0

Please sign in to comment.