Skip to content

Commit

Permalink
Merge pull request #187 from jediswaplabs/retroboydev/deadline
Browse files Browse the repository at this point in the history
added tx deadline functionality
  • Loading branch information
retroboydev authored Mar 20, 2024
2 parents 8b6da40 + dda69b6 commit 29b1b08
Show file tree
Hide file tree
Showing 7 changed files with 37 additions and 42 deletions.
11 changes: 5 additions & 6 deletions src/components/Settings/TransactionDeadlineSettings/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import Expand from 'components/Expand'
import QuestionHelper from 'components/QuestionHelper'
import Row from 'components/Row'
import { Input, InputContainer } from 'components/Settings/Input'
import { DEFAULT_DEADLINE_FROM_NOW } from 'constants/misc'
import {DEFAULT_DEADLINE_FROM_NOW, MAX_DEADLINE_TIME_IN_SECONDS, MIN_DEADLINE_TIME_IN_SECONDS} from 'constants/misc'
import ms from 'ms'
import React, { useState } from 'react'
import { useUserTransactionTTL } from 'state/user/hooks'
Expand All @@ -13,7 +13,6 @@ enum DeadlineError {
InvalidInput = 'InvalidInput',
}

const THREE_DAYS_IN_SECONDS = ms(`3d`) / 1000
const NUMBERS_ONLY = /^[0-9\b]+$/

