Skip to content

Commit

Permalink
feat: add delegate form fill on click from public delegates list
Browse files Browse the repository at this point in the history
  • Loading branch information
katamarinaki committed Aug 27, 2024
1 parent 540fcf9 commit 794474a
Show file tree
Hide file tree
Showing 8 changed files with 115 additions and 45 deletions.
25 changes: 23 additions & 2 deletions modules/delegation/providers/DelegationFormContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
useContext,
useCallback,
useState,
useEffect,
} from 'react'
import { useGovernanceBalance } from 'modules/tokens/hooks/useGovernanceBalance'
import { useDelegationInfo } from '../hooks/useDelegationInfo'
Expand All @@ -19,6 +20,7 @@ import {
import { useDelegationFormSubmit } from '../hooks/useDelegationFormSubmit'
import { useDelegationRevoke } from '../hooks/useDelegationRevoke'
import { ToastSuccess } from '@lidofinance/lido-ui'
import { isValidAddress } from 'modules/shared/utils/addressValidation'

//
// Data context
Expand Down Expand Up @@ -116,17 +118,36 @@ const useDelegationFormActions = (
//
// Data provider
//
export const DelegationFormProvider: FC<{ mode: DelegationFormMode }> = ({
export type DelegationFormProviderProps = {
mode: DelegationFormMode
presetDelegateAddress?: string
}

export const DelegationFormProvider: FC<DelegationFormProviderProps> = ({
children,
mode,
presetDelegateAddress,
}) => {
const networkData = useDelegationFormNetworkData()

const formObject = useForm<DelegationFormInput>({
defaultValues: { delegateAddress: null },
defaultValues: { delegateAddress: '' },
mode: 'onChange',
})

useEffect(() => {
const currentValue = formObject.getValues('delegateAddress')
if (
presetDelegateAddress &&
isValidAddress(presetDelegateAddress) &&
currentValue?.toLowerCase() !== presetDelegateAddress.toLowerCase()
) {
console.log('setting default address', presetDelegateAddress)
formObject.setValue('delegateAddress', presetDelegateAddress)
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [presetDelegateAddress])

const {
isSubmitting,
txAragonDelegate,
Expand Down
9 changes: 1 addition & 8 deletions modules/delegation/publicDelegates.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// The list of public delegates was provided by DAO Ops workstream member
export const PUBLIC_DELEGATES = [
{
name: 'Matt Stam',
Expand Down Expand Up @@ -125,14 +126,6 @@ export const PUBLIC_DELEGATES = [
lido: 'https://research.lido.fi/t/nodesoda-com-delegate-thread/8031',
twitter: 'https://x.com/pablolema85',
},
{
name: 'eboadom (Ernesto)',
avatar:
'https://dub1.discourse-cdn.com/business20/user_avatar/research.lido.fi/eboadom/288/3764_2.png',
address: '0x000b4369B71B6634F27F5De9Cbaaabb0D21B8be5',
lido: 'https://research.lido.fi/t/eboadom-delegate-thread/8079',
twitter: 'https://x.com/eboadom',
},
{
name: 'ReservoirDAO',
avatar:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,11 @@ export function DelegationAddressInput() {
aragonDelegateAddress,
snapshotDelegateAddress,
mode,
register,
} = useDelegationFormData()

return (
<InputControl
{...register('delegateAddress')}
name="delegateAddress"
label="Delegate address"
disabled={
!isWalletConnected || loading.isDelegationInfoLoading || isSubmitting
Expand Down
13 changes: 7 additions & 6 deletions modules/delegation/ui/DelegationForm/DelegationForm.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { DelegationFormProvider } from 'modules/delegation/providers/DelegationFormContext'
import { DelegationFormMode } from 'modules/delegation/types'
import {
DelegationFormProvider,
DelegationFormProviderProps,
} from 'modules/delegation/providers/DelegationFormContext'
import { DelegationStatus } from './DelegationStatus/DelegationStatus'
import { DelegationFormSubtitle } from './DelegationFormSubtitle'
import { DelegationAddressInput } from './DelegationAddressInput'
Expand All @@ -9,14 +11,13 @@ import { DelegationFormFootNote } from './DelegationFormFootNote'
import { DelegationFormController } from './DelegationFormController'
import { DelegationTxStatus } from './DelegationTxStatus'

type Props = {
mode: DelegationFormMode
type Props = DelegationFormProviderProps & {
onCustomizeClick?: () => void
}

export function DelegationForm({ mode, onCustomizeClick }: Props) {
export function DelegationForm({ onCustomizeClick, ...providerProps }: Props) {
return (
<DelegationFormProvider mode={mode}>
<DelegationFormProvider {...providerProps}>
<DelegationFormController>
<DelegationFormSubtitle />
<DelegationStatus />
Expand Down
23 changes: 19 additions & 4 deletions modules/delegation/ui/DelegationSettings/DelegationSettings.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useState } from 'react'
import { useCallback, useState } from 'react'
import { Button, Text } from '@lidofinance/lido-ui'

import { FormTitle, FormWrap, Wrap } from './DelegationSettingsStyle'
Expand All @@ -7,6 +7,14 @@ import { PublicDelegateList } from '../PublicDelegateList'

export function DelegationSettings() {
const [isSimpleModeOn, setIsSimpleModeOn] = useState(true)
const [delegateFromPublicList, setDelegateFromPublicList] = useState<string>()

const handleDelegatePick = useCallback(
(address: string) => () => {
setDelegateFromPublicList(address)
},
[],
)

return (
<Wrap>
Expand All @@ -28,16 +36,23 @@ export function DelegationSettings() {
{isSimpleModeOn ? (
<DelegationForm
mode="simple"
presetDelegateAddress={delegateFromPublicList}
onCustomizeClick={() => setIsSimpleModeOn(false)}
/>
) : (
<>
<DelegationForm mode="aragon" />
<DelegationForm mode="snapshot" />
<DelegationForm
mode="aragon"
presetDelegateAddress={delegateFromPublicList}
/>
<DelegationForm
mode="snapshot"
presetDelegateAddress={delegateFromPublicList}
/>
</>
)}
</FormWrap>
<PublicDelegateList />
<PublicDelegateList onDelegatePick={handleDelegatePick} />
</Wrap>
)
}
36 changes: 25 additions & 11 deletions modules/delegation/ui/PublicDelegateList/PublicDelegateList.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Button, Text, trimAddress } from '@lidofinance/lido-ui'
import Image from 'next/image'
import {
DelegateInfo,
Header,
Expand All @@ -14,15 +15,18 @@ import { useWeb3 } from 'modules/blockChain/hooks/useWeb3'
import { useProcessedPublicDelegatesList } from './useProcessedPublicDelegatesList'
import { PageLoader } from 'modules/shared/ui/Common/PageLoader'
import { isValidAddress } from 'modules/shared/utils/addressValidation'
import { formatBalance } from 'modules/blockChain/utils/formatBalance'
import { AddressPop } from 'modules/shared/ui/Common/AddressPop'

import AragonSvg from 'assets/aragon.com.svg.react'
import XSocialSvg from 'assets/x.social.com.svg.react'
import LidoSocialSvg from 'assets/lido.social.com.svg.react'
import Image from 'next/image'
import { formatBalance } from 'modules/blockChain/utils/formatBalance'
import { AddressPop } from 'modules/shared/ui/Common/AddressPop'

export function PublicDelegateList() {
type Props = {
onDelegatePick: (address: string) => () => void
}

export function PublicDelegateList({ onDelegatePick }: Props) {
const { isWalletConnected } = useWeb3()

const { data, initialLoading } = useProcessedPublicDelegatesList()
Expand Down Expand Up @@ -58,12 +62,17 @@ export function PublicDelegateList() {
<ListItem key={delegate.address}>
<DelegateInfo>
<AvatarWrap>
<Image
src={delegate.avatar ?? ''}
alt=""
layout="fill"
loader={({ src }) => src}
/>
{delegate.avatar ? (
<Image
src={delegate.avatar}
alt=""
layout="fill"
loader={({ src }) => src}
unoptimized
/>
) : (
<div />
)}
</AvatarWrap>
<div>
<Text size="xxs" weight={700}>
Expand Down Expand Up @@ -93,7 +102,12 @@ export function PublicDelegateList() {
</ExternalLink>
</SocialButtons>
{isWalletConnected && (
<Button size="xs" variant="outlined">
<Button
size="xs"
variant="outlined"
disabled={!delegate.resolvedDelegateAddress}
onClick={onDelegatePick(delegate.resolvedDelegateAddress!)}
>
Delegate
</Button>
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,8 @@ export const AvatarWrap = styled.div`
background-color: var(--lido-color-primaryVisited);
overflow: hidden;
& > img {
& > img,
div {
width: 100%;
height: 100%;
object-fit: cover;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,53 +5,72 @@ import { useWeb3 } from 'modules/blockChain/hooks/useWeb3'
import { DELEGATORS_FETCH_TOTAL } from 'modules/delegation/constants'
import { PUBLIC_DELEGATES } from 'modules/delegation/publicDelegates'
import { useEnsResolvers } from 'modules/shared/hooks/useEnsResolvers'
import { isValidEns } from 'modules/shared/utils/addressValidation'
import {
isValidAddress,
isValidEns,
} from 'modules/shared/utils/addressValidation'

type ProcessedDelegate = typeof PUBLIC_DELEGATES[number] & {
delegatorsCount: string
delegatedVotingPower: BigNumber | string
resolvedDelegateAddress: string | null
}

export const useProcessedPublicDelegatesList = () => {
const { chainId } = useWeb3()
const voting = ContractVoting.useRpc()

const { resolveName } = useEnsResolvers()

return useLidoSWRImmutable(
return useLidoSWRImmutable<ProcessedDelegate[]>(
[`swr:useProcessedPublicDelegatesList`, chainId],
async () => {
const parsedList = await Promise.all(
const parsedList: ProcessedDelegate[] = await Promise.all(
PUBLIC_DELEGATES.map(async delegate => {
let delegateAddress: string | null = delegate.address
let resolvedDelegateAddress: string | null =
delegate.address.toLowerCase()

// If `address` was provided as ENS name, convert it to address
if (isValidEns(delegateAddress)) {
delegateAddress = await resolveName(delegateAddress)
if (isValidEns(delegate.address)) {
resolvedDelegateAddress =
(await resolveName(delegate.address))?.toLowerCase() ?? null

// If ENS name wasn't not resolved, return delegate with N/A values
if (!delegateAddress) {
if (!resolvedDelegateAddress) {
return {
...delegate,
delegatorsCount: 'N/A',
delegatedVotingPower: 'N/A',
resolvedDelegateAddress: null,
}
}
} else if (!isValidAddress(delegate.address)) {
return {
...delegate,
delegatorsCount: 'N/A',
delegatedVotingPower: 'N/A',
resolvedDelegateAddress: null,
}
}

const delegatorsCount = await voting.getDelegatedVotersCount(
delegateAddress,
resolvedDelegateAddress,
)

if (delegatorsCount.isZero()) {
return {
...delegate,
delegatorsCount: '0',
delegatedVotingPower: '0',
delegatedVotingPower: BigNumber.from(0),
resolvedDelegateAddress,
}
}

const delegatorsAddresses = await voting.getDelegatedVoters(
delegateAddress,
resolvedDelegateAddress,
0,
DELEGATORS_FETCH_TOTAL,
)
console.log('addresses', delegatorsAddresses)
const delegatorsBalances = await voting.getVotingPowerMultiple(
delegatorsAddresses,
)
Expand All @@ -64,6 +83,7 @@ export const useProcessedPublicDelegatesList = () => {
...delegate,
delegatorsCount: delegatorsCount.toString(),
delegatedVotingPower: delegatedVotingPower,
resolvedDelegateAddress,
}
}),
)
Expand All @@ -72,6 +92,9 @@ export const useProcessedPublicDelegatesList = () => {
if (typeof a.delegatedVotingPower === 'string') {
return 1
}
if (typeof b.delegatedVotingPower === 'string') {
return -1
}
if (a.delegatedVotingPower.lt(b.delegatedVotingPower)) {
return 1
}
Expand All @@ -81,5 +104,8 @@ export const useProcessedPublicDelegatesList = () => {
return 0
})
},
{
onError: (error, key) => console.error(key, error),
},
)
}

0 comments on commit 794474a

Please sign in to comment.