refactor/bugfix: new wallet form being wrong about mint supply (#1667)
This commit is contained in:
parent
dcd194eb91
commit
bca2760d41
|
@ -6,11 +6,7 @@ import asFindable from '@utils/queries/asFindable'
|
|||
import queryClient from './queryClient'
|
||||
|
||||
export const governanceAccountQueryKeys = {
|
||||
all: (cluster: string, kind: string) => [
|
||||
cluster,
|
||||
'Governance Account',
|
||||
`${kind}`,
|
||||
],
|
||||
all: (cluster: string, kind: string) => [cluster, `${kind}`],
|
||||
byPubkey: (cluster: string, kind: string, k: PublicKey) => [
|
||||
...governanceAccountQueryKeys.all(cluster, kind),
|
||||
k.toString(),
|
||||
|
@ -53,7 +49,8 @@ export async function fetchGovernanceAccountByPubkey<
|
|||
kindLabel: string,
|
||||
pubkey: PublicKey
|
||||
) {
|
||||
const f = () => getGovernanceAccount(connection, pubkey, kind)
|
||||
const f = () =>
|
||||
asFindable(() => getGovernanceAccount(connection, pubkey, kind))()
|
||||
return queryClient.fetchQuery({
|
||||
queryKey: governanceAccountQueryKeys.byPubkey(
|
||||
connection.rpcEndpoint,
|
||||
|
|
|
@ -29,6 +29,7 @@ interface Props
|
|||
}
|
||||
|
||||
function Form(props: Props & { title: string; description: string }) {
|
||||
console.log('form props', props);
|
||||
const [showCouncilOptions, setShowCouncilOptions] = useState(
|
||||
props.initialCouncilRules?.canVote || false,
|
||||
);
|
||||
|
|
|
@ -1,6 +1,11 @@
|
|||
import { BN } from '@coral-xyz/anchor';
|
||||
import { BigNumber } from 'bignumber.js';
|
||||
import { produce } from 'immer';
|
||||
|
||||
import {
|
||||
useRealmCommunityMintInfoQuery,
|
||||
useRealmCouncilMintInfoQuery,
|
||||
} from '@hooks/queries/mintInfo';
|
||||
import { ButtonToggle } from '@hub/components/controls/ButtonToggle';
|
||||
import { Input } from '@hub/components/controls/Input';
|
||||
import { Slider } from '@hub/components/controls/Slider';
|
||||
|
@ -12,6 +17,8 @@ import { capitalize } from '@hub/lib/capitalize';
|
|||
import { formatNumber } from '@hub/lib/formatNumber';
|
||||
import { FormProps } from '@hub/types/FormProps';
|
||||
|
||||
import { GovernanceTokenType } from '@hub/types/GovernanceTokenType';
|
||||
|
||||
import { SliderValue } from './SliderValue';
|
||||
import { ValueBlock } from './ValueBlock';
|
||||
import { VoteTippingSelector } from './VoteTippingSelector';
|
||||
|
@ -111,9 +118,27 @@ export function CanVote(props: Props) {
|
|||
}
|
||||
|
||||
export function VotingPowerToCreateProposals(props: Props) {
|
||||
const councilPowerPercent = props.rules.votingPowerToCreateProposals
|
||||
.dividedBy(props.rules.totalSupply)
|
||||
.multipliedBy(100);
|
||||
const communityTokenInfo = useRealmCommunityMintInfoQuery();
|
||||
const councilTokenInfo = useRealmCouncilMintInfoQuery();
|
||||
|
||||
const tokenInfoQuery =
|
||||
props.rules.tokenType === GovernanceTokenType.Community
|
||||
? communityTokenInfo
|
||||
: councilTokenInfo;
|
||||
|
||||
const supply = tokenInfoQuery.data?.result
|
||||
? new BigNumber(
|
||||
tokenInfoQuery.data?.result.supply
|
||||
.div(new BN(Math.pow(10, tokenInfoQuery.data.result.decimals)))
|
||||
.toString(),
|
||||
)
|
||||
: undefined;
|
||||
|
||||
const councilPowerPercent = supply
|
||||
? props.rules.votingPowerToCreateProposals
|
||||
.dividedBy(supply)
|
||||
.multipliedBy(100)
|
||||
: undefined;
|
||||
|
||||
return (
|
||||
<ValueBlock
|
||||
|
@ -144,8 +169,8 @@ export function VotingPowerToCreateProposals(props: Props) {
|
|||
Tokens
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center justify-end">
|
||||
{props.rules.totalSupply.isGreaterThan(0) && (
|
||||
{councilPowerPercent && supply?.isGreaterThan(0) && (
|
||||
<div className="flex items-center justify-end">
|
||||
<div className="mt-1 text-xs text-neutral-500">
|
||||
{councilPowerPercent.isGreaterThan(0)
|
||||
? councilPowerPercent.isLessThan(0.01)
|
||||
|
@ -157,8 +182,8 @@ export function VotingPowerToCreateProposals(props: Props) {
|
|||
: 0}
|
||||
% of token supply
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</ValueBlock>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,12 +1,17 @@
|
|||
import {
|
||||
createSetGovernanceConfig,
|
||||
GovernanceConfig,
|
||||
Realm,
|
||||
VoteThresholdType,
|
||||
VoteTipping,
|
||||
} from '@solana/spl-governance';
|
||||
import type { PublicKey } from '@solana/web3.js';
|
||||
import type { Connection, PublicKey } from '@solana/web3.js';
|
||||
import BigNumber from 'bignumber.js';
|
||||
import BN from 'bn.js';
|
||||
|
||||
import { fetchGovernanceAccountByPubkey } from '@hooks/queries/governanceAccount';
|
||||
import { fetchMintInfoByPubkey } from '@hooks/queries/mintInfo';
|
||||
import queryClient from '@hooks/queries/queryClient';
|
||||
import { GovernanceVoteTipping } from '@hub/types/GovernanceVoteTipping';
|
||||
|
||||
import { MAX_NUM } from './constants';
|
||||
|
@ -32,13 +37,15 @@ function convertVoteTipping(tipping: GovernanceVoteTipping): VoteTipping {
|
|||
}
|
||||
}
|
||||
|
||||
export function createTransaction(
|
||||
export async function createTransaction(
|
||||
connection: Connection,
|
||||
programId: PublicKey,
|
||||
programVersion: number,
|
||||
governance: PublicKey,
|
||||
realmPk: PublicKey,
|
||||
rules: Rules,
|
||||
) {
|
||||
const newConfig = rules2governanceConfig(rules);
|
||||
const newConfig = await rules2governanceConfig(connection, realmPk, rules);
|
||||
|
||||
const instruction = createSetGovernanceConfig(
|
||||
programId,
|
||||
|
@ -50,15 +57,40 @@ export function createTransaction(
|
|||
return instruction;
|
||||
}
|
||||
|
||||
export function rules2governanceConfig(
|
||||
export async function rules2governanceConfig(
|
||||
connection: Connection,
|
||||
realmPk: PublicKey,
|
||||
rules: Omit<Rules, 'governanceAddress' | 'walletAddress'>,
|
||||
) {
|
||||
const realm = await fetchGovernanceAccountByPubkey(
|
||||
connection,
|
||||
Realm,
|
||||
'Realm',
|
||||
realmPk,
|
||||
);
|
||||
if (!realm.result) throw new Error('realm fetch failed');
|
||||
const communityMintInfo = await fetchMintInfoByPubkey(
|
||||
connection,
|
||||
realm.result.account.communityMint,
|
||||
);
|
||||
const councilMintInfo =
|
||||
realm.result.account.config.councilMint !== undefined
|
||||
? await fetchMintInfoByPubkey(
|
||||
connection,
|
||||
realm.result.account.config.councilMint,
|
||||
)
|
||||
: undefined;
|
||||
|
||||
const communityRules = rules.communityTokenRules;
|
||||
const councilRules = rules.councilTokenRules;
|
||||
|
||||
const minCommunityTokensToCreateProposal = new BN(
|
||||
(communityRules.canCreateProposal
|
||||
? communityRules.votingPowerToCreateProposals.shiftedBy(
|
||||
communityRules.tokenMintDecimals.toNumber(),
|
||||
communityMintInfo.result?.decimals ??
|
||||
(() => {
|
||||
throw new Error('communityMintInfo failed to fetch');
|
||||
})(),
|
||||
)
|
||||
: MAX_NUM
|
||||
).toString(),
|
||||
|
@ -67,7 +99,12 @@ export function rules2governanceConfig(
|
|||
const minCouncilTokensToCreateProposal = new BN(
|
||||
(councilRules && councilRules.canCreateProposal
|
||||
? councilRules.votingPowerToCreateProposals.shiftedBy(
|
||||
councilRules.tokenMintDecimals.toNumber(),
|
||||
councilMintInfo?.result?.decimals ??
|
||||
(() => {
|
||||
throw new Error(
|
||||
'councilMintInfo failed to fetch or doesnt exist',
|
||||
);
|
||||
})(),
|
||||
)
|
||||
: MAX_NUM
|
||||
).toString(),
|
||||
|
|
|
@ -57,10 +57,7 @@ const Rules = IT.type({
|
|||
canVeto: IT.boolean,
|
||||
canVote: IT.boolean,
|
||||
quorumPercent: IT.number,
|
||||
tokenMintAddress: PublicKey,
|
||||
tokenMintDecimals: BigNumber,
|
||||
tokenType: GovernanceTokenType,
|
||||
totalSupply: BigNumber,
|
||||
vetoQuorumPercent: IT.number,
|
||||
voteTipping: GovernanceVoteTipping,
|
||||
votingPowerToCreateProposals: BigNumber,
|
||||
|
|
|
@ -2,6 +2,7 @@ import CheckmarkIcon from '@carbon/icons-react/lib/Checkmark';
|
|||
import ChevronLeftIcon from '@carbon/icons-react/lib/ChevronLeft';
|
||||
import EditIcon from '@carbon/icons-react/lib/Edit';
|
||||
import { createInstructionData } from '@solana/spl-governance';
|
||||
import { useConnection } from '@solana/wallet-adapter-react';
|
||||
import { PublicKey } from '@solana/web3.js';
|
||||
import { BigNumber } from 'bignumber.js';
|
||||
import { hoursToSeconds, secondsToHours } from 'date-fns';
|
||||
|
@ -65,6 +66,7 @@ export function EditWalletRules(props: Props) {
|
|||
const { propose } = useCreateProposal();
|
||||
const realm = useRealmQuery().data?.result;
|
||||
const { symbol } = useRealm();
|
||||
const { connection } = useConnection();
|
||||
|
||||
const [result] = useQuery(gql.getGovernanceRulesResp, {
|
||||
query: gql.getGovernanceRules,
|
||||
|
@ -87,12 +89,12 @@ export function EditWalletRules(props: Props) {
|
|||
canVeto: false,
|
||||
canVote: false,
|
||||
quorumPercent: 1,
|
||||
tokenType: GovernanceTokenType.Community,
|
||||
// this isn't a valid value, but it's just to satisfy the types for the
|
||||
// default initialized value
|
||||
tokenMintAddress: props.governanceAddress,
|
||||
tokenMintDecimals: new BigNumber(0),
|
||||
tokenType: GovernanceTokenType.Community,
|
||||
totalSupply: new BigNumber(1),
|
||||
//tokenMintAddress: props.governanceAddress,
|
||||
//tokenMintDecimals: new BigNumber(0),
|
||||
//totalSupply: new BigNumber(1),
|
||||
vetoQuorumPercent: 100,
|
||||
voteTipping: GovernanceVoteTipping.Disabled,
|
||||
votingPowerToCreateProposals: new BigNumber(1),
|
||||
|
@ -311,10 +313,12 @@ export function EditWalletRules(props: Props) {
|
|||
|
||||
setSubmitting(true);
|
||||
|
||||
const instruction = createTransaction(
|
||||
const instruction = await createTransaction(
|
||||
connection,
|
||||
realm.owner,
|
||||
governance.version,
|
||||
governance.governanceAddress,
|
||||
realm.pubkey,
|
||||
{
|
||||
coolOffHours,
|
||||
depositExemptProposalCount,
|
||||
|
|
|
@ -45,7 +45,6 @@ interface Props {
|
|||
className?: string;
|
||||
}
|
||||
|
||||
// TODO generate defaults
|
||||
function NewWalletWithDefaults({
|
||||
defaults,
|
||||
...props
|
||||
|
|
|
@ -51,12 +51,7 @@ const configs2defaults = (configs: GovernanceConfig[]) => {
|
|||
votingPowerToCreateProposals: new BigNumber(
|
||||
highestMinCommunityTokensToCreateProposal.toString(),
|
||||
),
|
||||
// START totally fake dummy values 💀
|
||||
tokenMintAddress: new PublicKey(0),
|
||||
tokenMintDecimals: new BigNumber(0),
|
||||
tokenType: GovernanceTokenType.Community,
|
||||
totalSupply: new BigNumber(1),
|
||||
// END
|
||||
canVeto: false,
|
||||
vetoQuorumPercent: 60,
|
||||
canVote: enableCommunityVote,
|
||||
|
@ -70,12 +65,7 @@ const configs2defaults = (configs: GovernanceConfig[]) => {
|
|||
votingPowerToCreateProposals: new BigNumber(
|
||||
highestMinCouncilTokensToCreateProposal.toString(),
|
||||
),
|
||||
// START totally fake dummy values 💀
|
||||
tokenMintAddress: new PublicKey(0),
|
||||
tokenMintDecimals: new BigNumber(0),
|
||||
tokenType: GovernanceTokenType.Council,
|
||||
totalSupply: new BigNumber(1),
|
||||
// END
|
||||
canVeto: enableCouncilVetoVote,
|
||||
vetoQuorumPercent: 60,
|
||||
canVote: enableCouncilVote,
|
||||
|
|
|
@ -44,7 +44,11 @@ const useNewWalletCallback = (
|
|||
if (tokenOwnerRecord === undefined)
|
||||
throw new Error('insufficient voting power');
|
||||
|
||||
const config = rules2governanceConfig(rules);
|
||||
const config = await rules2governanceConfig(
|
||||
connection.current,
|
||||
realm.pubkey,
|
||||
rules,
|
||||
);
|
||||
|
||||
const instructions: TransactionInstruction[] = [];
|
||||
|
||||
|
|
Loading…
Reference in New Issue