export default function TransactionDeadlineSettings() {
Expand All @@ -39,15 +38,15 @@ export default function TransactionDeadlineSettings() {
setDeadlineError(false)

// If the input is empty, set the deadline to the default
if (value.length === 0) {
if (!value.length) {
setDeadline(DEFAULT_DEADLINE_FROM_NOW)
return
}

// Parse user input and set the deadline if valid, error otherwise
try {
const parsed: number = Number.parseInt(value) * 60
if (parsed === 0 || parsed > THREE_DAYS_IN_SECONDS) {
if (parsed < MIN_DEADLINE_TIME_IN_SECONDS || parsed > MAX_DEADLINE_TIME_IN_SECONDS) {
setDeadlineError(DeadlineError.InvalidInput)
} else {
setDeadline(parsed)
Expand All @@ -64,9 +63,9 @@ export default function TransactionDeadlineSettings() {
testId="transaction-deadline-settings"
header={
<Row width="auto">
<ThemedText.BodySecondary>
<ThemedText.BodyPrimary>
<Trans>Transaction deadline</Trans>
</ThemedText.BodySecondary>
</ThemedText.BodyPrimary>
<QuestionHelper
text={<Trans>Your transaction will revert if it is pending for more than this period of time.</Trans>}
/>
Expand Down
1 change: 1 addition & 0 deletions src/components/Settings/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ export default function SettingsTab({
<AnimatedDropdown open={!isUniswapXTrade(trade)}>
<ExpandColumn>
<MaxSlippageSettings autoSlippage={autoSlippage} />
<TransactionDeadlineSettings />
</ExpandColumn>
</AnimatedDropdown>
),
Expand Down
4 changes: 2 additions & 2 deletions src/components/Web3Status/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ const Web3StatusConnected = styled(Web3StatusGeneric)<{
}>`
font-family: 'Avenir LT Std';
background-color: ${({ theme }) => theme.surface5};
border: none;
border: 1px solid transparent;
color: ${({ theme }) => theme.white};
padding: 10px 24px;
`
Expand All @@ -76,7 +76,7 @@ const NetworkContainer = styled.div`
const NetworkSelected = styled(Web3StatusGeneric)<{}>`
font-family: 'Avenir LT Std';
background-color: ${({ theme }) => theme.jediNavyBlue};
border: none;
border: 1px solid transparent;
color: ${({ theme }) => theme.white};
margin-right: 16px;
padding: 10px 24px;
Expand Down
9 changes: 6 additions & 3 deletions src/constants/misc.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
import { Percent } from '@vnaysn/jediswap-sdk-core'
import JSBI from 'jsbi'
import ms from "ms";

export const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'

// TODO(WEB-1984): Convert the deadline to minutes and remove unecessary conversions from
// seconds to minutes in the codebase.
// 10 minutes, denominated in seconds
export const DEFAULT_DEADLINE_FROM_NOW = 60 * 10
export const L2_DEADLINE_FROM_NOW = 60 * 5
// 60 minutes, denominated in seconds
export const DEFAULT_DEADLINE_FROM_NOW = 5 * 60

// transaction popup dismissal amounts
export const DEFAULT_TXN_DISMISS_MS = 10000
export const L2_TXN_DISMISS_MS = 5000

export const MAX_DEADLINE_TIME_IN_SECONDS = ms(`3d`) / 1000
export const MIN_DEADLINE_TIME_IN_SECONDS = ms(`5m`) / 1000

export const BIG_INT_ZERO = JSBI.BigInt(0)

export const BIPS_BASE = 10_000
Expand Down
27 changes: 3 additions & 24 deletions src/hooks/useTransactionDeadline.ts
Original file line number Diff line number Diff line change
@@ -1,36 +1,15 @@
import { BigNumber } from '@ethersproject/bignumber'
import { useAccountDetails } from 'hooks/starknet-react'
import { L2_DEADLINE_FROM_NOW } from 'constants/misc'
import { useMemo } from 'react'
import { useAppSelector } from 'state/hooks'
import { useBlock, useContractRead } from '@starknet-react/core'
import MultiContractABI from 'contracts/multicall/abi.json'
import { MULTICALL_NETWORKS } from 'contracts/multicall'
import { DEFAULT_CHAIN_ID } from 'constants/tokens'

// combines the block timestamp with the user setting to give the deadline that should be used for any submitted transaction
export default function useTransactionDeadline(): BigNumber | undefined {
const { chainId } = useAccountDetails()
const ttl = useAppSelector((state) => state.user.userDeadline)
const blockTimestamp = useCurrentBlockTimestamp()
const currentTimestamp = BigNumber.from(Math.round(Number(new Date()) / 1000).toString())
return useMemo(() => {
if (blockTimestamp && ttl) return BigNumber.from(blockTimestamp).add(ttl)
if (currentTimestamp && ttl) return BigNumber.from(currentTimestamp).add(ttl)
return undefined
}, [blockTimestamp, chainId, ttl])
}

const useCurrentBlockTimestamp = () => {
const { chainId } = useAccountDetails()
const { data: blockTimeStamp } = useContractRead({
functionName: 'get_current_block_timestamp',
args: [],
abi: MultiContractABI,
address: MULTICALL_NETWORKS[chainId ?? DEFAULT_CHAIN_ID],
watch: true,
})

if (!blockTimeStamp) return undefined
const { block_timestamp } = blockTimeStamp as any

return BigNumber.from(block_timestamp.toString())
}, [currentTimestamp, chainId, ttl])
}
5 changes: 1 addition & 4 deletions src/state/user/hooks.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { Percent, Token } from '@vnaysn/jediswap-sdk-core'
import { computePairAddress, Pair } from '@vnaysn/jediswap-sdk-v2'
import { useAccountDetails } from 'hooks/starknet-react'
import { SupportedLocale } from 'constants/locales'
import { L2_DEADLINE_FROM_NOW } from 'constants/misc'
import JSBI from 'jsbi'
import { useCallback, useMemo } from 'react'
import { useAppDispatch, useAppSelector } from 'state/hooks'
Expand Down Expand Up @@ -162,9 +161,7 @@ export function useUserHideClosedPositions(): [boolean, (newHideClosedPositions:
export function useUserTransactionTTL(): [number, (slippage: number) => void] {
const { chainId } = useAccountDetails()
const dispatch = useAppDispatch()
const userDeadline = useAppSelector((state) => state.user.userDeadline)
const onL2 = false
const deadline = onL2 ? L2_DEADLINE_FROM_NOW : userDeadline
const deadline = useAppSelector((state) => state.user.userDeadline)

const setUserDeadline = useCallback(
(userDeadline: number) => {
Expand Down
22 changes: 19 additions & 3 deletions src/state/user/reducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,28 @@ import { deletePersistedConnectionMeta, getPersistedConnectionMeta } from 'conne

import { ConnectionType } from '../../connection/types'
import { SupportedLocale } from '../../constants/locales'
import { DEFAULT_DEADLINE_FROM_NOW } from '../../constants/misc'
import { DEFAULT_DEADLINE_FROM_NOW, MAX_DEADLINE_TIME_IN_SECONDS, MIN_DEADLINE_TIME_IN_SECONDS } from '../../constants/misc'
import { RouterPreference } from '../../state/routing/types'
import { SerializedPair, SerializedToken, SlippageTolerance } from './types'

const selectedWallet = getPersistedConnectionMeta()?.type
const currentTimestamp = () => new Date().getTime()

const userDeadlineLocalStorageKey = 'user-deadline';
const getInitialUserDeadline = () => {
let result = DEFAULT_DEADLINE_FROM_NOW;
const storedUserDeadline = localStorage.getItem(userDeadlineLocalStorageKey)
if (!storedUserDeadline) { return result}
try {
const parsedUserDeadline = Number.parseInt(storedUserDeadline)
if (parsedUserDeadline >= MIN_DEADLINE_TIME_IN_SECONDS && parsedUserDeadline <= MAX_DEADLINE_TIME_IN_SECONDS) {
result = parsedUserDeadline;
}
}
catch (error) {}
return result;
}

export interface UserState {
selectedWallet?: ConnectionType

Expand Down Expand Up @@ -69,7 +84,7 @@ export const initialState: UserState = {
userHideClosedPositions: false,
userSlippageTolerance: SlippageTolerance.Auto,
userSlippageToleranceHasBeenMigratedToAuto: true,
userDeadline: DEFAULT_DEADLINE_FROM_NOW,
userDeadline: getInitialUserDeadline(),
tokens: {},
pairs: {},
timestamp: currentTimestamp(),
Expand Down Expand Up @@ -100,7 +115,8 @@ const userSlice = createSlice({
},
updateUserDeadline(state, action) {
state.userDeadline = action.payload.userDeadline
state.timestamp = currentTimestamp()
state.timestamp = currentTimestamp();
localStorage.setItem(userDeadlineLocalStorageKey, action.payload.userDeadline);
},
updateUserRouterPreference(state, action) {
state.userRouterPreference = action.payload.userRouterPreference
Expand Down

0 comments on commit 29b1b08

Please sign in to comment.