remove delegates from useMembersStore (#1659)

This commit is contained in:
agrippa 2023-06-05 21:01:24 -04:00 committed by GitHub
parent 96021ba076
commit 0955fee1a8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 178 additions and 277 deletions

View File

@ -26,6 +26,7 @@
"react/display-name": 0,
"react/prop-types": 0,
"unused-imports/no-unused-imports": "error",
//"@typescript-eslint/no-unnecessary-condition": "error",
"@typescript-eslint/explicit-function-return-type": 0,
"@typescript-eslint/explicit-module-boundary-types": 0,
"@typescript-eslint/explicit-member-accessibility": 0,

View File

@ -15,7 +15,7 @@ import {
} from '@utils/tokens'
import { capitalize } from '@utils/helpers'
import { TokenRecordsWithWalletAddress } from './types'
import { Member, Delegates } from 'utils/uiTypes/members'
import { Member } from 'utils/uiTypes/members'
import useMembersStore from 'stores/useMembersStore'
import { useRealmQuery } from '@hooks/queries/realm'
import { useTokenRecordsByOwnersMap } from '@hooks/queries/tokenOwnerRecord'
@ -31,7 +31,6 @@ export default function useMembers() {
const connection = useLegacyConnectionContext()
const setMembers = useMembersStore((s) => s.setMembers)
const setDelegates = useMembersStore((s) => s.setDelegates)
const tokenRecordArray: TokenRecordsWithWalletAddress[] = useMemo(
() =>
@ -205,60 +204,6 @@ export default function useMembers() {
[communityAndCouncilTokenRecords]
)
// Loop through Members list to get our delegates and their tokens
// Return a object of key: walletId and value: object of arrays for council/community tokenOwnerRecords.
const getDelegateWalletMap = (members: Array<Member>): Delegates => {
const delegateMap = {} as Delegates
members.forEach((member: Member) => {
if (member?.delegateWalletCouncil) {
const walletId = member?.delegateWalletCouncil.toBase58()
if (delegateMap[walletId]) {
const oldCouncilRecords = delegateMap[walletId].councilMembers || []
delegateMap[walletId] = {
...delegateMap[walletId],
councilMembers: [...oldCouncilRecords, member],
councilTokenCount: (
delegateMap[walletId]?.councilTokenCount ?? BN_ZERO
).add(member.councilVotes),
}
} else {
delegateMap[walletId] = {
councilMembers: [member],
councilTokenCount: member.councilVotes
? member.councilVotes
: BN_ZERO,
}
}
}
if (member?.delegateWalletCommunity) {
const walletId = member?.delegateWalletCommunity.toBase58()
if (delegateMap[walletId]) {
const oldCommunityRecords =
delegateMap[walletId].communityMembers || []
delegateMap[walletId] = {
...delegateMap[walletId],
communityMembers: [...oldCommunityRecords, member],
communityTokenCount: (
delegateMap[walletId]?.communityTokenCount ?? BN_ZERO
).add(member.communityVotes),
}
} else {
delegateMap[walletId] = {
communityMembers: [member],
communityTokenCount: member.communityVotes
? member.communityVotes
: BN_ZERO,
}
}
}
})
return delegateMap
}
// Move to store if will be used more across application
useEffect(() => {
console.log('useMembers is fetching')
@ -277,19 +222,12 @@ export default function useMembers() {
setMembers(members)
}
const getDelegates = async () => {
const members = [...membersWithTokensDeposited]
const delegateMap = getDelegateWalletMap(members)
setDelegates(delegateMap)
}
handleSetMembers()
getDelegates()
}, [
fetchCommunityMembersATAS,
fetchCouncilMembersWithTokensOutsideRealm,
membersWithTokensDeposited,
realm?.pubkey,
setDelegates,
setMembers,
])
}

View File

@ -1,45 +1,56 @@
import { DisplayAddress } from '@cardinal/namespaces-components'
import Select from '@components/inputs/Select'
import useMembersStore from 'stores/useMembersStore'
import useRealm from 'hooks/useRealm'
import useWalletOnePointOh from '@hooks/useWalletOnePointOh'
import {
useTokenOwnerRecordsDelegatedToUser,
useUserCommunityTokenOwnerRecord,
useUserCouncilTokenOwnerRecord,
} from '@hooks/queries/tokenOwnerRecord'
import { useSelectedDelegatorStore } from 'stores/useSelectedDelegatorStore'
import { PublicKey } from '@solana/web3.js'
import useLegacyConnectionContext from '@hooks/useLegacyConnectionContext'
import { useRealmQuery } from '@hooks/queries/realm'
import { useMemo } from 'react'
const DelegateBalanceCard = () => {
const delegates = useMembersStore((s) => s.compact.delegates)
const wallet = useWalletOnePointOh()
const connection = useLegacyConnectionContext()
const walletId = wallet?.publicKey?.toBase58()
const ownTokenRecord = useUserCommunityTokenOwnerRecord().data?.result
const ownCouncilTokenRecord = useUserCouncilTokenOwnerRecord().data?.result
const realm = useRealmQuery().data?.result
const { ownDelegateTokenRecords, ownDelegateCouncilTokenRecords } = useRealm()
const delegatesArray = useTokenOwnerRecordsDelegatedToUser()
// returns array of community tokenOwnerRecords that connected wallet has been delegated
const communityTorsDelegatedToUser = useMemo(
() =>
realm === undefined
? undefined
: delegatesArray?.filter((x) =>
x.account.governingTokenMint.equals(realm.account.communityMint)
),
[delegatesArray, realm]
)
const councilMintAddr = realm?.account.config.councilMint
// returns array of council tokenOwnerRecords that connected wallet has been delegated
const councilTorsDelegatedToUser = useMemo(
() =>
councilMintAddr === undefined
? undefined
: delegatesArray?.filter((x) =>
x.account.governingTokenMint.equals(councilMintAddr)
),
[delegatesArray, councilMintAddr]
)
const {
setCommunityDelegator,
setCouncilDelegator,
} = useSelectedDelegatorStore()
const getCouncilDelegateAmt = () => {
if (walletId && delegates?.[walletId]) {
return delegates?.[walletId]?.councilMembers?.length ?? 0
}
return 0
}
const getCommunityDelegateAmt = () => {
if (walletId && delegates?.[walletId]) {
return delegates?.[walletId]?.communityMembers?.length ?? 0
}
return 0
}
const handleCouncilSelect = (councilTokenRecord?: string) => {
setCouncilDelegator(
councilTokenRecord ? new PublicKey(councilTokenRecord) : undefined
@ -52,139 +63,143 @@ const DelegateBalanceCard = () => {
)
}
if (!walletId || !delegates?.[walletId]) {
if (!walletId) {
return null
}
return (
<>
<h3 className="mb-0 mt-2">Your Delegates</h3>
{walletId && delegates?.[walletId]?.councilMembers && (
<div className="flex space-x-4 items-center mt-4">
<div className="bg-bkg-1 px-4 py-2 justify-between rounded-md w-full">
<div className="flex flex-row justify-between w-full mb-2">
<div>
<p className="text-fgd-3 text-xs">Delegate Accounts</p>
<p className="font-bold mb-0 text-fgd-1 text-xl">
{getCouncilDelegateAmt()}
</p>
{walletId &&
councilTorsDelegatedToUser &&
councilTorsDelegatedToUser.length > 0 && (
<div className="flex space-x-4 items-center mt-4">
<div className="bg-bkg-1 px-4 py-2 justify-between rounded-md w-full">
<div className="flex flex-row justify-between w-full mb-2">
<div>
<p className="text-fgd-3 text-xs">Delegate Accounts</p>
<p className="font-bold mb-0 text-fgd-1 text-xl">
{councilTorsDelegatedToUser?.length ?? 0}
</p>
</div>
</div>
</div>
<p className="text-fgd-3 text-xs mb-1">Selected Delegate</p>
<Select
value={
(ownCouncilTokenRecord &&
ownCouncilTokenRecord?.account?.governingTokenOwner?.toBase58()) ||
''
}
placeholder="Delegate to use for council votes"
onChange={handleCouncilSelect}
componentLabel={
ownCouncilTokenRecord ? (
<div className="relative">
<DisplayAddress
connection={connection.current}
address={
ownCouncilTokenRecord?.account?.governingTokenOwner
}
height="12px"
width="100px"
dark={true}
/>
<div className="absolute bg-bkg-1 bottom-0 left-0 w-full h-full opacity-0 " />
</div>
) : (
<p className="text-fgd-3 text-xs mb-1">Selected Delegate</p>
<Select
value={
(ownCouncilTokenRecord &&
ownCouncilTokenRecord.account.governingTokenOwner.toBase58()) ||
''
)
}
>
<Select.Option key={'reset'} value={undefined}>
Use own wallet
</Select.Option>
{ownDelegateCouncilTokenRecords?.map((councilDelegate) => (
<Select.Option
key={councilDelegate?.account?.governingTokenOwner?.toBase58()}
value={councilDelegate?.account?.governingTokenOwner?.toBase58()}
>
<div className="relative">
<DisplayAddress
connection={connection.current}
address={councilDelegate?.account?.governingTokenOwner}
height="12px"
width="100px"
dark={true}
/>
<div className="absolute bg-bkg-1 bottom-0 left-0 w-full h-full opacity-0 " />
</div>
}
placeholder="Delegate to use for council votes"
onChange={handleCouncilSelect}
componentLabel={
ownCouncilTokenRecord ? (
<div className="relative">
<DisplayAddress
connection={connection.current}
address={
ownCouncilTokenRecord.account.governingTokenOwner
}
height="12px"
width="100px"
dark={true}
/>
<div className="absolute bg-bkg-1 bottom-0 left-0 w-full h-full opacity-0 " />
</div>
) : (
''
)
}
>
<Select.Option key={'reset'} value={undefined}>
Use own wallet
</Select.Option>
))}
</Select>
{councilTorsDelegatedToUser?.map((councilDelegate) => (
<Select.Option
key={councilDelegate.account.governingTokenOwner.toBase58()}
value={councilDelegate.account.governingTokenOwner.toBase58()}
>
<div className="relative">
<DisplayAddress
connection={connection.current}
address={councilDelegate.account.governingTokenOwner}
height="12px"
width="100px"
dark={true}
/>
<div className="absolute bg-bkg-1 bottom-0 left-0 w-full h-full opacity-0 " />
</div>
</Select.Option>
))}
</Select>
</div>
</div>
</div>
)}
{walletId && delegates?.[walletId]?.communityMembers && (
<div className="flex space-x-4 items-center mt-4">
<div className="bg-bkg-1 px-4 py-2 justify-between rounded-md w-full">
<div className="flex flex-row justify-between w-full mb-2">
<div>
<p className="text-fgd-3 text-xs">Delegate Accounts</p>
<p className="font-bold mb-0 text-fgd-1 text-xl">
{getCommunityDelegateAmt()}
</p>
)}
{walletId &&
communityTorsDelegatedToUser &&
communityTorsDelegatedToUser.length > 0 && (
<div className="flex space-x-4 items-center mt-4">
<div className="bg-bkg-1 px-4 py-2 justify-between rounded-md w-full">
<div className="flex flex-row justify-between w-full mb-2">
<div>
<p className="text-fgd-3 text-xs">Delegate Accounts</p>
<p className="font-bold mb-0 text-fgd-1 text-xl">
{communityTorsDelegatedToUser.length ?? 0}
</p>
</div>
</div>
</div>
<p className="text-fgd-3 text-xs mb-1">Selected Delegate</p>
<Select
value={
(ownTokenRecord &&
ownTokenRecord.account.governingTokenOwner.toBase58()) ||
''
}
placeholder="Delegate to use for community votes"
onChange={handleCommunitySelect}
componentLabel={
ownTokenRecord ? (
<div className="relative">
<DisplayAddress
connection={connection.current}
address={ownTokenRecord.account.governingTokenOwner}
height="12px"
width="100px"
dark={true}
/>
<div className="absolute bg-bkg-1 bottom-0 left-0 w-full h-full opacity-0 " />
</div>
) : (
<p className="text-fgd-3 text-xs mb-1">Selected Delegate</p>
<Select
value={
(ownTokenRecord &&
ownTokenRecord.account.governingTokenOwner.toBase58()) ||
''
)
}
>
<Select.Option key={'reset'} value={''}>
Use own wallet
</Select.Option>
{ownDelegateTokenRecords?.map((communityDelegate) => (
<Select.Option
key={communityDelegate?.account?.governingTokenOwner?.toBase58()}
value={communityDelegate?.account?.governingTokenOwner?.toBase58()}
>
<div className="relative">
<DisplayAddress
connection={connection.current}
address={communityDelegate?.account?.governingTokenOwner}
height="12px"
width="100px"
dark={true}
/>
<div className="absolute bg-bkg-1 bottom-0 left-0 w-full h-full opacity-0 " />
</div>
}
placeholder="Delegate to use for community votes"
onChange={handleCommunitySelect}
componentLabel={
ownTokenRecord ? (
<div className="relative">
<DisplayAddress
connection={connection.current}
address={ownTokenRecord.account.governingTokenOwner}
height="12px"
width="100px"
dark={true}
/>
<div className="absolute bg-bkg-1 bottom-0 left-0 w-full h-full opacity-0 " />
</div>
) : (
''
)
}
>
<Select.Option key={'reset'} value={''}>
Use own wallet
</Select.Option>
))}
</Select>
{communityTorsDelegatedToUser.map((communityDelegate) => (
<Select.Option
key={communityDelegate.account.governingTokenOwner.toBase58()}
value={communityDelegate.account.governingTokenOwner.toBase58()}
>
<div className="relative">
<DisplayAddress
connection={connection.current}
address={communityDelegate.account.governingTokenOwner}
height="12px"
width="100px"
dark={true}
/>
<div className="absolute bg-bkg-1 bottom-0 left-0 w-full h-full opacity-0 " />
</div>
</Select.Option>
))}
</Select>
</div>
</div>
</div>
)}
)}
</>
)
}

View File

@ -16,6 +16,7 @@ import { useRealmQuery } from './realm'
import queryClient from './queryClient'
import { useMemo } from 'react'
import useLegacyConnectionContext from '@hooks/useLegacyConnectionContext'
import useWalletOnePointOh from '@hooks/useWalletOnePointOh'
export const tokenOwnerRecordQueryKeys = {
all: (cluster: EndpointTypes) => [cluster, 'TokenOwnerRecord'],
@ -67,6 +68,25 @@ export const useTokenOwnerRecordsForRealmQuery = () => {
return query
}
// TODO filter in the gPA (would need rpc to also index)
export const useTokenOwnerRecordsDelegatedToUser = () => {
const { data: tors } = useTokenOwnerRecordsForRealmQuery()
const wallet = useWalletOnePointOh()
const delagatingTors = useMemo(
() =>
tors?.filter(
(x) =>
wallet?.publicKey !== undefined &&
wallet?.publicKey !== null &&
x.account.governanceDelegate !== undefined &&
x.account.governanceDelegate.equals(wallet.publicKey)
),
[tors, wallet?.publicKey]
)
return delagatingTors
}
/** @deprecated this hook exists for refactoring legacy code easily -- you should probably not be using it in any new code */
export const useTokenRecordsByOwnersMap = () => {
const { data: tors } = useTokenOwnerRecordsForRealmQuery()

View File

@ -13,7 +13,6 @@ import {
VoteRegistryVoterWeight,
VoterWeight,
} from '../models/voteWeights'
import useMembersStore from 'stores/useMembersStore'
import {
NFT_PLUGINS_PKS,
VSR_PLUGIN_PKS,
@ -31,7 +30,6 @@ import { useVsrMode } from './useVsrMode'
import useWalletOnePointOh from './useWalletOnePointOh'
import { useRealmQuery } from './queries/realm'
import {
useTokenRecordsByOwnersMap,
useUserCommunityTokenOwnerRecord,
useUserCouncilTokenOwnerRecord,
} from './queries/tokenOwnerRecord'
@ -56,11 +54,6 @@ export default function useRealm() {
const realm = useRealmQuery().data?.result
const realmInfo = useSelectedRealmInfo()
const {
communityTORsByOwner: tokenRecords,
councilTORsByOwner: councilTokenOwnerRecords,
} = useTokenRecordsByOwnersMap()
const config = useRealmConfigQuery().data?.result
const mint = useRealmCommunityMintInfoQuery().data?.result
const councilMint = useRealmCouncilMintInfoQuery().data?.result
@ -98,8 +91,6 @@ export default function useRealm() {
// eslint-disable-next-line react-hooks/exhaustive-deps -- TODO please fix, it can cause difficult bugs. You might wanna check out https://bobbyhadz.com/blog/react-hooks-exhaustive-deps for info. -@asktree
}, [wallet?.publicKey])
const delegates = useMembersStore((s) => s.compact.delegates)
const realmTokenAccount = useMemo(
() =>
realm &&
@ -109,27 +100,6 @@ export default function useRealm() {
[realm, tokenAccounts]
)
// TODO refactor as query
// returns array of community tokenOwnerRecords that connected wallet has been delegated
const ownDelegateTokenRecords = useMemo(() => {
if (wallet?.connected && wallet.publicKey && tokenRecords) {
const walletId = wallet.publicKey.toBase58()
const delegatedWallets = delegates && delegates[walletId]
if (delegatedWallets?.communityMembers) {
const communityTokenRecords = delegatedWallets.communityMembers.map(
(member) => {
return tokenRecords[member.walletAddress]
}
)
return communityTokenRecords
}
}
return undefined
// eslint-disable-next-line react-hooks/exhaustive-deps -- TODO please fix, it can cause difficult bugs. You might wanna check out https://bobbyhadz.com/blog/react-hooks-exhaustive-deps for info. -@asktree
}, [tokenRecords, wallet, connected])
const councilTokenAccount = useMemo(
() =>
realm &&
@ -141,31 +111,6 @@ export default function useRealm() {
[realm, tokenAccounts]
)
// TODO refactor as query
// returns array of council tokenOwnerRecords that connected wallet has been delegated
const ownDelegateCouncilTokenRecords = useMemo(() => {
if (
wallet?.connected &&
councilMint &&
wallet.publicKey &&
councilTokenOwnerRecords
) {
const walletId = wallet.publicKey.toBase58()
const delegatedWallets = delegates && delegates[walletId]
if (delegatedWallets?.councilMembers) {
const councilTokenRecords = delegatedWallets.councilMembers.map(
(member) => {
return councilTokenOwnerRecords[member.walletAddress]
}
)
return councilTokenRecords
}
}
return undefined
// eslint-disable-next-line react-hooks/exhaustive-deps -- TODO please fix, it can cause difficult bugs. You might wanna check out https://bobbyhadz.com/blog/react-hooks-exhaustive-deps for info. -@asktree
}, [tokenRecords, wallet, connected])
const canChooseWhoVote =
realm?.account.communityMint &&
(!mint?.supply.isZero() ||
@ -225,8 +170,7 @@ export default function useRealm() {
//councilTokenOwnerRecords,
toManyCouncilOutstandingProposalsForUse,
toManyCommunityOutstandingProposalsForUser,
ownDelegateTokenRecords,
ownDelegateCouncilTokenRecords,
//config,
currentPluginPk,
vsrMode,
@ -237,8 +181,7 @@ export default function useRealm() {
councilTokenAccount,
currentPluginPk,
isNftMode,
ownDelegateCouncilTokenRecords,
ownDelegateTokenRecords,
ownVoterWeight,
realmInfo,
realmTokenAccount,

View File

@ -1,6 +1,6 @@
import create, { State } from 'zustand'
import { ViewState } from '@components/Members/types'
import { Member, Delegates } from '@utils/uiTypes/members'
import { Member } from '@utils/uiTypes/members'
interface MembersStore extends State {
compact: {
@ -8,13 +8,13 @@ interface MembersStore extends State {
currentMember: Member | null
members: Member[]
activeMembers: Member[]
delegates: Delegates | null
//delegates: Delegates | null
}
setCurrentCompactViewMember: (item: Member) => void
setCurrentCompactView: (viewState: ViewState) => void
resetCompactViewState: () => void
setMembers: (members: Member[]) => void
setDelegates: (delegates: Delegates) => void
//setDelegates: (delegates: Delegates) => void
}
const compactDefaultState = {
@ -22,7 +22,7 @@ const compactDefaultState = {
currentMember: null,
members: [],
activeMembers: [],
delegates: null,
//delegates: null,
}
const useMembersStore = create<MembersStore>((set, _get) => ({
@ -53,11 +53,6 @@ const useMembersStore = create<MembersStore>((set, _get) => ({
s.compact.activeMembers = activeMembers
})
},
setDelegates: (delegates: Delegates) => {
set((s) => {
s.compact.delegates = delegates
})
},
}))
export default useMembersStore

View File

@ -10,14 +10,3 @@ export interface Member {
delegateWalletCouncil?: PublicKey
delegateWalletCommunity?: PublicKey
}
interface Delegate {
communityMembers?: Array<Member>
councilMembers?: Array<Member>
communityTokenCount?: BN
councilTokenCount?: BN
}
export interface Delegates {
[key: string]: Delegate
}