Commit c560b943 authored by eddie's avatar eddie Committed by GitHub

feat: create feature flag for swap widget (#5909)

* feat: create feature flag for swap widget

* feat: add new flag to modal

* fix: missing defaultField usage
parent 93a4f002
...@@ -3,6 +3,7 @@ import { useFiatOnrampFlag } from 'featureFlags/flags/fiatOnramp' ...@@ -3,6 +3,7 @@ import { useFiatOnrampFlag } from 'featureFlags/flags/fiatOnramp'
import { NftListV2Variant, useNftListV2Flag } from 'featureFlags/flags/nftListV2' import { NftListV2Variant, useNftListV2Flag } from 'featureFlags/flags/nftListV2'
import { PayWithAnyTokenVariant, usePayWithAnyTokenFlag } from 'featureFlags/flags/payWithAnyToken' import { PayWithAnyTokenVariant, usePayWithAnyTokenFlag } from 'featureFlags/flags/payWithAnyToken'
import { Permit2Variant, usePermit2Flag } from 'featureFlags/flags/permit2' import { Permit2Variant, usePermit2Flag } from 'featureFlags/flags/permit2'
import { SwapWidgetVariant, useSwapWidgetFlag } from 'featureFlags/flags/swapWidget'
import { TraceJsonRpcVariant, useTraceJsonRpcFlag } from 'featureFlags/flags/traceJsonRpc' import { TraceJsonRpcVariant, useTraceJsonRpcFlag } from 'featureFlags/flags/traceJsonRpc'
import { useAtomValue, useUpdateAtom } from 'jotai/utils' import { useAtomValue, useUpdateAtom } from 'jotai/utils'
import { Children, PropsWithChildren, ReactElement, ReactNode, useCallback, useState } from 'react' import { Children, PropsWithChildren, ReactElement, ReactNode, useCallback, useState } from 'react'
...@@ -229,6 +230,12 @@ export default function FeatureFlagModal() { ...@@ -229,6 +230,12 @@ export default function FeatureFlagModal() {
featureFlag={FeatureFlag.payWithAnyToken} featureFlag={FeatureFlag.payWithAnyToken}
label="Pay With Any Token" label="Pay With Any Token"
/> />
<FeatureFlagOption
variant={SwapWidgetVariant}
value={useSwapWidgetFlag()}
featureFlag={FeatureFlag.swapWidget}
label="Swap Widget"
/>
<FeatureFlagGroup name="Debug"> <FeatureFlagGroup name="Debug">
<FeatureFlagOption <FeatureFlagOption
variant={TraceJsonRpcVariant} variant={TraceJsonRpcVariant}
......
import { WidgetSkeleton } from 'components/Widget' import { WidgetSkeleton } from 'components/Widget'
import { WIDGET_WIDTH } from 'components/Widget' import { DEFAULT_WIDGET_WIDTH } from 'components/Widget'
import { ArrowLeft } from 'react-feather' import { ArrowLeft } from 'react-feather'
import { useParams } from 'react-router-dom' import { useParams } from 'react-router-dom'
import styled, { useTheme } from 'styled-components/macro' import styled, { useTheme } from 'styled-components/macro'
...@@ -44,7 +44,7 @@ export const RightPanel = styled.div` ...@@ -44,7 +44,7 @@ export const RightPanel = styled.div`
display: none; display: none;
flex-direction: column; flex-direction: column;
gap: 20px; gap: 20px;
width: ${WIDGET_WIDTH}px; width: ${DEFAULT_WIDGET_WIDTH}px;
@media screen and (min-width: ${({ theme }) => theme.breakpoint.lg}px) { @media screen and (min-width: ${({ theme }) => theme.breakpoint.lg}px) {
display: flex; display: flex;
......
...@@ -2,6 +2,7 @@ import { Trans } from '@lingui/macro' ...@@ -2,6 +2,7 @@ import { Trans } from '@lingui/macro'
import { Trace } from '@uniswap/analytics' import { Trace } from '@uniswap/analytics'
import { InterfacePageName } from '@uniswap/analytics-events' import { InterfacePageName } from '@uniswap/analytics-events'
import { Currency } from '@uniswap/sdk-core' import { Currency } from '@uniswap/sdk-core'
import { Field } from '@uniswap/widgets'
import { useWeb3React } from '@web3-react/core' import { useWeb3React } from '@web3-react/core'
import CurrencyLogo from 'components/Logo/CurrencyLogo' import CurrencyLogo from 'components/Logo/CurrencyLogo'
import { AboutSection } from 'components/Tokens/TokenDetails/About' import { AboutSection } from 'components/Tokens/TokenDetails/About'
...@@ -223,6 +224,7 @@ export default function TokenDetails({ ...@@ -223,6 +224,7 @@ export default function TokenDetails({
<RightPanel> <RightPanel>
<Widget <Widget
token={token ?? undefined} token={token ?? undefined}
defaultField={Field.OUTPUT}
onTokenChange={navigateToWidgetSelectedToken} onTokenChange={navigateToWidgetSelectedToken}
onReviewSwapClick={onReviewSwapClick} onReviewSwapClick={onReviewSwapClick}
/> />
......
...@@ -10,6 +10,7 @@ import { Currency, TradeType } from '@uniswap/sdk-core' ...@@ -10,6 +10,7 @@ import { Currency, TradeType } from '@uniswap/sdk-core'
import { import {
AddEthereumChainParameter, AddEthereumChainParameter,
EMPTY_TOKEN_LIST, EMPTY_TOKEN_LIST,
Field,
OnReviewSwapClick, OnReviewSwapClick,
SwapWidget, SwapWidget,
SwapWidgetSkeleton, SwapWidgetSkeleton,
...@@ -36,7 +37,7 @@ import { useSyncWidgetSettings } from './settings' ...@@ -36,7 +37,7 @@ import { useSyncWidgetSettings } from './settings'
import { DARK_THEME, LIGHT_THEME } from './theme' import { DARK_THEME, LIGHT_THEME } from './theme'
import { useSyncWidgetTransactions } from './transactions' import { useSyncWidgetTransactions } from './transactions'
export const WIDGET_WIDTH = 360 export const DEFAULT_WIDGET_WIDTH = 360
const WIDGET_ROUTER_URL = 'https://api.uniswap.org/v1/' const WIDGET_ROUTER_URL = 'https://api.uniswap.org/v1/'
...@@ -46,15 +47,23 @@ function useWidgetTheme() { ...@@ -46,15 +47,23 @@ function useWidgetTheme() {
interface WidgetProps { interface WidgetProps {
token?: Currency token?: Currency
width?: number | string
defaultField: Field
onTokenChange?: (token: Currency) => void onTokenChange?: (token: Currency) => void
onReviewSwapClick?: OnReviewSwapClick onReviewSwapClick?: OnReviewSwapClick
} }
export default function Widget({ token, onTokenChange, onReviewSwapClick }: WidgetProps) { export default function Widget({
token,
width = DEFAULT_WIDGET_WIDTH,
defaultField,
onTokenChange,
onReviewSwapClick,
}: WidgetProps) {
const { connector, provider } = useWeb3React() const { connector, provider } = useWeb3React()
const locale = useActiveLocale() const locale = useActiveLocale()
const theme = useWidgetTheme() const theme = useWidgetTheme()
const { inputs, tokenSelector } = useSyncWidgetInputs({ token, onTokenChange }) const { inputs, tokenSelector } = useSyncWidgetInputs({ token, onTokenChange, defaultField })
const { settings } = useSyncWidgetSettings() const { settings } = useSyncWidgetSettings()
const { transactions } = useSyncWidgetTransactions() const { transactions } = useSyncWidgetTransactions()
...@@ -159,7 +168,7 @@ export default function Widget({ token, onTokenChange, onReviewSwapClick }: Widg ...@@ -159,7 +168,7 @@ export default function Widget({ token, onTokenChange, onReviewSwapClick }: Widg
routerUrl={WIDGET_ROUTER_URL} routerUrl={WIDGET_ROUTER_URL}
locale={locale} locale={locale}
theme={theme} theme={theme}
width={WIDGET_WIDTH} width={width}
// defaultChainId is excluded - it is always inferred from the passed provider // defaultChainId is excluded - it is always inferred from the passed provider
onConnectWalletClick={onConnectWalletClick} onConnectWalletClick={onConnectWalletClick}
provider={provider} provider={provider}
...@@ -182,5 +191,5 @@ export default function Widget({ token, onTokenChange, onReviewSwapClick }: Widg ...@@ -182,5 +191,5 @@ export default function Widget({ token, onTokenChange, onReviewSwapClick }: Widg
export function WidgetSkeleton() { export function WidgetSkeleton() {
const theme = useWidgetTheme() const theme = useWidgetTheme()
return <SwapWidgetSkeleton theme={theme} width={WIDGET_WIDTH} /> return <SwapWidgetSkeleton theme={theme} width={DEFAULT_WIDGET_WIDTH} />
} }
...@@ -21,26 +21,29 @@ function includesDefaultToken(tokens: SwapTokens) { ...@@ -21,26 +21,29 @@ function includesDefaultToken(tokens: SwapTokens) {
*/ */
export function useSyncWidgetInputs({ export function useSyncWidgetInputs({
token, token,
defaultField,
onTokenChange, onTokenChange,
}: { }: {
token?: Currency token?: Currency
defaultField: Field
onTokenChange?: (token: Currency) => void onTokenChange?: (token: Currency) => void
}) { }) {
const trace = useTrace({ section: InterfaceSectionName.WIDGET }) const trace = useTrace({ section: InterfaceSectionName.WIDGET })
const [type, setType] = useState<SwapValue['type']>(TradeType.EXACT_INPUT) const [type, setType] = useState<SwapValue['type']>(TradeType.EXACT_INPUT)
const [amount, setAmount] = useState<SwapValue['amount']>(EMPTY_AMOUNT) const [amount, setAmount] = useState<SwapValue['amount']>(EMPTY_AMOUNT)
const [tokens, setTokens] = useState<SwapTokens>({ [Field.OUTPUT]: token, default: token }) const [tokens, setTokens] = useState<SwapTokens>({ [defaultField]: token, default: token })
useEffect(() => { useEffect(() => {
setTokens((tokens) => { setTokens((tokens) => {
const update = { ...tokens, default: token } const update = { ...tokens, default: token }
if (!includesDefaultToken(update)) { if (!includesDefaultToken(update)) {
return { [Field.OUTPUT]: update.default, default: update.default } return { [defaultField]: update.default, default: update.default }
} }
return update return update
}) })
}, [token]) }, [defaultField, token])
const onAmountChange = useCallback( const onAmountChange = useCallback(
(field: Field, amount: string, origin?: 'max') => { (field: Field, amount: string, origin?: 'max') => {
......
...@@ -4,4 +4,5 @@ export enum FeatureFlag { ...@@ -4,4 +4,5 @@ export enum FeatureFlag {
permit2 = 'permit2', permit2 = 'permit2',
nftListV2 = 'nftListV2', nftListV2 = 'nftListV2',
payWithAnyToken = 'payWithAnyToken', payWithAnyToken = 'payWithAnyToken',
swapWidget = 'swapWidget',
} }
import { BaseVariant, FeatureFlag, useBaseFlag } from '../index'
export function useSwapWidgetFlag(): BaseVariant {
return useBaseFlag(FeatureFlag.swapWidget, BaseVariant.Control)
}
export function useSwapWidgetEnabled(): boolean {
return useSwapWidgetFlag() === BaseVariant.Enabled
}
export { BaseVariant as SwapWidgetVariant }
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment