From d4bda383be12a9464de323eff5583aa191ab242f Mon Sep 17 00:00:00 2001 From: agrippa kellum Date: Fri, 15 Dec 2023 17:41:22 -0500 Subject: [PATCH] remove voting nfts from voteclient --- actions/castVote.ts | 7 +- hooks/queries/plugins/nftVoter.ts | 82 ++++++++++++++++-------- hub/providers/Proposal/createProposal.ts | 2 - tools/nftVoteCalc.ts | 12 ++-- utils/uiTypes/VotePlugin.ts | 28 +++++--- 5 files changed, 87 insertions(+), 44 deletions(-) diff --git a/actions/castVote.ts b/actions/castVote.ts index 4deb70b56c..00efbf9124 100644 --- a/actions/castVote.ts +++ b/actions/castVote.ts @@ -447,14 +447,17 @@ export async function castVote( }), ] const totalVoteCost = await calcCostOfNftVote( + connection, message, instructionsChunks.length, proposal.pubkey, - votingPlugin + votingPlugin, + realm.pubkey, + walletPubkey ) const hasEnoughSol = await checkHasEnoughSolToVote( totalVoteCost, - wallet.publicKey!, + walletPubkey, connection ) if (!hasEnoughSol) { diff --git a/hooks/queries/plugins/nftVoter.ts b/hooks/queries/plugins/nftVoter.ts index 898fcec348..edc45a7d7b 100644 --- a/hooks/queries/plugins/nftVoter.ts +++ b/hooks/queries/plugins/nftVoter.ts @@ -4,52 +4,79 @@ import { getRegistrarPDA } from '@utils/plugin/accounts' import { Program } from '@coral-xyz/anchor' import { IDL, NftVoter } from 'idls/nft_voter' import asFindable from '@utils/queries/asFindable' -import { fetchRealmConfigQuery, useRealmConfigQuery } from '../realmConfig' +import { fetchRealmConfigQuery } from '../realmConfig' import { useBatchedVoteDelegators } from '@components/VotePanel/useDelegators' import { useConnection } from '@solana/wallet-adapter-react' import useSelectedRealmPubkey from '@hooks/selectedRealm/useSelectedRealmPubkey' import { getNftGovpower } from '../governancePower' import { useQueries, useQuery } from '@tanstack/react-query' -import { DasNftObject, useDigitalAssetsByOwner } from '../digitalAssets' -import { useCallback, useMemo } from 'react' +import { + fetchDigitalAssetsByOwner, + useDigitalAssetsByOwner, +} from '../digitalAssets' +import { useMemo } from 'react' import { ON_NFT_VOTER_V2 } from '@constants/flags' +import queryClient from '../queryClient' import { NFT_PLUGINS_PKS } from '@constants/plugins' +import { getNetworkFromEndpoint } from '@utils/connection' export const useVotingNfts = (ownerPk: PublicKey | undefined) => { const { connection } = useConnection() const realmPk = useSelectedRealmPubkey() const { data: nfts } = useDigitalAssetsByOwner(ownerPk) - const config = useRealmConfigQuery().data?.result - const currentPluginPk = config?.account.communityTokenConfig.voterWeightAddin const registrar = useQuery(nftRegistrarQuery(connection, realmPk)).data ?.result const usedCollectionsPks = useMemo( - () => - currentPluginPk === undefined || - !NFT_PLUGINS_PKS.includes(currentPluginPk.toBase58()) - ? undefined - : registrar?.collectionConfigs.map((x) => x.collection.toBase58()), - [currentPluginPk, registrar?.collectionConfigs] + () => registrar?.collectionConfigs.map((x) => x.collection.toBase58()), + [registrar?.collectionConfigs] ) - const getIsFromCollection = useCallback( - (nft: DasNftObject) => { - const collection = nft.grouping.find((x) => x.group_key === 'collection') - return ( - (ON_NFT_VOTER_V2 || !nft.compression.compressed) && - collection && - usedCollectionsPks?.includes(collection.group_value) && - nft.creators?.filter((x) => x.verified).length > 0 - ) - }, - [usedCollectionsPks] + const votingNfts = nfts?.filter((nft) => { + const collection = nft.grouping.find((x) => x.group_key === 'collection') + return ( + (ON_NFT_VOTER_V2 || !nft.compression.compressed) && + collection && + usedCollectionsPks?.includes(collection.group_value) && + nft.creators?.filter((x) => x.verified).length > 0 + ) + }) + + return votingNfts +} + +export const getVotingNfts = async ( + connection: Connection, + realmPk: PublicKey, + ownerPk: PublicKey +) => { + const realm = fetchRealmByPubkey(connection, realmPk) + if (realm === undefined) throw new Error() + const config = await fetchRealmConfigQuery(connection, realmPk) + if (config.result === undefined) throw new Error() + const currentPluginPk = + config.result.account.communityTokenConfig.voterWeightAddin + if (currentPluginPk === undefined) throw new Error() + const { result: registrar } = await queryClient.fetchQuery( + nftRegistrarQuery(connection, realmPk) + ) + if (registrar === undefined) throw new Error() + const usedCollectionsPks = registrar.collectionConfigs.map((x) => + x.collection.toBase58() ) - const votingNfts = nfts - ?.filter(getIsFromCollection) - .filter((x) => ON_NFT_VOTER_V2 || !x.compression.compressed) + const network = getNetworkFromEndpoint(connection.rpcEndpoint) as any + const nfts = await fetchDigitalAssetsByOwner(network, ownerPk) + const votingNfts = nfts?.filter((nft) => { + const collection = nft.grouping.find((x) => x.group_key === 'collection') + return ( + (ON_NFT_VOTER_V2 || !nft.compression.compressed) && + collection && + usedCollectionsPks?.includes(collection.group_value) && + nft.creators?.filter((x) => x.verified).length > 0 + ) + }) return votingNfts } @@ -99,7 +126,10 @@ export const nftRegistrarQuery = ( const config = await fetchRealmConfigQuery(connection, realmPk) const programId = config.result?.account.communityTokenConfig.voterWeightAddin - if (programId === undefined) + if ( + programId === undefined || + !NFT_PLUGINS_PKS.includes(programId.toString()) + ) return { found: false, result: undefined } as const const { registrar: registrarPk } = await getRegistrarPDA( diff --git a/hub/providers/Proposal/createProposal.ts b/hub/providers/Proposal/createProposal.ts index 3a2e809394..444f420a05 100644 --- a/hub/providers/Proposal/createProposal.ts +++ b/hub/providers/Proposal/createProposal.ts @@ -260,8 +260,6 @@ export async function createProposal(args: Args) { client, walletPk: args.requestingUserPublicKey, }); - - votingClient._setCurrentVoterNfts(votingNfts); } } diff --git a/tools/nftVoteCalc.ts b/tools/nftVoteCalc.ts index 0c9c1f29ea..6c3ba46ccf 100644 --- a/tools/nftVoteCalc.ts +++ b/tools/nftVoteCalc.ts @@ -7,6 +7,7 @@ import { getNftVoteRecordProgramAddress, getUsedNftsForProposal, } from 'NftVotePlugin/accounts' +import { getVotingNfts } from '@hooks/queries/plugins/nftVoter' //lamports costs hardcoded for now. //TODO figure out better cost handling @@ -17,20 +18,23 @@ const commentAvgCharacterCost = 6960 const singleTransactionCosts = 5000 export const calcCostOfNftVote = async ( + connection: Connection, comment: ChatMessageBody | undefined, numberOfTransactions: number, proposalPk: PublicKey, - votingPlugin: VotingClient + votingPlugin: VotingClient, + realmPk: PublicKey, + userPk: PublicKey ) => { let nftToVoteCount = 0 - const voterNfts = votingPlugin.votingNfts + const votingNfts = await getVotingNfts(connection, realmPk, userPk) const nftsAlreadyUsedToVote = await getUsedNftsForProposal( votingPlugin.client as NftVoterClient, proposalPk ) if (nftsAlreadyUsedToVote.length > 0) { - for (const nft of voterNfts) { + for (const nft of votingNfts) { const { nftVoteRecord } = await getNftVoteRecordProgramAddress( proposalPk, nft.id, @@ -45,7 +49,7 @@ export const calcCostOfNftVote = async ( } } } else { - nftToVoteCount = voterNfts.length + nftToVoteCount = votingNfts.length } let baseCost = castVoteIxAndUpdateVoterWeightIxCost diff --git a/utils/uiTypes/VotePlugin.ts b/utils/uiTypes/VotePlugin.ts index 98df689f0e..22da4901e2 100644 --- a/utils/uiTypes/VotePlugin.ts +++ b/utils/uiTypes/VotePlugin.ts @@ -14,7 +14,6 @@ import { getVoterWeightPDA, } from 'VoteStakeRegistry/sdk/accounts' import { NFTWithMint } from './nfts' -import { DasNftObject } from '@hooks/queries/digitalAssets' import { getPreviousVotingWeightRecord, getVoteInstruction, @@ -54,6 +53,7 @@ import { NftVoterV2 } from 'idls/nft_voter_v2' import { Program } from '@project-serum/anchor' import { fetchTokenOwnerRecordByPubkey } from '@hooks/queries/tokenOwnerRecord' import { StakeConnection as PythClient } from '@pythnetwork/staking' +import { getVotingNfts } from '@hooks/queries/plugins/nftVoter' export type UpdateVoterWeightRecordTypes = | 'castVote' @@ -113,7 +113,6 @@ export class VotingClient { client: Client | undefined realm: ProgramAccount | undefined walletPk: PublicKey | null | undefined - votingNfts: DasNftObject[] heliumVsrVotingPositions: PositionWithMeta[] gatewayToken: PublicKey oracles: PublicKey[] @@ -124,7 +123,6 @@ export class VotingClient { this.client = client this.realm = realm this.walletPk = walletPk - this.votingNfts = [] this.heliumVsrVotingPositions = [] this.oracles = [] this.instructions = [] @@ -278,6 +276,12 @@ export class VotingClient { instructions ) + const votingNfts = await getVotingNfts( + this.client.program.provider.connection, + realm.pubkey, + walletPk + ) + if (!ON_NFT_VOTER_V2) { console.log('on nft voter v1') const updateVoterWeightRecordIx = await getUpdateVoterWeightRecordInstruction( @@ -285,7 +289,7 @@ export class VotingClient { walletPk, registrar, voterWeightPk, - this.votingNfts, + votingNfts, type ) instructions.push(updateVoterWeightRecordIx) @@ -299,7 +303,7 @@ export class VotingClient { walletPk, registrar, voterWeightPk, - this.votingNfts, + votingNfts, type ) createNftActionTicketIxs?.push(...createNftTicketIxs) @@ -508,6 +512,13 @@ export class VotingClient { this.client, proposal.pubkey ) + + const votingNfts = await getVotingNfts( + this.client.program.provider.connection, + realm.pubkey, + walletPk + ) + if (!ON_NFT_VOTER_V2) { const castNftVoteIxs = await getCastNftVoteInstruction( this.client.program as Program, @@ -516,7 +527,7 @@ export class VotingClient { proposal.pubkey, tokenOwnerRecord, voterWeightPk, - this.votingNfts, + votingNfts, nftVoteRecordsFiltered ) instructions.push(...castNftVoteIxs) @@ -531,7 +542,7 @@ export class VotingClient { proposal.pubkey, tokenOwnerRecord, voterWeightPk, - this.votingNfts, + votingNfts, nftVoteRecordsFiltered ) createNftActionTicketIxs?.push(...castNftVoteTicketIxs) @@ -760,9 +771,6 @@ export class VotingClient { voterWeightRecordBump, } } - _setCurrentVoterNfts = (nfts: DasNftObject[]) => { - this.votingNfts = nfts - } _setCurrentHeliumVsrPositions = (positions: PositionWithMeta[]) => { this.heliumVsrVotingPositions = positions }