Skip to content

Commit

Permalink
Merge pull request #759 from invariant-labs/add-dynamic-fee
Browse files Browse the repository at this point in the history
add dynamic fee
  • Loading branch information
wojciech-cichocki authored Nov 6, 2024
2 parents 0e5c38c + e1901f4 commit 282b6c8
Show file tree
Hide file tree
Showing 6 changed files with 102 additions and 25 deletions.
4 changes: 4 additions & 0 deletions src/components/Header/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ export interface IHeader {
onDisconnectWallet: () => void
defaultMainnetRPC: string
recentPriorityFee: string
recentIsDynamic: boolean
onPrioritySave: () => void
rpcStatus: RpcStatus
}
Expand All @@ -49,6 +50,7 @@ export const Header: React.FC<IHeader> = ({
onDisconnectWallet,
defaultMainnetRPC,
recentPriorityFee,
recentIsDynamic,
onPrioritySave,
rpcStatus
}) => {
Expand Down Expand Up @@ -159,6 +161,7 @@ export const Header: React.FC<IHeader> = ({
{typeOfNetwork === NetworkType.MAINNET ? (
<SelectPriorityButton
recentPriorityFee={recentPriorityFee}
recentIsDynamic={recentIsDynamic}
onPrioritySave={onPrioritySave}
/>
) : null}
Expand Down Expand Up @@ -259,6 +262,7 @@ export const Header: React.FC<IHeader> = ({
open={priorityModal}
anchorEl={routesModalAnchor}
recentPriorityFee={recentPriorityFee}
recentIsDynamic={recentIsDynamic}
handleClose={() => {
unblurContent()
setPriorityModal(false)
Expand Down
8 changes: 7 additions & 1 deletion src/components/HeaderButton/SelectPriorityButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,15 @@ import useStyles from './style'

export interface Props {
recentPriorityFee: string
recentIsDynamic: boolean
onPrioritySave: () => void
}

export const SelectPriorityButton: React.FC<Props> = ({ recentPriorityFee, onPrioritySave }) => {
export const SelectPriorityButton: React.FC<Props> = ({
recentPriorityFee,
recentIsDynamic,
onPrioritySave
}) => {
const classes = useStyles()

const [anchorEl, setAnchorEl] = useState<HTMLButtonElement | null>(null)
Expand Down Expand Up @@ -40,6 +45,7 @@ export const SelectPriorityButton: React.FC<Props> = ({ recentPriorityFee, onPri
open={priorityModal}
anchorEl={anchorEl}
recentPriorityFee={recentPriorityFee}
recentIsDynamic={recentIsDynamic}
handleClose={handleClose}
onPrioritySave={onPrioritySave}
/>
Expand Down
84 changes: 72 additions & 12 deletions src/components/Modals/Priority/Priority.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ interface Props {
handleClose: () => void
anchorEl: HTMLButtonElement | null
recentPriorityFee: string
recentIsDynamic: boolean
onPrioritySave: () => void
}

Expand All @@ -19,6 +20,7 @@ const Priority: React.FC<Props> = ({
handleClose,
anchorEl,
recentPriorityFee,
recentIsDynamic,
onPrioritySave
}) => {
const classes = useStyles()
Expand All @@ -29,19 +31,31 @@ const Priority: React.FC<Props> = ({
const [inputValue, setInputValue] = useState('')
const [saveButtonContent, setSaveButtonContent] = useState('Save settings')
const [timerId, setTimerId] = useState(0)
const [dynamicFee, setDynamicFee] = useState<number | null>(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_PRIORITY_FEE', recentPriorityFee.toString())
localStorage.setItem('INVARIANT_IS_DYNAMIC_FEE', recentIsDynamic.toString())
}, [])

useEffect(() => {
Expand Down Expand Up @@ -71,6 +85,11 @@ const Priority: React.FC<Props> = ({
const handleClick = (index: number) => {
setInputValue('')

if (index === 4) {
setIsDynamic(true)
} else {
setIsDynamic(false)
}
setSelectedIndex(index)
}

Expand All @@ -90,20 +109,55 @@ const Priority: React.FC<Props> = ({
}

if (+inputValue > 0) {
setIsDynamic(false)
setSelectedFee(+inputValue)
localStorage.setItem('INVARIANT_MAINNET_PRIORITY_FEE', inputValue)
localStorage.setItem('INVARIANT_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_PRIORITY_FEE', (dynamicFee ?? 0).toString())
localStorage.setItem('INVARIANT_IS_DYNAMIC_FEE', 'true')
} else {
setIsDynamic(false)
setSelectedFee(priorityFeeOptions[selectedIndex].saveValue)
localStorage.setItem(
'INVARIANT_PRIORITY_FEE',
priorityFeeOptions[selectedIndex].saveValue.toString()
)
localStorage.setItem('INVARIANT_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_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' },
{
Expand All @@ -113,7 +167,13 @@ const Priority: React.FC<Props> = ({
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 (
Expand Down Expand Up @@ -146,11 +206,11 @@ const Priority: React.FC<Props> = ({
<Box>
<TransactionPriorityButton
areButtonsSelected={selectedIndex !== -1}
selected={selectedIndex === index}
selected={isDynamic ? params.saveValue === 'DYNAMIC' : selectedIndex === index}
index={index}
label={params.label}
value={params.value}
saveValue={params.saveValue}
value={typeof params.value === 'string' ? dynamicFee ?? 0 : params.value}
saveValue={typeof params.value === 'string' ? dynamicFee ?? 0 : params.value}
description={params.description}
onClick={handleClick}
/>
Expand Down
13 changes: 10 additions & 3 deletions src/containers/HeaderWrapper/HeaderWrapper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

Expand Down Expand Up @@ -54,11 +54,17 @@ 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('INVARIANT_IS_DYNAMIC_FEE')

return lastIsDynamic === null ? true : lastIsDynamic === 'true'
}, [])

const currentRpcStatus = useSelector(rpcStatus)

const useDefaultRpc = () => {
Expand Down Expand Up @@ -110,6 +116,7 @@ export const HeaderWrapper: React.FC = () => {
rpc={currentRpc}
defaultMainnetRPC={defaultMainnetRPC}
recentPriorityFee={recentPriorityFee}
recentIsDynamic={recentIsDynamic}
onPrioritySave={() => {
dispatch(
snackbarsActions.add({
Expand Down
14 changes: 7 additions & 7 deletions src/store/sagas/positions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ function* handleInitPositionAndPoolWithSOL(action: PayloadAction<InitPositionDat
let initPositionTx: Transaction
let poolSigners: Keypair[] = []

const fee = localStorage.getItem('INVARIANT_MAINNET_PRIORITY_FEE')
const fee = localStorage.getItem('INVARIANT_PRIORITY_FEE')

const { transaction, signers } = yield* call(
[marketProgram, marketProgram.initPoolAndPositionTx],
Expand Down Expand Up @@ -435,7 +435,7 @@ function* handleInitPositionWithSOL(action: PayloadAction<InitPositionData>): 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, {
Expand Down Expand Up @@ -623,7 +623,7 @@ export function* handleInitPosition(action: PayloadAction<InitPositionData>): 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(
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -1125,7 +1125,7 @@ export function* handleClaimFee(action: PayloadAction<number>) {

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)
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -1517,7 +1517,7 @@ export function* handleClosePosition(action: PayloadAction<ClosePositionData>) {
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)
Expand Down
4 changes: 2 additions & 2 deletions src/store/sagas/swap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down Expand Up @@ -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(
Expand Down

0 comments on commit 282b6c8

Please sign in to comment.