From b72c8dedfa4df45a79fd78c52405ba50a8eccf8d Mon Sep 17 00:00:00 2001 From: zielvna Date: Wed, 6 Nov 2024 12:03:02 +0100 Subject: [PATCH 1/2] add dynamic fee --- src/components/Header/Header.tsx | 4 + .../HeaderButton/SelectPriorityButton.tsx | 8 +- src/components/Modals/Priority/Priority.tsx | 82 ++++++++++++++++--- .../HeaderWrapper/HeaderWrapper.tsx | 11 ++- 4 files changed, 91 insertions(+), 14 deletions(-) diff --git a/src/components/Header/Header.tsx b/src/components/Header/Header.tsx index c28326552..e3d25ada3 100644 --- a/src/components/Header/Header.tsx +++ b/src/components/Header/Header.tsx @@ -33,6 +33,7 @@ export interface IHeader { onDisconnectWallet: () => void defaultMainnetRPC: string recentPriorityFee: string + recentIsDynamic: boolean onPrioritySave: () => void rpcStatus: RpcStatus } @@ -49,6 +50,7 @@ export const Header: React.FC = ({ onDisconnectWallet, defaultMainnetRPC, recentPriorityFee, + recentIsDynamic, onPrioritySave, rpcStatus }) => { @@ -159,6 +161,7 @@ export const Header: React.FC = ({ {typeOfNetwork === NetworkType.MAINNET ? ( ) : null} @@ -259,6 +262,7 @@ export const Header: React.FC = ({ open={priorityModal} anchorEl={routesModalAnchor} recentPriorityFee={recentPriorityFee} + recentIsDynamic={recentIsDynamic} handleClose={() => { unblurContent() setPriorityModal(false) diff --git a/src/components/HeaderButton/SelectPriorityButton.tsx b/src/components/HeaderButton/SelectPriorityButton.tsx index a2c0bc699..5ffa33804 100644 --- a/src/components/HeaderButton/SelectPriorityButton.tsx +++ b/src/components/HeaderButton/SelectPriorityButton.tsx @@ -7,10 +7,15 @@ import useStyles from './style' export interface Props { recentPriorityFee: string + recentIsDynamic: boolean onPrioritySave: () => void } -export const SelectPriorityButton: React.FC = ({ recentPriorityFee, onPrioritySave }) => { +export const SelectPriorityButton: React.FC = ({ + recentPriorityFee, + recentIsDynamic, + onPrioritySave +}) => { const classes = useStyles() const [anchorEl, setAnchorEl] = useState(null) @@ -40,6 +45,7 @@ export const SelectPriorityButton: React.FC = ({ recentPriorityFee, onPri open={priorityModal} anchorEl={anchorEl} recentPriorityFee={recentPriorityFee} + recentIsDynamic={recentIsDynamic} handleClose={handleClose} onPrioritySave={onPrioritySave} /> diff --git a/src/components/Modals/Priority/Priority.tsx b/src/components/Modals/Priority/Priority.tsx index 950366975..8a8c88cc2 100644 --- a/src/components/Modals/Priority/Priority.tsx +++ b/src/components/Modals/Priority/Priority.tsx @@ -11,6 +11,7 @@ interface Props { handleClose: () => void anchorEl: HTMLButtonElement | null recentPriorityFee: string + recentIsDynamic: boolean onPrioritySave: () => void } @@ -19,6 +20,7 @@ const Priority: React.FC = ({ handleClose, anchorEl, recentPriorityFee, + recentIsDynamic, onPrioritySave }) => { const classes = useStyles() @@ -29,19 +31,31 @@ const Priority: React.FC = ({ const [inputValue, setInputValue] = useState('') const [saveButtonContent, setSaveButtonContent] = useState('Save settings') const [timerId, setTimerId] = useState(0) + const [dynamicFee, setDynamicFee] = useState(null) + const [isDynamic, setIsDynamic] = useState(recentIsDynamic) const maxFee = 2 useEffect(() => { - const index = priorityFeeOptions.findIndex(option => option.saveValue === +recentPriorityFee) + const index = priorityFeeOptions.findIndex(option => + isDynamic ? option.saveValue === 'DYNAMIC' : option.saveValue === +recentPriorityFee + ) setSelectedIndex(index) if (index !== -1) { - setSelectedFee(priorityFeeOptions[index].saveValue) + if (typeof priorityFeeOptions[index].saveValue === 'string') { + setSelectedFee(dynamicFee ?? 0) + } else { + setSelectedFee(priorityFeeOptions[index].saveValue) + } } else { setInputValue(recentPriorityFee) setSelectedFee(+recentPriorityFee) } + + console.log(recentPriorityFee.toString(), recentIsDynamic.toString()) + localStorage.setItem('INVARIANT_MAINNET_PRIORITY_FEE', recentPriorityFee.toString()) + localStorage.setItem('IS_DYNAMIC_FEE', recentIsDynamic.toString()) }, []) useEffect(() => { @@ -71,6 +85,11 @@ const Priority: React.FC = ({ const handleClick = (index: number) => { setInputValue('') + if (index === 4) { + setIsDynamic(true) + } else { + setIsDynamic(false) + } setSelectedIndex(index) } @@ -90,20 +109,55 @@ const Priority: React.FC = ({ } if (+inputValue > 0) { + setIsDynamic(false) setSelectedFee(+inputValue) localStorage.setItem('INVARIANT_MAINNET_PRIORITY_FEE', inputValue) } else { - setSelectedFee(priorityFeeOptions[selectedIndex].saveValue) - localStorage.setItem( - 'INVARIANT_MAINNET_PRIORITY_FEE', - priorityFeeOptions[selectedIndex].saveValue.toString() - ) + if (typeof priorityFeeOptions[selectedIndex].saveValue === 'string') { + setIsDynamic(true) + setSelectedFee(dynamicFee ?? 0) + localStorage.setItem('INVARIANT_MAINNET_PRIORITY_FEE', (dynamicFee ?? 0).toString()) + localStorage.setItem('IS_DYNAMIC_FEE', 'true') + } else { + setIsDynamic(false) + setSelectedFee(priorityFeeOptions[selectedIndex].saveValue) + localStorage.setItem( + 'INVARIANT_MAINNET_PRIORITY_FEE', + priorityFeeOptions[selectedIndex].saveValue.toString() + ) + localStorage.setItem('IS_DYNAMIC_FEE', 'false') + } } onPrioritySave() handleClose() } + useEffect(() => { + const loadDynamicFee = async () => { + const dynamicFee = await getCurrentDynamicFee() + const fee = +(dynamicFee / 10 ** 9).toFixed(9) + setDynamicFee(fee) + + if (isDynamic) { + localStorage.setItem('INVARIANT_MAINNET_PRIORITY_FEE', fee.toString()) + } + } + + void loadDynamicFee() + const interval = setInterval(() => { + void loadDynamicFee() + }, 60 * 1000) + + return () => clearInterval(interval) + }) + + const getCurrentDynamicFee = async () => { + const response = await fetch('https://solanacompass.com/api/fees') + const data = await response.json() + return data['15'].avg + } + const priorityFeeOptions: IPriorityFeeOptions[] = [ { label: 'Normal', value: 0.000005, saveValue: 0, description: '1x Market fee' }, { @@ -113,7 +167,13 @@ const Priority: React.FC = ({ description: '85% percentile fees from last 20 blocks' }, { label: 'High', value: 0.05, saveValue: 0.05, description: '5x Market fee' }, - { label: 'Turbo', value: 0.1, saveValue: 0.1, description: '10x Market fee' } + { label: 'Turbo', value: 0.1, saveValue: 0.1, description: '10x Market fee' }, + { + label: 'Dynamic', + value: 'DYNAMIC', + saveValue: 'DYNAMIC', + description: 'Custom fee based on market demand' + } ] return ( @@ -146,11 +206,11 @@ const Priority: React.FC = ({ diff --git a/src/containers/HeaderWrapper/HeaderWrapper.tsx b/src/containers/HeaderWrapper/HeaderWrapper.tsx index b66102aef..423bf3896 100644 --- a/src/containers/HeaderWrapper/HeaderWrapper.tsx +++ b/src/containers/HeaderWrapper/HeaderWrapper.tsx @@ -13,8 +13,8 @@ import { useLocation } from 'react-router-dom' export interface IPriorityFeeOptions { label: string - value: number - saveValue: number + value: number | string + saveValue: number | string description: string } @@ -59,6 +59,12 @@ export const HeaderWrapper: React.FC = () => { return lastFee === null ? '' : lastFee }, []) + const recentIsDynamic = useMemo(() => { + const lastIsDynamic = localStorage.getItem('IS_DYNAMIC_FEE') + + return lastIsDynamic === null ? true : lastIsDynamic === 'true' + }, []) + const currentRpcStatus = useSelector(rpcStatus) const useDefaultRpc = () => { @@ -110,6 +116,7 @@ export const HeaderWrapper: React.FC = () => { rpc={currentRpc} defaultMainnetRPC={defaultMainnetRPC} recentPriorityFee={recentPriorityFee} + recentIsDynamic={recentIsDynamic} onPrioritySave={() => { dispatch( snackbarsActions.add({ From e1901f45328dcae5307ca9529e1735acd14a3955 Mon Sep 17 00:00:00 2001 From: zielvna Date: Wed, 6 Nov 2024 12:26:38 +0100 Subject: [PATCH 2/2] rename local storage keys of priority fee data --- src/components/Modals/Priority/Priority.tsx | 16 ++++++++-------- src/containers/HeaderWrapper/HeaderWrapper.tsx | 4 ++-- src/store/sagas/positions.ts | 14 +++++++------- src/store/sagas/swap.ts | 4 ++-- 4 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/components/Modals/Priority/Priority.tsx b/src/components/Modals/Priority/Priority.tsx index 8a8c88cc2..0e4928c3b 100644 --- a/src/components/Modals/Priority/Priority.tsx +++ b/src/components/Modals/Priority/Priority.tsx @@ -54,8 +54,8 @@ const Priority: React.FC = ({ } console.log(recentPriorityFee.toString(), recentIsDynamic.toString()) - localStorage.setItem('INVARIANT_MAINNET_PRIORITY_FEE', recentPriorityFee.toString()) - localStorage.setItem('IS_DYNAMIC_FEE', recentIsDynamic.toString()) + localStorage.setItem('INVARIANT_PRIORITY_FEE', recentPriorityFee.toString()) + localStorage.setItem('INVARIANT_IS_DYNAMIC_FEE', recentIsDynamic.toString()) }, []) useEffect(() => { @@ -111,21 +111,21 @@ const Priority: React.FC = ({ if (+inputValue > 0) { setIsDynamic(false) setSelectedFee(+inputValue) - localStorage.setItem('INVARIANT_MAINNET_PRIORITY_FEE', inputValue) + localStorage.setItem('INVARIANT_PRIORITY_FEE', inputValue) } else { if (typeof priorityFeeOptions[selectedIndex].saveValue === 'string') { setIsDynamic(true) setSelectedFee(dynamicFee ?? 0) - localStorage.setItem('INVARIANT_MAINNET_PRIORITY_FEE', (dynamicFee ?? 0).toString()) - localStorage.setItem('IS_DYNAMIC_FEE', 'true') + localStorage.setItem('INVARIANT_PRIORITY_FEE', (dynamicFee ?? 0).toString()) + localStorage.setItem('INVARIANT_IS_DYNAMIC_FEE', 'true') } else { setIsDynamic(false) setSelectedFee(priorityFeeOptions[selectedIndex].saveValue) localStorage.setItem( - 'INVARIANT_MAINNET_PRIORITY_FEE', + 'INVARIANT_PRIORITY_FEE', priorityFeeOptions[selectedIndex].saveValue.toString() ) - localStorage.setItem('IS_DYNAMIC_FEE', 'false') + localStorage.setItem('INVARIANT_IS_DYNAMIC_FEE', 'false') } } @@ -140,7 +140,7 @@ const Priority: React.FC = ({ setDynamicFee(fee) if (isDynamic) { - localStorage.setItem('INVARIANT_MAINNET_PRIORITY_FEE', fee.toString()) + localStorage.setItem('INVARIANT_PRIORITY_FEE', fee.toString()) } } diff --git a/src/containers/HeaderWrapper/HeaderWrapper.tsx b/src/containers/HeaderWrapper/HeaderWrapper.tsx index 423bf3896..6dfbf2e07 100644 --- a/src/containers/HeaderWrapper/HeaderWrapper.tsx +++ b/src/containers/HeaderWrapper/HeaderWrapper.tsx @@ -54,13 +54,13 @@ export const HeaderWrapper: React.FC = () => { }, []) const recentPriorityFee = useMemo(() => { - const lastFee = localStorage.getItem('INVARIANT_MAINNET_PRIORITY_FEE') + const lastFee = localStorage.getItem('INVARIANT_PRIORITY_FEE') return lastFee === null ? '' : lastFee }, []) const recentIsDynamic = useMemo(() => { - const lastIsDynamic = localStorage.getItem('IS_DYNAMIC_FEE') + const lastIsDynamic = localStorage.getItem('INVARIANT_IS_DYNAMIC_FEE') return lastIsDynamic === null ? true : lastIsDynamic === 'true' }, []) diff --git a/src/store/sagas/positions.ts b/src/store/sagas/positions.ts index e605e6eb9..5edc4e2a7 100644 --- a/src/store/sagas/positions.ts +++ b/src/store/sagas/positions.ts @@ -131,7 +131,7 @@ function* handleInitPositionAndPoolWithSOL(action: PayloadAction): Ge combinedTransaction.add(createIx).add(transferIx).add(initIx) - const fee = localStorage.getItem('INVARIANT_MAINNET_PRIORITY_FEE') + const fee = localStorage.getItem('INVARIANT_PRIORITY_FEE') const initPositionTx = yield* call([marketProgram, marketProgram.initPositionTx], { pair: new Pair(data.tokenX, data.tokenY, { @@ -623,7 +623,7 @@ export function* handleInitPosition(action: PayloadAction): Ge let tx: Transaction let poolSigners: Keypair[] = [] - const fee = localStorage.getItem('INVARIANT_MAINNET_PRIORITY_FEE') + const fee = localStorage.getItem('INVARIANT_PRIORITY_FEE') if (action.payload.initPool) { const { transaction, signers } = yield* call( @@ -963,7 +963,7 @@ export function* handleClaimFeeWithSOL(positionIndex: number) { let tx = new Transaction().add(createIx).add(initIx).add(ix).add(unwrapIx) - const fee = localStorage.getItem('INVARIANT_MAINNET_PRIORITY_FEE') + const fee = localStorage.getItem('INVARIANT_PRIORITY_FEE') if (fee) { tx = yield* call([marketProgram, marketProgram.addPriorityFee], solToPriorityFee(+fee), tx) @@ -1125,7 +1125,7 @@ export function* handleClaimFee(action: PayloadAction) { let tx = new Transaction().add(ix) - const fee = localStorage.getItem('INVARIANT_MAINNET_PRIORITY_FEE') + const fee = localStorage.getItem('INVARIANT_PRIORITY_FEE') if (fee) { tx = yield* call([marketProgram, marketProgram.addPriorityFee], solToPriorityFee(+fee), tx) @@ -1324,7 +1324,7 @@ export function* handleClosePositionWithSOL(data: ClosePositionData) { tx = new Transaction().add(createIx).add(initIx).add(ix).add(unwrapIx) } - const fee = localStorage.getItem('INVARIANT_MAINNET_PRIORITY_FEE') + const fee = localStorage.getItem('INVARIANT_PRIORITY_FEE') if (fee) { tx = yield* call([marketProgram, marketProgram.addPriorityFee], solToPriorityFee(+fee), tx) @@ -1517,7 +1517,7 @@ export function* handleClosePosition(action: PayloadAction) { tx = new Transaction().add(ix) } - const fee = localStorage.getItem('INVARIANT_MAINNET_PRIORITY_FEE') + const fee = localStorage.getItem('INVARIANT_PRIORITY_FEE') if (fee) { tx = yield* call([marketProgram, marketProgram.addPriorityFee], solToPriorityFee(+fee), tx) diff --git a/src/store/sagas/swap.ts b/src/store/sagas/swap.ts index 7ece6c1be..8b70718e1 100644 --- a/src/store/sagas/swap.ts +++ b/src/store/sagas/swap.ts @@ -98,7 +98,7 @@ export function* handleSwapWithSOL(): Generator { ? new Transaction().add(createIx).add(transferIx).add(initIx) : new Transaction().add(createIx).add(initIx) - const fee = localStorage.getItem('INVARIANT_MAINNET_PRIORITY_FEE') + const fee = localStorage.getItem('INVARIANT_PRIORITY_FEE') if (fee) { initialTx = yield* call( @@ -423,7 +423,7 @@ export function* handleSwap(): Generator { swapTx.recentBlockhash = blockhash.blockhash swapTx.feePayer = wallet.publicKey - const fee = localStorage.getItem('INVARIANT_MAINNET_PRIORITY_FEE') + const fee = localStorage.getItem('INVARIANT_PRIORITY_FEE') if (fee) { swapTx = yield* call(