Skip to content

Commit

Permalink
Separate slippage tolerance settings between Liquidity Actions & Swap (
Browse files Browse the repository at this point in the history
…#2388)

* Add state user / poolSlippageTolerance

Remove dummies

Minor

Update setting slippage

Separate slippage

* KEP-1931 Separate degen mode

* Update logic more clear
  • Loading branch information
neikop authored Nov 23, 2023
1 parent 13318cf commit 7f539fa
Show file tree
Hide file tree
Showing 9 changed files with 176 additions and 38 deletions.
5 changes: 2 additions & 3 deletions src/components/SwapForm/SlippageSetting.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,12 @@ type Props = {
isStablePairSwap: boolean
rightComponent?: ReactNode
tooltip?: ReactNode
isCrossChain?: boolean
}
const SlippageSetting = ({ isStablePairSwap, rightComponent, tooltip, isCrossChain }: Props) => {
const SlippageSetting = ({ isStablePairSwap, rightComponent, tooltip }: Props) => {
const theme = useTheme()
const [expanded, setExpanded] = useState(false)

const { setRawSlippage, rawSlippage, isSlippageControlPinned } = useSlippageSettingByPage(isCrossChain)
const { rawSlippage, setRawSlippage, isSlippageControlPinned } = useSlippageSettingByPage()
const defaultRawSlippage = getDefaultSlippage(isStablePairSwap)

const isWarningSlippage = checkWarningSlippage(rawSlippage, isStablePairSwap)
Expand Down
6 changes: 2 additions & 4 deletions src/components/swapv2/SwapSettingsPanel/SlippageSetting.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,10 @@ const Message = styled.div`

type Props = {
shouldShowPinButton?: boolean
isCrossChain?: boolean
}

const SlippageSetting: React.FC<Props> = ({ shouldShowPinButton = true, isCrossChain = false }) => {
const { rawSlippage, setRawSlippage, isSlippageControlPinned, togglePinSlippage } =
useSlippageSettingByPage(isCrossChain)
const SlippageSetting: React.FC<Props> = ({ shouldShowPinButton = true }) => {
const { rawSlippage, setRawSlippage, isSlippageControlPinned, togglePinSlippage } = useSlippageSettingByPage()

const isStablePairSwap = useCheckStablePairSwap()
const slippageStatus = checkRangeSlippage(rawSlippage, isStablePairSwap)
Expand Down
2 changes: 1 addition & 1 deletion src/components/swapv2/SwapSettingsPanel/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ const SettingsPanel: React.FC<Props> = ({
<Trans>Advanced Settings</Trans>
</span>

<SlippageSetting isCrossChain={isCrossChainPage} />
<SlippageSetting />
{isSwapPage && <TransactionTimeLimitSetting />}
<DegenModeSetting showConfirmation={showConfirmation} setShowConfirmation={setShowConfirmation} />
{isSwapPage && (
Expand Down
16 changes: 16 additions & 0 deletions src/hooks/usePageLocation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { useLocation } from 'react-router-dom'

import { APP_PATHS } from 'constants/index'

const SWAP_PAGE_URLS = [APP_PATHS.SWAP, APP_PATHS.PARTNER_SWAP, APP_PATHS.LIMIT, APP_PATHS.CROSS_CHAIN]

const usePageLocation = () => {
const location = useLocation()

return {
isSwapPage: SWAP_PAGE_URLS.some(url => location.pathname.startsWith(url)),
isCrossChain: location.pathname.startsWith(APP_PATHS.CROSS_CHAIN),
}
}

export default usePageLocation
1 change: 0 additions & 1 deletion src/pages/CrossChain/SwapForm/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,6 @@ export default function SwapForm() {
</div>

<SlippageSetting
isCrossChain
isStablePairSwap={isStablePairSwap}
tooltip={
<Text>
Expand Down
6 changes: 6 additions & 0 deletions src/state/user/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,17 @@ export interface SerializedPair {
export const updateUserDegenMode = createAction<{ userDegenMode: boolean; isStablePairSwap: boolean }>(
'user/updateUserDegenMode',
)
export const updatePoolDegenMode = createAction<{ poolDegenMode: boolean; isStablePairSwap: boolean }>(
'user/updatePoolDegenMode',
)
export const toggleUseAggregatorForZap = createAction('user/toggleUseAggregatorForZap')
export const updateUserLocale = createAction<{ userLocale: SupportedLocale }>('user/updateUserLocale')
export const updateUserSlippageTolerance = createAction<{ userSlippageTolerance: number }>(
'user/updateUserSlippageTolerance',
)
export const updatePoolSlippageTolerance = createAction<{ poolSlippageTolerance: number }>(
'user/updatePoolSlippageTolerance',
)

export const updateUserDeadline = createAction<{ userDeadline: number }>('user/updateUserDeadline')
export const addSerializedToken = createAction<{ serializedToken: SerializedToken }>('user/addSerializedToken')
Expand Down
80 changes: 68 additions & 12 deletions src/state/user/hooks.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
useStaticFeeFactoryContract,
} from 'hooks/useContract'
import useDebounce from 'hooks/useDebounce'
import usePageLocation from 'hooks/usePageLocation'
import { ParticipantInfo, ParticipantStatus } from 'pages/TrueSightV2/types'
import { AppDispatch, AppState } from 'state'
import { useKyberSwapConfig } from 'state/application/hooks'
Expand Down Expand Up @@ -43,6 +44,8 @@ import {
toggleTradeRoutes,
toggleUseAggregatorForZap,
updateAcceptedTermVersion,
updatePoolDegenMode,
updatePoolSlippageTolerance,
updateTokenAnalysisSettings,
updateUserDeadline,
updateUserDegenMode,
Expand Down Expand Up @@ -121,15 +124,38 @@ export function useIsAcceptedTerm(): [boolean, (isAcceptedTerm: boolean) => void
}

export function useDegenModeManager(): [boolean, () => void] {
const [swapDegenMode, toggleSwapDegenMode] = useSwapDegenMode()
const [poolDegenMode, togglePoolDegenMode] = usePoolDegenMode()

const { isSwapPage } = usePageLocation()
if (isSwapPage) {
return [swapDegenMode, toggleSwapDegenMode]
}
return [poolDegenMode, togglePoolDegenMode]
}

export function useSwapDegenMode(): [boolean, () => void] {
const dispatch = useDispatch<AppDispatch>()
const degenMode = useSelector<AppState, AppState['user']['userDegenMode']>(state => state.user.userDegenMode)
const isStablePairSwap = useCheckStablePairSwap()

const toggleSetDegenMode = useCallback(() => {
dispatch(updateUserDegenMode({ userDegenMode: !degenMode, isStablePairSwap }))
}, [degenMode, dispatch, isStablePairSwap])
const userDegenMode = useSelector<AppState, AppState['user']['userDegenMode']>(state => state.user.userDegenMode)
const toggleUserDegenMode = useCallback(() => {
dispatch(updateUserDegenMode({ userDegenMode: !userDegenMode, isStablePairSwap }))
}, [userDegenMode, dispatch, isStablePairSwap])

return [degenMode, toggleSetDegenMode]
return [userDegenMode, toggleUserDegenMode]
}

export function usePoolDegenMode(): [boolean, () => void] {
const dispatch = useDispatch<AppDispatch>()
const isStablePairSwap = useCheckStablePairSwap()

const poolDegenMode = useSelector<AppState, AppState['user']['poolDegenMode']>(state => state.user.poolDegenMode)
const togglePoolDegenMode = useCallback(() => {
dispatch(updatePoolDegenMode({ poolDegenMode: !poolDegenMode, isStablePairSwap }))
}, [poolDegenMode, dispatch, isStablePairSwap])

return [poolDegenMode, togglePoolDegenMode]
}

export function useAggregatorForZapSetting(): [boolean, () => void] {
Expand All @@ -146,21 +172,44 @@ export function useAggregatorForZapSetting(): [boolean, () => void] {
}

export function useUserSlippageTolerance(): [number, (slippage: number) => void] {
const [swapSlippageTolerance, setSwapSlippageTolerance] = useSwapSlippageTolerance()
const [poolSlippageTolerance, setPoolSlippageTolerance] = usePoolSlippageTolerance()

const { isSwapPage } = usePageLocation()
if (isSwapPage) {
return [swapSlippageTolerance, setSwapSlippageTolerance]
}
return [poolSlippageTolerance, setPoolSlippageTolerance]
}

export function useSwapSlippageTolerance(): [number, (slippage: number) => void] {
const dispatch = useDispatch<AppDispatch>()
const userSlippageTolerance = useSelector<AppState, AppState['user']['userSlippageTolerance']>(state => {
return state.user.userSlippageTolerance
})

const setUserSlippageTolerance = useCallback(
(userSlippageTolerance: number) => {
dispatch(updateUserSlippageTolerance({ userSlippageTolerance }))
},
[dispatch],
)

return [userSlippageTolerance, setUserSlippageTolerance]
}

export function usePoolSlippageTolerance(): [number, (slippage: number) => void] {
const dispatch = useDispatch<AppDispatch>()
const poolSlippageTolerance = useSelector<AppState, AppState['user']['poolSlippageTolerance']>(state => {
return state.user.poolSlippageTolerance
})
const setPoolSlippageTolerance = useCallback(
(poolSlippageTolerance: number) => {
dispatch(updatePoolSlippageTolerance({ poolSlippageTolerance }))
},
[dispatch],
)
return [poolSlippageTolerance, setPoolSlippageTolerance]
}

export function useUserTransactionTTL(): [number, (slippage: number) => void] {
const dispatch = useDispatch<AppDispatch>()
const userDeadline = useSelector<AppState, AppState['user']['userDeadline']>(state => {
Expand Down Expand Up @@ -461,10 +510,12 @@ export const useCrossChainSetting = () => {
return { setting, setExpressExecutionMode, setRawSlippage, toggleSlippageControlPinned }
}

export const useSlippageSettingByPage = (isCrossChain = false) => {
export const useSlippageSettingByPage = () => {
const dispatch = useDispatch()
const { isCrossChain } = usePageLocation()
const [rawSlippageTolerance, setRawSlippageTolerance] = useUserSlippageTolerance()

const isPinSlippageSwap = useAppSelector(state => state.user.isSlippageControlPinned)
const [rawSlippageSwap, setRawSlippageSwap] = useUserSlippageTolerance()
const togglePinSlippageSwap = () => {
dispatch(pinSlippageControl(!isSlippageControlPinned))
}
Expand All @@ -475,12 +526,17 @@ export const useSlippageSettingByPage = (isCrossChain = false) => {
toggleSlippageControlPinned: togglePinnedSlippageCrossChain,
} = useCrossChainSetting()

const rawSlippage = isCrossChain ? rawSlippageSwapCrossChain : rawSlippageTolerance
const setRawSlippage = isCrossChain ? setRawSlippageCrossChain : setRawSlippageTolerance
const isSlippageControlPinned = isCrossChain ? isPinSlippageCrossChain : isPinSlippageSwap
const rawSlippage = isCrossChain ? rawSlippageSwapCrossChain : rawSlippageSwap
const setRawSlippage = isCrossChain ? setRawSlippageCrossChain : setRawSlippageSwap
const togglePinSlippage = isCrossChain ? togglePinnedSlippageCrossChain : togglePinSlippageSwap

return { setRawSlippage, rawSlippage, isSlippageControlPinned, togglePinSlippage }
return {
rawSlippage,
setRawSlippage,
isSlippageControlPinned,
togglePinSlippage,
}
}

const participantDefault = {
Expand Down
38 changes: 34 additions & 4 deletions src/state/user/reducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ import {
toggleUseAggregatorForZap,
updateAcceptedTermVersion,
updateChainId,
updatePoolDegenMode,
updatePoolSlippageTolerance,
updateTokenAnalysisSettings,
updateUserDeadline,
updateUserDegenMode,
Expand Down Expand Up @@ -64,10 +66,13 @@ export interface UserState {

userDegenMode: boolean
userDegenModeAutoDisableTimestamp: number
poolDegenMode: boolean
poolDegenModeAutoDisableTimestamp: number
useAggregatorForZap: boolean

// user defined slippage tolerance in bips, used in all txns
userSlippageTolerance: number
// user defined slippage tolerance in bips, used in SWAP page
userSlippageTolerance: number // For SWAP page
poolSlippageTolerance: number // For POOL and other pages

// deadline set by user in minutes, used in all txns
userDeadline: number
Expand Down Expand Up @@ -149,11 +154,14 @@ export const CROSS_CHAIN_SETTING_DEFAULT = {
}

const initialState: UserState = {
userDegenMode: false,
useAggregatorForZap: true,
userDegenMode: false, // For SWAP page
userDegenModeAutoDisableTimestamp: 0,
poolDegenMode: false, // For POOL and other pages
poolDegenModeAutoDisableTimestamp: 0,
useAggregatorForZap: true,
userLocale: null,
userSlippageTolerance: INITIAL_ALLOWED_SLIPPAGE,
poolSlippageTolerance: INITIAL_ALLOWED_SLIPPAGE,
userDeadline: DEFAULT_DEADLINE_FROM_NOW,
tokens: {},
pairs: {},
Expand Down Expand Up @@ -230,6 +238,24 @@ export default createReducer(initialState, builder =>
}
state.timestamp = currentTimestamp()
})
.addCase(updatePoolDegenMode, (state, action) => {
state.poolDegenMode = action.payload.poolDegenMode
if (action.payload.poolDegenMode) {
state.poolDegenModeAutoDisableTimestamp = Date.now() + AUTO_DISABLE_DEGEN_MODE_MINUTES * 60 * 1000
} else {
// If max slippage <= 19.99%, no need update slippage.
if (state.poolSlippageTolerance <= MAX_NORMAL_SLIPPAGE_IN_BIPS) {
return
}
// Else, update to default slippage.
if (action.payload.isStablePairSwap) {
state.poolSlippageTolerance = Math.min(state.poolSlippageTolerance, DEFAULT_SLIPPAGE_STABLE_PAIR_SWAP)
} else {
state.poolSlippageTolerance = Math.min(state.poolSlippageTolerance, DEFAULT_SLIPPAGE)
}
}
state.timestamp = currentTimestamp()
})
.addCase(updateUserLocale, (state, action) => {
state.userLocale = action.payload.userLocale
state.timestamp = currentTimestamp()
Expand All @@ -238,6 +264,10 @@ export default createReducer(initialState, builder =>
state.userSlippageTolerance = action.payload.userSlippageTolerance
state.timestamp = currentTimestamp()
})
.addCase(updatePoolSlippageTolerance, (state, action) => {
state.poolSlippageTolerance = action.payload.poolSlippageTolerance
state.timestamp = currentTimestamp()
})
.addCase(updateUserDeadline, (state, action) => {
state.userDeadline = action.payload.userDeadline
state.timestamp = currentTimestamp()
Expand Down
60 changes: 47 additions & 13 deletions src/state/user/updater.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,31 +5,65 @@ import { useInterval } from 'react-use'
import { DEFAULT_SLIPPAGE, DEFAULT_SLIPPAGE_STABLE_PAIR_SWAP, MAX_NORMAL_SLIPPAGE_IN_BIPS } from 'constants/index'
import { AppDispatch, AppState } from 'state/index'
import { useCheckStablePairSwap } from 'state/swap/hooks'
import { useUserSlippageTolerance } from 'state/user/hooks'
import { usePoolSlippageTolerance, useSwapSlippageTolerance } from 'state/user/hooks'

import { updateUserDegenMode } from './actions'
import { updatePoolDegenMode, updateUserDegenMode } from './actions'

export default function Updater(): null {
const dispatch = useDispatch<AppDispatch>()
const degenMode = useSelector<AppState, AppState['user']['userDegenMode']>(state => state.user.userDegenMode)
const userDegenModeAutoDisableTimestamp = useSelector<
const isStablePairSwap = useCheckStablePairSwap()

const swapDegenMode = useSelector<AppState, AppState['user']['userDegenMode']>(state => state.user.userDegenMode)
const swapDegenModeAutoDisableTimestamp = useSelector<
AppState,
AppState['user']['userDegenModeAutoDisableTimestamp']
>(state => state.user.userDegenModeAutoDisableTimestamp)
const isStablePairSwap = useCheckStablePairSwap()
const [rawSlippage, setRawSlippage] = useUserSlippageTolerance()

const autoDisableDegenMode = useCallback(() => {
if (degenMode && userDegenModeAutoDisableTimestamp <= Date.now()) {
const poolDegenMode = useSelector<AppState, AppState['user']['poolDegenMode']>(state => state.user.poolDegenMode)
const poolDegenModeAutoDisableTimestamp = useSelector<
AppState,
AppState['user']['poolDegenModeAutoDisableTimestamp']
>(state => state.user.poolDegenModeAutoDisableTimestamp)

const [swapSlippageTolerance, setSwapSlippageTolerance] = useSwapSlippageTolerance()
const [poolSlippageTolerance, setPoolSlippageTolerance] = usePoolSlippageTolerance()

const autoDisableSwapDegenMode = useCallback(() => {
if (swapDegenMode && swapDegenModeAutoDisableTimestamp <= Date.now()) {
dispatch(updateUserDegenMode({ userDegenMode: false, isStablePairSwap }))
if (rawSlippage > MAX_NORMAL_SLIPPAGE_IN_BIPS) {
if (isStablePairSwap) setRawSlippage(DEFAULT_SLIPPAGE_STABLE_PAIR_SWAP)
else setRawSlippage(DEFAULT_SLIPPAGE)
if (swapSlippageTolerance > MAX_NORMAL_SLIPPAGE_IN_BIPS) {
if (isStablePairSwap) setSwapSlippageTolerance(DEFAULT_SLIPPAGE_STABLE_PAIR_SWAP)
else setSwapSlippageTolerance(DEFAULT_SLIPPAGE)
}
}
}, [
swapDegenMode,
dispatch,
isStablePairSwap,
swapSlippageTolerance,
setSwapSlippageTolerance,
swapDegenModeAutoDisableTimestamp,
])

const autoDisablePoolDegenMode = useCallback(() => {
if (poolDegenMode && poolDegenModeAutoDisableTimestamp <= Date.now()) {
dispatch(updatePoolDegenMode({ poolDegenMode: false, isStablePairSwap }))
if (poolSlippageTolerance > MAX_NORMAL_SLIPPAGE_IN_BIPS) {
if (isStablePairSwap) setPoolSlippageTolerance(DEFAULT_SLIPPAGE_STABLE_PAIR_SWAP)
else setPoolSlippageTolerance(DEFAULT_SLIPPAGE)
}
}
}, [degenMode, dispatch, isStablePairSwap, rawSlippage, setRawSlippage, userDegenModeAutoDisableTimestamp])
}, [
poolDegenMode,
dispatch,
isStablePairSwap,
poolSlippageTolerance,
setPoolSlippageTolerance,
poolDegenModeAutoDisableTimestamp,
])

useInterval(autoDisableDegenMode, 1_000)
useInterval(autoDisableSwapDegenMode, 1_000)
useInterval(autoDisablePoolDegenMode, 1_000)

return null
}

0 comments on commit 7f539fa

Please sign in to comment.