mirror of https://github.com/certusone/oyster.git
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:
parent
7f60b40d7a
commit
778265c0d6
|
@ -67,7 +67,7 @@ export const PROGRAM_IDS = [
|
|||
{
|
||||
name: 'mainnet-beta',
|
||||
governance: () => ({
|
||||
programId: new PublicKey('GovergMfhoNZePj4v86rLXZSN4DeFSLmvKEgWCch1Zuu'),
|
||||
programId: new PublicKey('GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw'),
|
||||
}),
|
||||
wormhole: () => ({
|
||||
pubkey: new PublicKey('WormT3McKhFJ2RkiGpdw9GKvNCrB2aB54gb2uV9MfQC'),
|
||||
|
@ -88,7 +88,7 @@ export const PROGRAM_IDS = [
|
|||
{
|
||||
name: 'testnet',
|
||||
governance: () => ({
|
||||
programId: new PublicKey('GovergMfhoNZePj4v86rLXZSN4DeFSLmvKEgWCch1Zuu'),
|
||||
programId: new PublicKey('GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw'),
|
||||
}),
|
||||
wormhole: () => ({
|
||||
pubkey: new PublicKey('5gQf5AUhAgWYgUCt9ouShm9H7dzzXUsLdssYwe5krKhg'),
|
||||
|
@ -107,7 +107,7 @@ export const PROGRAM_IDS = [
|
|||
{
|
||||
name: 'devnet',
|
||||
governance: () => ({
|
||||
programId: new PublicKey('GovergMfhoNZePj4v86rLXZSN4DeFSLmvKEgWCch1Zuu'),
|
||||
programId: new PublicKey('GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw'),
|
||||
}),
|
||||
wormhole: () => ({
|
||||
pubkey: new PublicKey('WormT3McKhFJ2RkiGpdw9GKvNCrB2aB54gb2uV9MfQC'),
|
||||
|
@ -125,7 +125,7 @@ export const PROGRAM_IDS = [
|
|||
{
|
||||
name: 'localnet',
|
||||
governance: () => ({
|
||||
programId: new PublicKey('GovergMfhoNZePj4v86rLXZSN4DeFSLmvKEgWCch1Zuu'),
|
||||
programId: new PublicKey('GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw'),
|
||||
}),
|
||||
wormhole: () => ({
|
||||
pubkey: new PublicKey('WormT3McKhFJ2RkiGpdw9GKvNCrB2aB54gb2uV9MfQC'),
|
||||
|
|
|
@ -33,7 +33,7 @@ export function RealmDepositBadge({
|
|||
)}`}
|
||||
</span>
|
||||
)}
|
||||
{communityTokenOwnerRecord && councilTokenOwnerRecord && ', '}
|
||||
{communityTokenOwnerRecord && councilTokenOwnerRecord && ' | '}
|
||||
{councilTokenOwnerRecord && (
|
||||
<span>
|
||||
{`council tokens: ${formatTokenAmount(
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
import { PublicKey } from '@solana/web3.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
|
||||
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 {
|
||||
accountType = GovernanceAccountType.Realm;
|
||||
|
||||
communityMint: PublicKey;
|
||||
|
||||
reserved: BN;
|
||||
|
||||
councilMint: PublicKey | undefined;
|
||||
|
||||
name: string;
|
||||
|
||||
constructor(args: {
|
||||
communityMint: PublicKey;
|
||||
reserved: BN;
|
||||
councilMint: PublicKey | undefined;
|
||||
name: string;
|
||||
}) {
|
||||
this.communityMint = args.communityMint;
|
||||
this.reserved = args.reserved;
|
||||
this.councilMint = args.councilMint;
|
||||
this.name = args.name;
|
||||
}
|
||||
|
@ -81,31 +107,42 @@ export class Realm {
|
|||
export class GovernanceConfig {
|
||||
realm: PublicKey;
|
||||
governedAccount: PublicKey;
|
||||
yesVoteThresholdPercentage: number;
|
||||
minTokensToCreateProposal: number;
|
||||
voteThresholdPercentageType: VoteThresholdPercentageType;
|
||||
voteThresholdPercentage: number;
|
||||
minTokensToCreateProposal: BN;
|
||||
minInstructionHoldUpTime: number;
|
||||
maxVotingTime: number;
|
||||
voteWeightSource: VoteWeightSource;
|
||||
proposalCoolOffTime: number;
|
||||
|
||||
constructor(args: {
|
||||
realm: PublicKey;
|
||||
governedAccount: PublicKey;
|
||||
yesVoteThresholdPercentage: number;
|
||||
minTokensToCreateProposal: number;
|
||||
voteThresholdPercentageType?: VoteThresholdPercentageType;
|
||||
voteThresholdPercentage: number;
|
||||
minTokensToCreateProposal: BN;
|
||||
minInstructionHoldUpTime: number;
|
||||
maxVotingTime: number;
|
||||
voteWeightSource?: VoteWeightSource;
|
||||
proposalCoolOffTime?: number;
|
||||
}) {
|
||||
this.realm = args.realm;
|
||||
this.governedAccount = args.governedAccount;
|
||||
this.yesVoteThresholdPercentage = args.yesVoteThresholdPercentage;
|
||||
this.voteThresholdPercentageType =
|
||||
args.voteThresholdPercentageType ?? VoteThresholdPercentageType.YesVote;
|
||||
this.voteThresholdPercentage = args.voteThresholdPercentage;
|
||||
this.minTokensToCreateProposal = args.minTokensToCreateProposal;
|
||||
this.minInstructionHoldUpTime = args.minInstructionHoldUpTime;
|
||||
this.maxVotingTime = args.maxVotingTime;
|
||||
this.voteWeightSource = args.voteWeightSource ?? VoteWeightSource.Deposit;
|
||||
this.proposalCoolOffTime = args.proposalCoolOffTime ?? 0;
|
||||
}
|
||||
}
|
||||
|
||||
export class Governance {
|
||||
accountType: GovernanceAccountType;
|
||||
config: GovernanceConfig;
|
||||
reserved: BN;
|
||||
proposalCount: number;
|
||||
|
||||
isProgramGovernance() {
|
||||
|
@ -127,10 +164,12 @@ export class Governance {
|
|||
constructor(args: {
|
||||
accountType: number;
|
||||
config: GovernanceConfig;
|
||||
reserved?: BN;
|
||||
proposalCount: number;
|
||||
}) {
|
||||
this.accountType = args.accountType;
|
||||
this.config = args.config;
|
||||
this.reserved = args.reserved ?? ZERO;
|
||||
this.proposalCount = args.proposalCount;
|
||||
}
|
||||
}
|
||||
|
@ -146,12 +185,14 @@ export class TokenOwnerRecord {
|
|||
|
||||
governingTokenDepositAmount: BN;
|
||||
|
||||
governanceDelegate?: PublicKey;
|
||||
|
||||
unrelinquishedVotesCount: number;
|
||||
|
||||
totalVotesCount: number;
|
||||
|
||||
reserved: BN;
|
||||
|
||||
governanceDelegate?: PublicKey;
|
||||
|
||||
constructor(args: {
|
||||
realm: PublicKey;
|
||||
governingTokenMint: PublicKey;
|
||||
|
@ -159,6 +200,7 @@ export class TokenOwnerRecord {
|
|||
governingTokenDepositAmount: BN;
|
||||
unrelinquishedVotesCount: number;
|
||||
totalVotesCount: number;
|
||||
reserved: BN;
|
||||
}) {
|
||||
this.realm = args.realm;
|
||||
this.governingTokenMint = args.governingTokenMint;
|
||||
|
@ -166,6 +208,7 @@ export class TokenOwnerRecord {
|
|||
this.governingTokenDepositAmount = args.governingTokenDepositAmount;
|
||||
this.unrelinquishedVotesCount = args.unrelinquishedVotesCount;
|
||||
this.totalVotesCount = args.totalVotesCount;
|
||||
this.reserved = args.reserved;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -222,31 +265,35 @@ export class Proposal {
|
|||
|
||||
signatoriesSignedOffCount: number;
|
||||
|
||||
descriptionLink: string;
|
||||
|
||||
name: string;
|
||||
|
||||
yesVotesCount: BN;
|
||||
|
||||
noVotesCount: BN;
|
||||
|
||||
instructionsExecutedCount: number;
|
||||
|
||||
instructionsCount: number;
|
||||
|
||||
instructionsNextIndex: number;
|
||||
|
||||
draftAt: BN;
|
||||
|
||||
signingOffAt: BN | null;
|
||||
|
||||
votingAt: BN | null;
|
||||
|
||||
votingAtSlot: BN | null;
|
||||
|
||||
votingCompletedAt: BN | null;
|
||||
|
||||
executingAt: BN | null;
|
||||
|
||||
closedAt: BN | null;
|
||||
|
||||
instructionsExecutedCount: number;
|
||||
executionFlags: InstructionExecutionFlags | null;
|
||||
|
||||
instructionsCount: number;
|
||||
name: string;
|
||||
|
||||
instructionsNextIndex: number;
|
||||
descriptionLink: string;
|
||||
|
||||
constructor(args: {
|
||||
governance: PublicKey;
|
||||
|
@ -262,12 +309,14 @@ export class Proposal {
|
|||
draftAt: BN;
|
||||
signingOffAt: BN | null;
|
||||
votingAt: BN | null;
|
||||
votingAtSlot: BN | null;
|
||||
votingCompletedAt: BN | null;
|
||||
executingAt: BN | null;
|
||||
closedAt: BN | null;
|
||||
instructionsExecutedCount: number;
|
||||
instructionsCount: number;
|
||||
instructionsNextIndex: number;
|
||||
executionFlags: InstructionExecutionFlags;
|
||||
}) {
|
||||
this.governance = args.governance;
|
||||
this.governingTokenMint = args.governingTokenMint;
|
||||
|
@ -282,12 +331,14 @@ export class Proposal {
|
|||
this.draftAt = args.draftAt;
|
||||
this.signingOffAt = args.signingOffAt;
|
||||
this.votingAt = args.votingAt;
|
||||
this.votingAtSlot = args.votingAtSlot;
|
||||
this.votingCompletedAt = args.votingCompletedAt;
|
||||
this.executingAt = args.executingAt;
|
||||
this.closedAt = args.closedAt;
|
||||
this.instructionsExecutedCount = args.instructionsExecutedCount;
|
||||
this.instructionsCount = args.instructionsCount;
|
||||
this.instructionsNextIndex = args.instructionsNextIndex;
|
||||
this.executionFlags = args.executionFlags;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -391,19 +442,25 @@ export class InstructionData {
|
|||
export class ProposalInstruction {
|
||||
accountType = GovernanceAccountType.ProposalInstruction;
|
||||
proposal: PublicKey;
|
||||
instructionIndex: number;
|
||||
holdUpTime: number;
|
||||
instruction: InstructionData;
|
||||
executedAt: BN | null;
|
||||
executionStatus: InstructionExecutionStatus | null;
|
||||
|
||||
constructor(args: {
|
||||
proposal: PublicKey;
|
||||
instructionIndex: number;
|
||||
holdUpTime: number;
|
||||
instruction: InstructionData;
|
||||
executedAt: BN | null;
|
||||
executionStatus: InstructionExecutionStatus | null;
|
||||
}) {
|
||||
this.proposal = args.proposal;
|
||||
this.instructionIndex = args.instructionIndex;
|
||||
this.holdUpTime = args.holdUpTime;
|
||||
this.instruction = args.instruction;
|
||||
this.executedAt = args.executedAt;
|
||||
this.executionStatus = args.executionStatus;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -60,6 +60,11 @@ export const GovernanceError: Record<number, string> = [
|
|||
"Provided upgrade authority doesn't match current program upgrade authority", // InvalidUpgradeAuthority
|
||||
'Current program upgrade authority must sign transaction', // UpgradeAuthorityMustSign
|
||||
'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) {
|
||||
|
|
|
@ -10,6 +10,7 @@ export async function createUpgradeInstruction(
|
|||
programId: PublicKey,
|
||||
bufferAddress: PublicKey,
|
||||
governance: PublicKey,
|
||||
spillAddress: PublicKey,
|
||||
) {
|
||||
const PROGRAM_IDS = utils.programIds();
|
||||
|
||||
|
@ -35,7 +36,7 @@ export async function createUpgradeInstruction(
|
|||
isSigner: false,
|
||||
},
|
||||
{
|
||||
pubkey: governance,
|
||||
pubkey: spillAddress,
|
||||
isWritable: true,
|
||||
isSigner: false,
|
||||
},
|
||||
|
|
|
@ -259,6 +259,7 @@ export const GOVERNANCE_SCHEMA = new Map<any, any>([
|
|||
fields: [
|
||||
['accountType', 'u8'],
|
||||
['communityMint', 'pubkey'],
|
||||
['reserved', 'u64'],
|
||||
['councilMint', { kind: 'option', type: 'pubkey' }],
|
||||
['name', 'string'],
|
||||
],
|
||||
|
@ -271,6 +272,7 @@ export const GOVERNANCE_SCHEMA = new Map<any, any>([
|
|||
fields: [
|
||||
['accountType', 'u8'],
|
||||
['config', GovernanceConfig],
|
||||
['reserved', 'u64'],
|
||||
['proposalCount', 'u32'],
|
||||
],
|
||||
},
|
||||
|
@ -282,10 +284,13 @@ export const GOVERNANCE_SCHEMA = new Map<any, any>([
|
|||
fields: [
|
||||
['realm', 'pubkey'],
|
||||
['governedAccount', 'pubkey'],
|
||||
['yesVoteThresholdPercentage', 'u8'],
|
||||
['minTokensToCreateProposal', 'u16'],
|
||||
['voteThresholdPercentageType', 'u8'],
|
||||
['voteThresholdPercentage', 'u8'],
|
||||
['minTokensToCreateProposal', 'u64'],
|
||||
['minInstructionHoldUpTime', 'u32'],
|
||||
['maxVotingTime', 'u32'],
|
||||
['voteWeightSource', 'u8'],
|
||||
['proposalCoolOffTime', 'u32'],
|
||||
],
|
||||
},
|
||||
],
|
||||
|
@ -299,9 +304,10 @@ export const GOVERNANCE_SCHEMA = new Map<any, any>([
|
|||
['governingTokenMint', 'pubkey'],
|
||||
['governingTokenOwner', 'pubkey'],
|
||||
['governingTokenDepositAmount', 'u64'],
|
||||
['governanceDelegate', { kind: 'option', type: 'pubkey' }],
|
||||
['unrelinquishedVotesCount', 'u32'],
|
||||
['totalVotesCount', 'u32'],
|
||||
['reserved', 'u64'],
|
||||
['governanceDelegate', { kind: 'option', type: 'pubkey' }],
|
||||
],
|
||||
},
|
||||
],
|
||||
|
@ -317,19 +323,21 @@ export const GOVERNANCE_SCHEMA = new Map<any, any>([
|
|||
['tokenOwnerRecord', 'pubkey'],
|
||||
['signatoriesCount', 'u8'],
|
||||
['signatoriesSignedOffCount', 'u8'],
|
||||
['descriptionLink', 'string'],
|
||||
['name', 'string'],
|
||||
['yesVotesCount', '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'],
|
||||
['instructionsCount', '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: [
|
||||
['accountType', 'u8'],
|
||||
['proposal', 'pubkey'],
|
||||
['instructionIndex', 'u16'],
|
||||
['holdUpTime', 'u32'],
|
||||
['instruction', InstructionData],
|
||||
['executedAt', { kind: 'option', type: 'u64' }],
|
||||
['executionStatus', { kind: 'option', type: 'u8' }],
|
||||
],
|
||||
},
|
||||
],
|
||||
|
|
|
@ -466,10 +466,10 @@ function getMinRequiredYesVoteScore(
|
|||
governingTokenMint: MintInfo,
|
||||
): string {
|
||||
const minVotes =
|
||||
governance.info.config.yesVoteThresholdPercentage === 100
|
||||
governance.info.config.voteThresholdPercentage === 100
|
||||
? governingTokenMint.supply
|
||||
: governingTokenMint.supply
|
||||
.mul(new BN(governance.info.config.yesVoteThresholdPercentage))
|
||||
.mul(new BN(governance.info.config.voteThresholdPercentage))
|
||||
.div(new BN(100));
|
||||
|
||||
return new BigNumber(minVotes.toString())
|
||||
|
|
|
@ -76,7 +76,7 @@ export function InstructionCard({
|
|||
<>
|
||||
<p>{`${LABELS.INSTRUCTION}: ${instructionDetails.dataBase64}`}</p>
|
||||
<p>
|
||||
{LABELS.HOLD_UP_TIME_DAYS}: {instruction.info.holdUpTime}
|
||||
{LABELS.HOLD_UP_TIME_DAYS}: {instruction.info.holdUpTime / 86400}
|
||||
</p>
|
||||
</>
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
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 { PublicKey, TransactionInstruction } from '@solana/web3.js';
|
||||
import {
|
||||
|
@ -18,7 +18,8 @@ import { AccountFormItem } from '../../../components/AccountFormItem/accountForm
|
|||
import { Governance } from '../../../models/accounts';
|
||||
import { createUpgradeInstruction } from '../../../models/sdkInstructions';
|
||||
import { serializeInstructionToBase64 } from '../../../models/serialisation';
|
||||
import { formDefaults, formVerticalLayout } from '../../../tools/forms';
|
||||
import { formDefaults } from '../../../tools/forms';
|
||||
const { useWallet } = contexts.Wallet;
|
||||
|
||||
export default function InstructionInput({
|
||||
governance,
|
||||
|
@ -116,17 +117,24 @@ const UpgradeProgramForm = ({
|
|||
governance: ParsedAccount<Governance>;
|
||||
onCreateInstruction: (instruction: TransactionInstruction) => void;
|
||||
}) => {
|
||||
const { wallet } = useWallet();
|
||||
|
||||
if (!wallet?.publicKey) {
|
||||
return <div>Wallet not connected</div>;
|
||||
}
|
||||
|
||||
const onCreate = async ({ bufferAddress }: { bufferAddress: string }) => {
|
||||
const upgradeIx = await createUpgradeInstruction(
|
||||
governance.info.config.governedAccount,
|
||||
new PublicKey(bufferAddress),
|
||||
governance.pubkey,
|
||||
wallet.publicKey!,
|
||||
);
|
||||
onCreateInstruction(upgradeIx);
|
||||
};
|
||||
|
||||
return (
|
||||
<Form {...formVerticalLayout} form={form} onFinish={onCreate}>
|
||||
<Form {...formDefaults} form={form} onFinish={onCreate}>
|
||||
<Form.Item label="program id">
|
||||
<ExplorerLink
|
||||
address={governance.info.config.governedAccount}
|
||||
|
@ -136,6 +144,9 @@ const UpgradeProgramForm = ({
|
|||
<Form.Item label="upgrade authority (governance account)">
|
||||
<ExplorerLink address={governance.pubkey} type="address" />
|
||||
</Form.Item>
|
||||
<Form.Item label="spill account (wallet)">
|
||||
<ExplorerLink address={wallet.publicKey} type="address" />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
name="bufferAddress"
|
||||
label="buffer address"
|
||||
|
@ -179,7 +190,7 @@ const MintToForm = ({
|
|||
|
||||
return (
|
||||
<Form
|
||||
{...formVerticalLayout}
|
||||
{...formDefaults}
|
||||
form={form}
|
||||
onFinish={onCreate}
|
||||
initialValues={{ amount: 1 }}
|
||||
|
|
|
@ -12,7 +12,7 @@ import { useProposalAuthority } from '../../../hooks/apiHooks';
|
|||
import { insertInstruction } from '../../../actions/insertInstruction';
|
||||
import '../style.less';
|
||||
|
||||
import { formVerticalLayout } from '../../../tools/forms';
|
||||
import { formDefaults } from '../../../tools/forms';
|
||||
import InstructionInput from './InstructionInput';
|
||||
|
||||
const { useWallet } = contexts.Wallet;
|
||||
|
@ -47,7 +47,7 @@ export function NewInstructionCard({
|
|||
proposal,
|
||||
proposalAuthority!.pubkey,
|
||||
index,
|
||||
values.holdUpTime,
|
||||
values.holdUpTime * 86400,
|
||||
values.instruction,
|
||||
);
|
||||
|
||||
|
@ -57,18 +57,20 @@ export function NewInstructionCard({
|
|||
}
|
||||
};
|
||||
|
||||
const minHoldUpTime = governance.info.config.minInstructionHoldUpTime / 86400;
|
||||
|
||||
return !proposalAuthority ? null : (
|
||||
<Card
|
||||
title="New Instruction"
|
||||
actions={[<SaveOutlined key="save" onClick={form.submit} />]}
|
||||
>
|
||||
<Form
|
||||
{...formVerticalLayout}
|
||||
{...formDefaults}
|
||||
form={form}
|
||||
name="control-hooks"
|
||||
onFinish={onFinish}
|
||||
initialValues={{
|
||||
holdUpTime: governance.info.config.minInstructionHoldUpTime,
|
||||
holdUpTime: minHoldUpTime,
|
||||
}}
|
||||
>
|
||||
<Form.Item
|
||||
|
@ -76,15 +78,12 @@ export function NewInstructionCard({
|
|||
label={LABELS.HOLD_UP_TIME_DAYS}
|
||||
rules={[{ required: true }]}
|
||||
>
|
||||
<InputNumber
|
||||
maxLength={64}
|
||||
min={governance.info.config.minInstructionHoldUpTime}
|
||||
/>
|
||||
<InputNumber min={minHoldUpTime} />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name="instruction"
|
||||
label="Instruction"
|
||||
label="instruction"
|
||||
rules={[{ required: true }]}
|
||||
>
|
||||
<InstructionInput governance={governance}></InstructionInput>
|
||||
|
|
|
@ -15,6 +15,7 @@ import { useKeyParam } from '../../hooks/useKeyParam';
|
|||
import { ModalFormAction } from '../../components/ModalFormAction/modalFormAction';
|
||||
|
||||
import { AccountFormItem } from '../../components/AccountFormItem/accountFormItem';
|
||||
import BN from 'bn.js';
|
||||
|
||||
const { useWallet } = contexts.Wallet;
|
||||
const { useConnection } = contexts.Connection;
|
||||
|
@ -42,8 +43,8 @@ export function RegisterGovernance({
|
|||
const config = new GovernanceConfig({
|
||||
realm: realmKey,
|
||||
governedAccount: new PublicKey(values.governedAccountAddress),
|
||||
yesVoteThresholdPercentage: values.yesVoteThresholdPercentage,
|
||||
minTokensToCreateProposal: values.minTokensToCreateProposal,
|
||||
voteThresholdPercentage: values.yesVoteThresholdPercentage,
|
||||
minTokensToCreateProposal: new BN(values.minTokensToCreateProposal),
|
||||
minInstructionHoldUpTime: values.minInstructionHoldUpTime * 86400,
|
||||
maxVotingTime: values.maxVotingTime * 86400,
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue