Governance: future proofing for v2 (#124)

* chore: update Governance account

* chore: update Proposal account

* chore: Update ProposalInstruction account

* chore: Update Realm account

* chore: update TokenOwnerRecord account

* fix: add spill address to upgrade instruction

* fix: display units for hold up time

* chore: update program id
This commit is contained in:
Sebastian Bor 2021-07-01 12:21:55 +01:00 committed by GitHub
parent 7f60b40d7a
commit 778265c0d6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 134 additions and 50 deletions

View File

@ -67,7 +67,7 @@ export const PROGRAM_IDS = [
{ {
name: 'mainnet-beta', name: 'mainnet-beta',
governance: () => ({ governance: () => ({
programId: new PublicKey('GovergMfhoNZePj4v86rLXZSN4DeFSLmvKEgWCch1Zuu'), programId: new PublicKey('GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw'),
}), }),
wormhole: () => ({ wormhole: () => ({
pubkey: new PublicKey('WormT3McKhFJ2RkiGpdw9GKvNCrB2aB54gb2uV9MfQC'), pubkey: new PublicKey('WormT3McKhFJ2RkiGpdw9GKvNCrB2aB54gb2uV9MfQC'),
@ -88,7 +88,7 @@ export const PROGRAM_IDS = [
{ {
name: 'testnet', name: 'testnet',
governance: () => ({ governance: () => ({
programId: new PublicKey('GovergMfhoNZePj4v86rLXZSN4DeFSLmvKEgWCch1Zuu'), programId: new PublicKey('GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw'),
}), }),
wormhole: () => ({ wormhole: () => ({
pubkey: new PublicKey('5gQf5AUhAgWYgUCt9ouShm9H7dzzXUsLdssYwe5krKhg'), pubkey: new PublicKey('5gQf5AUhAgWYgUCt9ouShm9H7dzzXUsLdssYwe5krKhg'),
@ -107,7 +107,7 @@ export const PROGRAM_IDS = [
{ {
name: 'devnet', name: 'devnet',
governance: () => ({ governance: () => ({
programId: new PublicKey('GovergMfhoNZePj4v86rLXZSN4DeFSLmvKEgWCch1Zuu'), programId: new PublicKey('GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw'),
}), }),
wormhole: () => ({ wormhole: () => ({
pubkey: new PublicKey('WormT3McKhFJ2RkiGpdw9GKvNCrB2aB54gb2uV9MfQC'), pubkey: new PublicKey('WormT3McKhFJ2RkiGpdw9GKvNCrB2aB54gb2uV9MfQC'),
@ -125,7 +125,7 @@ export const PROGRAM_IDS = [
{ {
name: 'localnet', name: 'localnet',
governance: () => ({ governance: () => ({
programId: new PublicKey('GovergMfhoNZePj4v86rLXZSN4DeFSLmvKEgWCch1Zuu'), programId: new PublicKey('GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw'),
}), }),
wormhole: () => ({ wormhole: () => ({
pubkey: new PublicKey('WormT3McKhFJ2RkiGpdw9GKvNCrB2aB54gb2uV9MfQC'), pubkey: new PublicKey('WormT3McKhFJ2RkiGpdw9GKvNCrB2aB54gb2uV9MfQC'),

View File

@ -33,7 +33,7 @@ export function RealmDepositBadge({
)}`} )}`}
</span> </span>
)} )}
{communityTokenOwnerRecord && councilTokenOwnerRecord && ', '} {communityTokenOwnerRecord && councilTokenOwnerRecord && ' | '}
{councilTokenOwnerRecord && ( {councilTokenOwnerRecord && (
<span> <span>
{`council tokens: ${formatTokenAmount( {`council tokens: ${formatTokenAmount(

View File

@ -1,6 +1,8 @@
import { PublicKey } from '@solana/web3.js'; import { PublicKey } from '@solana/web3.js';
import BN from 'bn.js'; import BN from 'bn.js';
import { utils } from '@oyster/common'; import { utils, constants } from '@oyster/common';
const { ZERO } = constants;
/// Seed prefix for Governance Program PDAs /// Seed prefix for Governance Program PDAs
export const GOVERNANCE_PROGRAM_SEED = 'governance'; export const GOVERNANCE_PROGRAM_SEED = 'governance';
@ -58,21 +60,45 @@ export function getAccountTypes(accountClass: GovernanceAccountClass) {
} }
} }
export enum VoteThresholdPercentageType {
YesVote,
Quorum,
}
export enum VoteWeightSource {
Deposit,
Snapshot,
}
export enum InstructionExecutionStatus {
Success,
Error,
}
export enum InstructionExecutionFlags {
Ordered,
UseTransaction,
}
export class Realm { export class Realm {
accountType = GovernanceAccountType.Realm; accountType = GovernanceAccountType.Realm;
communityMint: PublicKey; communityMint: PublicKey;
reserved: BN;
councilMint: PublicKey | undefined; councilMint: PublicKey | undefined;
name: string; name: string;
constructor(args: { constructor(args: {
communityMint: PublicKey; communityMint: PublicKey;
reserved: BN;
councilMint: PublicKey | undefined; councilMint: PublicKey | undefined;
name: string; name: string;
}) { }) {
this.communityMint = args.communityMint; this.communityMint = args.communityMint;
this.reserved = args.reserved;
this.councilMint = args.councilMint; this.councilMint = args.councilMint;
this.name = args.name; this.name = args.name;
} }
@ -81,31 +107,42 @@ export class Realm {
export class GovernanceConfig { export class GovernanceConfig {
realm: PublicKey; realm: PublicKey;
governedAccount: PublicKey; governedAccount: PublicKey;
yesVoteThresholdPercentage: number; voteThresholdPercentageType: VoteThresholdPercentageType;
minTokensToCreateProposal: number; voteThresholdPercentage: number;
minTokensToCreateProposal: BN;
minInstructionHoldUpTime: number; minInstructionHoldUpTime: number;
maxVotingTime: number; maxVotingTime: number;
voteWeightSource: VoteWeightSource;
proposalCoolOffTime: number;
constructor(args: { constructor(args: {
realm: PublicKey; realm: PublicKey;
governedAccount: PublicKey; governedAccount: PublicKey;
yesVoteThresholdPercentage: number; voteThresholdPercentageType?: VoteThresholdPercentageType;
minTokensToCreateProposal: number; voteThresholdPercentage: number;
minTokensToCreateProposal: BN;
minInstructionHoldUpTime: number; minInstructionHoldUpTime: number;
maxVotingTime: number; maxVotingTime: number;
voteWeightSource?: VoteWeightSource;
proposalCoolOffTime?: number;
}) { }) {
this.realm = args.realm; this.realm = args.realm;
this.governedAccount = args.governedAccount; this.governedAccount = args.governedAccount;
this.yesVoteThresholdPercentage = args.yesVoteThresholdPercentage; this.voteThresholdPercentageType =
args.voteThresholdPercentageType ?? VoteThresholdPercentageType.YesVote;
this.voteThresholdPercentage = args.voteThresholdPercentage;
this.minTokensToCreateProposal = args.minTokensToCreateProposal; this.minTokensToCreateProposal = args.minTokensToCreateProposal;
this.minInstructionHoldUpTime = args.minInstructionHoldUpTime; this.minInstructionHoldUpTime = args.minInstructionHoldUpTime;
this.maxVotingTime = args.maxVotingTime; this.maxVotingTime = args.maxVotingTime;
this.voteWeightSource = args.voteWeightSource ?? VoteWeightSource.Deposit;
this.proposalCoolOffTime = args.proposalCoolOffTime ?? 0;
} }
} }
export class Governance { export class Governance {
accountType: GovernanceAccountType; accountType: GovernanceAccountType;
config: GovernanceConfig; config: GovernanceConfig;
reserved: BN;
proposalCount: number; proposalCount: number;
isProgramGovernance() { isProgramGovernance() {
@ -127,10 +164,12 @@ export class Governance {
constructor(args: { constructor(args: {
accountType: number; accountType: number;
config: GovernanceConfig; config: GovernanceConfig;
reserved?: BN;
proposalCount: number; proposalCount: number;
}) { }) {
this.accountType = args.accountType; this.accountType = args.accountType;
this.config = args.config; this.config = args.config;
this.reserved = args.reserved ?? ZERO;
this.proposalCount = args.proposalCount; this.proposalCount = args.proposalCount;
} }
} }
@ -146,12 +185,14 @@ export class TokenOwnerRecord {
governingTokenDepositAmount: BN; governingTokenDepositAmount: BN;
governanceDelegate?: PublicKey;
unrelinquishedVotesCount: number; unrelinquishedVotesCount: number;
totalVotesCount: number; totalVotesCount: number;
reserved: BN;
governanceDelegate?: PublicKey;
constructor(args: { constructor(args: {
realm: PublicKey; realm: PublicKey;
governingTokenMint: PublicKey; governingTokenMint: PublicKey;
@ -159,6 +200,7 @@ export class TokenOwnerRecord {
governingTokenDepositAmount: BN; governingTokenDepositAmount: BN;
unrelinquishedVotesCount: number; unrelinquishedVotesCount: number;
totalVotesCount: number; totalVotesCount: number;
reserved: BN;
}) { }) {
this.realm = args.realm; this.realm = args.realm;
this.governingTokenMint = args.governingTokenMint; this.governingTokenMint = args.governingTokenMint;
@ -166,6 +208,7 @@ export class TokenOwnerRecord {
this.governingTokenDepositAmount = args.governingTokenDepositAmount; this.governingTokenDepositAmount = args.governingTokenDepositAmount;
this.unrelinquishedVotesCount = args.unrelinquishedVotesCount; this.unrelinquishedVotesCount = args.unrelinquishedVotesCount;
this.totalVotesCount = args.totalVotesCount; this.totalVotesCount = args.totalVotesCount;
this.reserved = args.reserved;
} }
} }
@ -222,31 +265,35 @@ export class Proposal {
signatoriesSignedOffCount: number; signatoriesSignedOffCount: number;
descriptionLink: string;
name: string;
yesVotesCount: BN; yesVotesCount: BN;
noVotesCount: BN; noVotesCount: BN;
instructionsExecutedCount: number;
instructionsCount: number;
instructionsNextIndex: number;
draftAt: BN; draftAt: BN;
signingOffAt: BN | null; signingOffAt: BN | null;
votingAt: BN | null; votingAt: BN | null;
votingAtSlot: BN | null;
votingCompletedAt: BN | null; votingCompletedAt: BN | null;
executingAt: BN | null; executingAt: BN | null;
closedAt: BN | null; closedAt: BN | null;
instructionsExecutedCount: number; executionFlags: InstructionExecutionFlags | null;
instructionsCount: number; name: string;
instructionsNextIndex: number; descriptionLink: string;
constructor(args: { constructor(args: {
governance: PublicKey; governance: PublicKey;
@ -262,12 +309,14 @@ export class Proposal {
draftAt: BN; draftAt: BN;
signingOffAt: BN | null; signingOffAt: BN | null;
votingAt: BN | null; votingAt: BN | null;
votingAtSlot: BN | null;
votingCompletedAt: BN | null; votingCompletedAt: BN | null;
executingAt: BN | null; executingAt: BN | null;
closedAt: BN | null; closedAt: BN | null;
instructionsExecutedCount: number; instructionsExecutedCount: number;
instructionsCount: number; instructionsCount: number;
instructionsNextIndex: number; instructionsNextIndex: number;
executionFlags: InstructionExecutionFlags;
}) { }) {
this.governance = args.governance; this.governance = args.governance;
this.governingTokenMint = args.governingTokenMint; this.governingTokenMint = args.governingTokenMint;
@ -282,12 +331,14 @@ export class Proposal {
this.draftAt = args.draftAt; this.draftAt = args.draftAt;
this.signingOffAt = args.signingOffAt; this.signingOffAt = args.signingOffAt;
this.votingAt = args.votingAt; this.votingAt = args.votingAt;
this.votingAtSlot = args.votingAtSlot;
this.votingCompletedAt = args.votingCompletedAt; this.votingCompletedAt = args.votingCompletedAt;
this.executingAt = args.executingAt; this.executingAt = args.executingAt;
this.closedAt = args.closedAt; this.closedAt = args.closedAt;
this.instructionsExecutedCount = args.instructionsExecutedCount; this.instructionsExecutedCount = args.instructionsExecutedCount;
this.instructionsCount = args.instructionsCount; this.instructionsCount = args.instructionsCount;
this.instructionsNextIndex = args.instructionsNextIndex; this.instructionsNextIndex = args.instructionsNextIndex;
this.executionFlags = args.executionFlags;
} }
} }
@ -391,19 +442,25 @@ export class InstructionData {
export class ProposalInstruction { export class ProposalInstruction {
accountType = GovernanceAccountType.ProposalInstruction; accountType = GovernanceAccountType.ProposalInstruction;
proposal: PublicKey; proposal: PublicKey;
instructionIndex: number;
holdUpTime: number; holdUpTime: number;
instruction: InstructionData; instruction: InstructionData;
executedAt: BN | null; executedAt: BN | null;
executionStatus: InstructionExecutionStatus | null;
constructor(args: { constructor(args: {
proposal: PublicKey; proposal: PublicKey;
instructionIndex: number;
holdUpTime: number; holdUpTime: number;
instruction: InstructionData; instruction: InstructionData;
executedAt: BN | null; executedAt: BN | null;
executionStatus: InstructionExecutionStatus | null;
}) { }) {
this.proposal = args.proposal; this.proposal = args.proposal;
this.instructionIndex = args.instructionIndex;
this.holdUpTime = args.holdUpTime; this.holdUpTime = args.holdUpTime;
this.instruction = args.instruction; this.instruction = args.instruction;
this.executedAt = args.executedAt; this.executedAt = args.executedAt;
this.executionStatus = args.executionStatus;
} }
} }

View File

@ -60,6 +60,11 @@ export const GovernanceError: Record<number, string> = [
"Provided upgrade authority doesn't match current program upgrade authority", // InvalidUpgradeAuthority "Provided upgrade authority doesn't match current program upgrade authority", // InvalidUpgradeAuthority
'Current program upgrade authority must sign transaction', // UpgradeAuthorityMustSign 'Current program upgrade authority must sign transaction', // UpgradeAuthorityMustSign
'Given program is not upgradable', //ProgramNotUpgradable 'Given program is not upgradable', //ProgramNotUpgradable
'Invalid token owner', //InvalidTokenOwner
'Current token owner must sign transaction', // TokenOwnerMustSign
'Given VoteThresholdPercentageType is not supported', //VoteThresholdPercentageTypeNotSupported
'Given VoteWeightSource is not supported', //VoteWeightSourceNotSupported
'Proposal cool off time is not supported', // ProposalCoolOffTimeNotSupported
]; ];
export function getTransactionErrorMsg(error: SendTransactionError) { export function getTransactionErrorMsg(error: SendTransactionError) {

View File

@ -10,6 +10,7 @@ export async function createUpgradeInstruction(
programId: PublicKey, programId: PublicKey,
bufferAddress: PublicKey, bufferAddress: PublicKey,
governance: PublicKey, governance: PublicKey,
spillAddress: PublicKey,
) { ) {
const PROGRAM_IDS = utils.programIds(); const PROGRAM_IDS = utils.programIds();
@ -35,7 +36,7 @@ export async function createUpgradeInstruction(
isSigner: false, isSigner: false,
}, },
{ {
pubkey: governance, pubkey: spillAddress,
isWritable: true, isWritable: true,
isSigner: false, isSigner: false,
}, },

View File

@ -259,6 +259,7 @@ export const GOVERNANCE_SCHEMA = new Map<any, any>([
fields: [ fields: [
['accountType', 'u8'], ['accountType', 'u8'],
['communityMint', 'pubkey'], ['communityMint', 'pubkey'],
['reserved', 'u64'],
['councilMint', { kind: 'option', type: 'pubkey' }], ['councilMint', { kind: 'option', type: 'pubkey' }],
['name', 'string'], ['name', 'string'],
], ],
@ -271,6 +272,7 @@ export const GOVERNANCE_SCHEMA = new Map<any, any>([
fields: [ fields: [
['accountType', 'u8'], ['accountType', 'u8'],
['config', GovernanceConfig], ['config', GovernanceConfig],
['reserved', 'u64'],
['proposalCount', 'u32'], ['proposalCount', 'u32'],
], ],
}, },
@ -282,10 +284,13 @@ export const GOVERNANCE_SCHEMA = new Map<any, any>([
fields: [ fields: [
['realm', 'pubkey'], ['realm', 'pubkey'],
['governedAccount', 'pubkey'], ['governedAccount', 'pubkey'],
['yesVoteThresholdPercentage', 'u8'], ['voteThresholdPercentageType', 'u8'],
['minTokensToCreateProposal', 'u16'], ['voteThresholdPercentage', 'u8'],
['minTokensToCreateProposal', 'u64'],
['minInstructionHoldUpTime', 'u32'], ['minInstructionHoldUpTime', 'u32'],
['maxVotingTime', 'u32'], ['maxVotingTime', 'u32'],
['voteWeightSource', 'u8'],
['proposalCoolOffTime', 'u32'],
], ],
}, },
], ],
@ -299,9 +304,10 @@ export const GOVERNANCE_SCHEMA = new Map<any, any>([
['governingTokenMint', 'pubkey'], ['governingTokenMint', 'pubkey'],
['governingTokenOwner', 'pubkey'], ['governingTokenOwner', 'pubkey'],
['governingTokenDepositAmount', 'u64'], ['governingTokenDepositAmount', 'u64'],
['governanceDelegate', { kind: 'option', type: 'pubkey' }],
['unrelinquishedVotesCount', 'u32'], ['unrelinquishedVotesCount', 'u32'],
['totalVotesCount', 'u32'], ['totalVotesCount', 'u32'],
['reserved', 'u64'],
['governanceDelegate', { kind: 'option', type: 'pubkey' }],
], ],
}, },
], ],
@ -317,19 +323,21 @@ export const GOVERNANCE_SCHEMA = new Map<any, any>([
['tokenOwnerRecord', 'pubkey'], ['tokenOwnerRecord', 'pubkey'],
['signatoriesCount', 'u8'], ['signatoriesCount', 'u8'],
['signatoriesSignedOffCount', 'u8'], ['signatoriesSignedOffCount', 'u8'],
['descriptionLink', 'string'],
['name', 'string'],
['yesVotesCount', 'u64'], ['yesVotesCount', 'u64'],
['noVotesCount', 'u64'], ['noVotesCount', 'u64'],
['draftAt', 'u64'],
['signingOffAt', { kind: 'option', type: 'u64' }],
['votingAt', { kind: 'option', type: 'u64' }],
['votingCompletedAt', { kind: 'option', type: 'u64' }],
['executingAt', { kind: 'option', type: 'u64' }],
['closedAt', { kind: 'option', type: 'u64' }],
['instructionsExecutedCount', 'u16'], ['instructionsExecutedCount', 'u16'],
['instructionsCount', 'u16'], ['instructionsCount', 'u16'],
['instructionsNextIndex', 'u16'], ['instructionsNextIndex', 'u16'],
['draftAt', 'u64'],
['signingOffAt', { kind: 'option', type: 'u64' }],
['votingAt', { kind: 'option', type: 'u64' }],
['votingAtSlot', { kind: 'option', type: 'u64' }],
['votingCompletedAt', { kind: 'option', type: 'u64' }],
['executingAt', { kind: 'option', type: 'u64' }],
['closedAt', { kind: 'option', type: 'u64' }],
['executionFlags', { kind: 'option', type: 'u8' }],
['name', 'string'],
['descriptionLink', 'string'],
], ],
}, },
], ],
@ -375,9 +383,11 @@ export const GOVERNANCE_SCHEMA = new Map<any, any>([
fields: [ fields: [
['accountType', 'u8'], ['accountType', 'u8'],
['proposal', 'pubkey'], ['proposal', 'pubkey'],
['instructionIndex', 'u16'],
['holdUpTime', 'u32'], ['holdUpTime', 'u32'],
['instruction', InstructionData], ['instruction', InstructionData],
['executedAt', { kind: 'option', type: 'u64' }], ['executedAt', { kind: 'option', type: 'u64' }],
['executionStatus', { kind: 'option', type: 'u8' }],
], ],
}, },
], ],

View File

@ -466,10 +466,10 @@ function getMinRequiredYesVoteScore(
governingTokenMint: MintInfo, governingTokenMint: MintInfo,
): string { ): string {
const minVotes = const minVotes =
governance.info.config.yesVoteThresholdPercentage === 100 governance.info.config.voteThresholdPercentage === 100
? governingTokenMint.supply ? governingTokenMint.supply
: governingTokenMint.supply : governingTokenMint.supply
.mul(new BN(governance.info.config.yesVoteThresholdPercentage)) .mul(new BN(governance.info.config.voteThresholdPercentage))
.div(new BN(100)); .div(new BN(100));
return new BigNumber(minVotes.toString()) return new BigNumber(minVotes.toString())

View File

@ -76,7 +76,7 @@ export function InstructionCard({
<> <>
<p>{`${LABELS.INSTRUCTION}: ${instructionDetails.dataBase64}`}</p> <p>{`${LABELS.INSTRUCTION}: ${instructionDetails.dataBase64}`}</p>
<p> <p>
{LABELS.HOLD_UP_TIME_DAYS}: {instruction.info.holdUpTime} {LABELS.HOLD_UP_TIME_DAYS}: {instruction.info.holdUpTime / 86400}
</p> </p>
</> </>
} }

View File

@ -1,5 +1,5 @@
import { PlusCircleOutlined } from '@ant-design/icons'; import { PlusCircleOutlined } from '@ant-design/icons';
import { ExplorerLink, ParsedAccount, utils } from '@oyster/common'; import { ExplorerLink, ParsedAccount, utils, contexts } from '@oyster/common';
import { Token } from '@solana/spl-token'; import { Token } from '@solana/spl-token';
import { PublicKey, TransactionInstruction } from '@solana/web3.js'; import { PublicKey, TransactionInstruction } from '@solana/web3.js';
import { import {
@ -18,7 +18,8 @@ import { AccountFormItem } from '../../../components/AccountFormItem/accountForm
import { Governance } from '../../../models/accounts'; import { Governance } from '../../../models/accounts';
import { createUpgradeInstruction } from '../../../models/sdkInstructions'; import { createUpgradeInstruction } from '../../../models/sdkInstructions';
import { serializeInstructionToBase64 } from '../../../models/serialisation'; import { serializeInstructionToBase64 } from '../../../models/serialisation';
import { formDefaults, formVerticalLayout } from '../../../tools/forms'; import { formDefaults } from '../../../tools/forms';
const { useWallet } = contexts.Wallet;
export default function InstructionInput({ export default function InstructionInput({
governance, governance,
@ -116,17 +117,24 @@ const UpgradeProgramForm = ({
governance: ParsedAccount<Governance>; governance: ParsedAccount<Governance>;
onCreateInstruction: (instruction: TransactionInstruction) => void; onCreateInstruction: (instruction: TransactionInstruction) => void;
}) => { }) => {
const { wallet } = useWallet();
if (!wallet?.publicKey) {
return <div>Wallet not connected</div>;
}
const onCreate = async ({ bufferAddress }: { bufferAddress: string }) => { const onCreate = async ({ bufferAddress }: { bufferAddress: string }) => {
const upgradeIx = await createUpgradeInstruction( const upgradeIx = await createUpgradeInstruction(
governance.info.config.governedAccount, governance.info.config.governedAccount,
new PublicKey(bufferAddress), new PublicKey(bufferAddress),
governance.pubkey, governance.pubkey,
wallet.publicKey!,
); );
onCreateInstruction(upgradeIx); onCreateInstruction(upgradeIx);
}; };
return ( return (
<Form {...formVerticalLayout} form={form} onFinish={onCreate}> <Form {...formDefaults} form={form} onFinish={onCreate}>
<Form.Item label="program id"> <Form.Item label="program id">
<ExplorerLink <ExplorerLink
address={governance.info.config.governedAccount} address={governance.info.config.governedAccount}
@ -136,6 +144,9 @@ const UpgradeProgramForm = ({
<Form.Item label="upgrade authority (governance account)"> <Form.Item label="upgrade authority (governance account)">
<ExplorerLink address={governance.pubkey} type="address" /> <ExplorerLink address={governance.pubkey} type="address" />
</Form.Item> </Form.Item>
<Form.Item label="spill account (wallet)">
<ExplorerLink address={wallet.publicKey} type="address" />
</Form.Item>
<Form.Item <Form.Item
name="bufferAddress" name="bufferAddress"
label="buffer address" label="buffer address"
@ -179,7 +190,7 @@ const MintToForm = ({
return ( return (
<Form <Form
{...formVerticalLayout} {...formDefaults}
form={form} form={form}
onFinish={onCreate} onFinish={onCreate}
initialValues={{ amount: 1 }} initialValues={{ amount: 1 }}

View File

@ -12,7 +12,7 @@ import { useProposalAuthority } from '../../../hooks/apiHooks';
import { insertInstruction } from '../../../actions/insertInstruction'; import { insertInstruction } from '../../../actions/insertInstruction';
import '../style.less'; import '../style.less';
import { formVerticalLayout } from '../../../tools/forms'; import { formDefaults } from '../../../tools/forms';
import InstructionInput from './InstructionInput'; import InstructionInput from './InstructionInput';
const { useWallet } = contexts.Wallet; const { useWallet } = contexts.Wallet;
@ -47,7 +47,7 @@ export function NewInstructionCard({
proposal, proposal,
proposalAuthority!.pubkey, proposalAuthority!.pubkey,
index, index,
values.holdUpTime, values.holdUpTime * 86400,
values.instruction, values.instruction,
); );
@ -57,18 +57,20 @@ export function NewInstructionCard({
} }
}; };
const minHoldUpTime = governance.info.config.minInstructionHoldUpTime / 86400;
return !proposalAuthority ? null : ( return !proposalAuthority ? null : (
<Card <Card
title="New Instruction" title="New Instruction"
actions={[<SaveOutlined key="save" onClick={form.submit} />]} actions={[<SaveOutlined key="save" onClick={form.submit} />]}
> >
<Form <Form
{...formVerticalLayout} {...formDefaults}
form={form} form={form}
name="control-hooks" name="control-hooks"
onFinish={onFinish} onFinish={onFinish}
initialValues={{ initialValues={{
holdUpTime: governance.info.config.minInstructionHoldUpTime, holdUpTime: minHoldUpTime,
}} }}
> >
<Form.Item <Form.Item
@ -76,15 +78,12 @@ export function NewInstructionCard({
label={LABELS.HOLD_UP_TIME_DAYS} label={LABELS.HOLD_UP_TIME_DAYS}
rules={[{ required: true }]} rules={[{ required: true }]}
> >
<InputNumber <InputNumber min={minHoldUpTime} />
maxLength={64}
min={governance.info.config.minInstructionHoldUpTime}
/>
</Form.Item> </Form.Item>
<Form.Item <Form.Item
name="instruction" name="instruction"
label="Instruction" label="instruction"
rules={[{ required: true }]} rules={[{ required: true }]}
> >
<InstructionInput governance={governance}></InstructionInput> <InstructionInput governance={governance}></InstructionInput>

View File

@ -15,6 +15,7 @@ import { useKeyParam } from '../../hooks/useKeyParam';
import { ModalFormAction } from '../../components/ModalFormAction/modalFormAction'; import { ModalFormAction } from '../../components/ModalFormAction/modalFormAction';
import { AccountFormItem } from '../../components/AccountFormItem/accountFormItem'; import { AccountFormItem } from '../../components/AccountFormItem/accountFormItem';
import BN from 'bn.js';
const { useWallet } = contexts.Wallet; const { useWallet } = contexts.Wallet;
const { useConnection } = contexts.Connection; const { useConnection } = contexts.Connection;
@ -42,8 +43,8 @@ export function RegisterGovernance({
const config = new GovernanceConfig({ const config = new GovernanceConfig({
realm: realmKey, realm: realmKey,
governedAccount: new PublicKey(values.governedAccountAddress), governedAccount: new PublicKey(values.governedAccountAddress),
yesVoteThresholdPercentage: values.yesVoteThresholdPercentage, voteThresholdPercentage: values.yesVoteThresholdPercentage,
minTokensToCreateProposal: values.minTokensToCreateProposal, minTokensToCreateProposal: new BN(values.minTokensToCreateProposal),
minInstructionHoldUpTime: values.minInstructionHoldUpTime * 86400, minInstructionHoldUpTime: values.minInstructionHoldUpTime * 86400,
maxVotingTime: values.maxVotingTime * 86400, maxVotingTime: values.maxVotingTime * 86400,
}); });