-
Notifications
You must be signed in to change notification settings - Fork 19
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
SOV-3945: prevent creation of "dead vestings" (#964)
* feat: custom row wrapper for table component * feat: add alert message * chore: fix review comments * chore: add changeset --------- Co-authored-by: soulBit <[email protected]>
- Loading branch information
1 parent
68e9c96
commit d0899e6
Showing
17 changed files
with
368 additions
and
49 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
'@sovryn/ui': patch | ||
--- | ||
|
||
feat: allow custom row wrapper in table component |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"frontend": patch | ||
--- | ||
|
||
SOV-3945: prevent "dead vestings" from LM rewards |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 2 additions & 0 deletions
2
...ge/components/Vesting/components/UnclaimedVestingAlert/UnclaimedVestingAlert.constants.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
export const MIN_ALERT_COUNT = 32; | ||
export const LOCK_CLAIM_COUNT = 43; |
35 changes: 35 additions & 0 deletions
35
...RewardsPage/components/Vesting/components/UnclaimedVestingAlert/UnclaimedVestingAlert.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
import React from 'react'; | ||
|
||
import { t } from 'i18next'; | ||
import { Link } from 'react-router-dom'; | ||
|
||
import { Paragraph } from '@sovryn/ui'; | ||
|
||
import { translations } from '../../../../../../../locales/i18n'; | ||
import { useGetUnclaimedUserVestingCount } from '../../hooks/useLmLimit'; | ||
import { | ||
LOCK_CLAIM_COUNT, | ||
MIN_ALERT_COUNT, | ||
} from './UnclaimedVestingAlert.constants'; | ||
|
||
export const UnclaimcedVestingAlert = () => { | ||
const count = useGetUnclaimedUserVestingCount(); | ||
|
||
if (count > MIN_ALERT_COUNT && count < LOCK_CLAIM_COUNT) { | ||
return ( | ||
<div className="bg-error-light bg-opacity-50 p-4 rounded-lg mt-12 my-4 mx-8"> | ||
<Paragraph> | ||
{t(translations.unclaimedVestings.text, { value: count })}{' '} | ||
<Link | ||
to="/rewards" | ||
className="underline text-primary-20 hover:text-primary-10" | ||
> | ||
{t(translations.unclaimedVestings.cta)} | ||
</Link> | ||
</Paragraph> | ||
</div> | ||
); | ||
} | ||
|
||
return null; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
59 changes: 59 additions & 0 deletions
59
apps/frontend/src/app/5_pages/RewardsPage/components/Vesting/context/VestingContext.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
import React, { | ||
useContext, | ||
createContext, | ||
useState, | ||
useCallback, | ||
FC, | ||
PropsWithChildren, | ||
} from 'react'; | ||
|
||
import { produce } from 'immer'; | ||
|
||
import { VestingContractTableRecord } from '../Vesting.types'; | ||
|
||
export type State = { | ||
count: number; | ||
item?: VestingContractTableRecord; | ||
}; | ||
|
||
type Update = (state: State) => void; | ||
|
||
type Actions = { | ||
update: (handler: Update) => void; | ||
}; | ||
|
||
const defaultValue: State & Actions = { | ||
count: 0, | ||
item: undefined, | ||
update: () => {}, | ||
}; | ||
|
||
const VestingContext = createContext<State & Actions>(defaultValue); | ||
|
||
export function useVestingContext() { | ||
const context = useContext(VestingContext); | ||
if (context === undefined) { | ||
throw new Error( | ||
'useVestingContext must be used within a VestingContextProvider', | ||
); | ||
} | ||
return context; | ||
} | ||
|
||
export const VestingContextProvider: FC<PropsWithChildren> = ({ children }) => { | ||
const [state, setState] = useState<State>({ | ||
count: 0, | ||
item: undefined, | ||
}); | ||
|
||
const handleOnChange = useCallback( | ||
(handler: (value: State) => void) => setState(produce(handler)), | ||
[], | ||
); | ||
|
||
return ( | ||
<VestingContext.Provider value={{ ...state, update: handleOnChange }}> | ||
{children} | ||
</VestingContext.Provider> | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
55 changes: 55 additions & 0 deletions
55
apps/frontend/src/app/5_pages/RewardsPage/components/Vesting/hooks/useLmLimit.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
import { useMemo } from 'react'; | ||
|
||
import dayjs from 'dayjs'; | ||
|
||
import { useAccount } from '../../../../../../hooks/useAccount'; | ||
import { rskClient } from '../../../../../../utils/clients'; | ||
import { | ||
useGetUserVestingsOfTypeQuery, | ||
VestingContractType, | ||
} from '../../../../../../utils/graphql/rsk/generated'; | ||
|
||
export const useGetUnclaimedUserVestingCount = () => { | ||
const { account } = useAccount(); | ||
const { data } = useGetUserVestingsOfTypeQuery({ | ||
variables: { | ||
user: account.toLowerCase(), | ||
type: VestingContractType.Rewards, | ||
}, | ||
client: rskClient, | ||
}); | ||
|
||
const result = useMemo(() => { | ||
const stakeHistoryItems = data?.vestingContracts[0]?.stakeHistory?.map( | ||
item => ({ | ||
amount: item.amount, | ||
lockedUntil: item.lockedUntil, | ||
}), | ||
); | ||
|
||
if (!stakeHistoryItems) { | ||
return 0; | ||
} | ||
|
||
const normalizedStakeHistoryItems = stakeHistoryItems.reduce((map, obj) => { | ||
const { lockedUntil, amount } = obj; | ||
map.set(lockedUntil, (map.get(lockedUntil) || 0) + Number(amount)); | ||
return map; | ||
}, new Map()); | ||
|
||
const unlockDates = Array.from( | ||
normalizedStakeHistoryItems, | ||
([lockedUntil, amount]) => ({ | ||
lockedUntil, | ||
amount, | ||
isUnlocked: lockedUntil <= dayjs().unix(), | ||
}), | ||
).sort((a, b) => a.lockedUntil - b.lockedUntil); | ||
|
||
const pastDatesLength = unlockDates?.filter(item => item.isUnlocked).length; | ||
|
||
return pastDatesLength; | ||
}, [data?.vestingContracts]); | ||
|
||
return result; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.