diff --git a/codecov.yml b/codecov.yml
index db921b0b00..c865e13f93 100644
--- a/codecov.yml
+++ b/codecov.yml
@@ -9,6 +9,7 @@ ignore:
- "**/styled.tsx"
- "**/constants/**/*"
- "constants/**/*"
+ - "src/dev/*"
coverage:
status:
diff --git a/src/components/TopLevelModals/index.tsx b/src/components/TopLevelModals/index.tsx
index daf41444a8..44bddf3813 100644
--- a/src/components/TopLevelModals/index.tsx
+++ b/src/components/TopLevelModals/index.tsx
@@ -6,11 +6,13 @@ import BaseAnnouncementBanner from 'components/Banner/BaseAnnouncementBanner'
import AddressClaimModal from 'components/claim/AddressClaimModal'
import ConnectedAccountBlocked from 'components/ConnectedAccountBlocked'
import FiatOnrampModal from 'components/FiatOnrampModal'
+import DevFlagsBox from 'dev/DevFlagsBox'
import useAccountRiskCheck from 'hooks/useAccountRiskCheck'
import Bag from 'nft/components/bag/Bag'
import TransactionCompleteModal from 'nft/components/collection/TransactionCompleteModal'
import { useModalIsOpen, useToggleModal } from 'state/application/hooks'
import { ApplicationModal } from 'state/application/reducer'
+import { isDevelopmentEnv, isStagingEnv } from 'utils/env'
export default function TopLevelModals() {
const addressClaimOpen = useModalIsOpen(ApplicationModal.ADDRESS_CLAIM)
@@ -19,6 +21,7 @@ export default function TopLevelModals() {
const { account } = useWeb3React()
useAccountRiskCheck(account)
const accountBlocked = Boolean(blockedAccountModalOpen && account)
+ const shouldShowDevFlags = isDevelopmentEnv() || isStagingEnv()
return (
<>
@@ -31,6 +34,7 @@ export default function TopLevelModals() {
+ {shouldShowDevFlags && }
>
)
}
diff --git a/src/dev/DevFlagsBox.tsx b/src/dev/DevFlagsBox.tsx
new file mode 100644
index 0000000000..f8d60abbac
--- /dev/null
+++ b/src/dev/DevFlagsBox.tsx
@@ -0,0 +1,67 @@
+import { BaseVariant, FeatureFlag, featureFlagSettings as featureFlagSettingsAtom } from 'featureFlags'
+import { useAtomValue } from 'jotai/utils'
+import { useMemo, useState } from 'react'
+import { useGate } from 'statsig-react'
+import styled from 'styled-components'
+import { ThemedText } from 'theme/components'
+import { isDevelopmentEnv, isStagingEnv } from 'utils/env'
+
+const Box = styled.div`
+ position: fixed;
+ bottom: 20px;
+ left: 20px;
+ background-color: ${({ theme }) => theme.surface1};
+ padding: 10px;
+ border: 1px solid ${({ theme }) => theme.accent1};
+ z-index: 1000;
+
+ @media only screen and (max-width: ${({ theme }) => `${theme.breakpoint.md}px`}) {
+ bottom: 70px;
+ }
+`
+const TopBar = styled.div`
+ display: flex;
+ justify-content: space-between;
+`
+const Gate = (flagName: string, featureFlagSettings: Record) => {
+ const gateResult = useGate(flagName)
+ if (gateResult) {
+ const { value: statsigValue }: { value: boolean } = gateResult
+ const flagSetting = featureFlagSettings[flagName]
+ const settingValue: boolean = flagSetting === BaseVariant.Enabled
+ if (flagSetting && statsigValue !== settingValue) {
+ return (
+
+ {flagName}: {flagSetting}
+
+ )
+ }
+ }
+ return null
+}
+
+export default function DevFlagsBox() {
+ const featureFlagsAtom = useAtomValue(featureFlagSettingsAtom)
+ const featureFlags = useMemo(() => Object.values(FeatureFlag), [])
+
+ const overrides = featureFlags.map((flagName) => Gate(flagName, featureFlagsAtom))
+ const hasOverrides = overrides.some((g) => g !== null)
+
+ const [isOpen, setIsOpen] = useState(true)
+ const toggleOpen = () => setIsOpen((open) => !open)
+
+ return (
+
+
+ {isOpen ? 'πΊπ' : 'πΏβοΈ'}
+ {isOpen && (
+
+ {isStagingEnv() && 'Staging build overrides'}
+ {isDevelopmentEnv() && 'Development build overrides'}
+
+ )}
+
+ {isOpen && (hasOverrides ? overrides : No overrides)}
+
+ )
+}