diff --git a/packages/bridge/src/components/EthereumConnect/index.tsx b/packages/bridge/src/components/EthereumConnect/index.tsx
index 0c52d6f..9bfa1c3 100644
--- a/packages/bridge/src/components/EthereumConnect/index.tsx
+++ b/packages/bridge/src/components/EthereumConnect/index.tsx
@@ -1,14 +1,28 @@
import React from 'react';
-import { Button } from 'antd';
+import { Button, Dropdown, Menu } from 'antd';
import { useCorrectNetwork } from '../../hooks/useCorrectNetwork';
import { shortenAddress } from '@oyster/common';
import { useEthereum } from '../../contexts';
export const EthereumConnect = () => {
- const { accounts, onConnectEthereum, connected, walletProvider } = useEthereum();
+ const {
+ accounts,
+ onConnectEthereum,
+ connected,
+ walletProvider,
+ select,
+ } = useEthereum();
const { hasCorrespondingNetworks } = useCorrectNetwork();
+ const menu = (
+
+ );
+
return (
{connected ? (
@@ -28,6 +42,13 @@ export const EthereumConnect = () => {
WRONG NETWORK
)
+ ) : !!walletProvider ? (
+ onConnectEthereum && onConnectEthereum()}
+ overlay={menu}
+ >
+ Connect Ethereum
+
) : (
- } />
+ disconnect()}
+ style={{ marginTop: '8px' }}
+ >
+ Disconnect ETH
+
+ ) : undefined
+ }
+ useWalletBadge={true}
+ left={}
+ />
)}
diff --git a/packages/bridge/src/components/TokenSelectModal/index.tsx b/packages/bridge/src/components/TokenSelectModal/index.tsx
index e6406e4..0132deb 100644
--- a/packages/bridge/src/components/TokenSelectModal/index.tsx
+++ b/packages/bridge/src/components/TokenSelectModal/index.tsx
@@ -119,7 +119,7 @@ export const TokenSelectModal = (props: {
visible={isModalVisible}
onCancel={() => hideModal()}
footer={null}
- className={"token-select-modal"}
+ className={'token-select-modal'}
>
void;
+ disconnect: () => void;
onConnectEthereum?: () => void;
}
@@ -57,6 +59,8 @@ export const EthereumContext = createContext({
accounts: [''],
chainId: 0,
connected: false,
+ select() {},
+ disconnect() {},
walletProvider: null,
});
@@ -142,12 +146,12 @@ export const EthereumProvider: FunctionComponent = ({ children }) => {
}, [setTokens]);
const onConnectEthereum = useCallback(() => {
- if (wallet && providerUrl) {
+ if (wallet && providerUrl && !connected) {
wallet.connect();
- } else {
+ } else if (!connected) {
select();
}
- }, [wallet, providerUrl]);
+ }, [wallet, connected, providerUrl]);
useEffect(() => {
if (wallet) {
@@ -162,6 +166,11 @@ export const EthereumProvider: FunctionComponent = ({ children }) => {
});
wallet.on('disconnect', error => {
setConnected(false);
+ setAccounts([]);
+ // @ts-ignore
+ setChainId(0);
+ // @ts-ignore
+ setProvider(null);
});
// @ts-ignore
wallet.on('accountsChanged', accounts => {
@@ -184,10 +193,10 @@ export const EthereumProvider: FunctionComponent = ({ children }) => {
const close = useCallback(() => setIsModalVisible(false), []);
useEffect(() => {
- if (walletConnected && !connected) {
+ if (walletConnected) {
onConnectEthereum();
}
- }, [walletConnected, connected, providerUrl]);
+ }, [walletConnected, providerUrl]);
return (
{
connected,
chainId,
walletProvider,
+ select,
+ disconnect: () => wallet?.disconnect(),
onConnectEthereum: () => onConnectEthereum(),
}}
>
diff --git a/packages/bridge/src/views/home/index.tsx b/packages/bridge/src/views/home/index.tsx
index e1504a0..31c9a0f 100644
--- a/packages/bridge/src/views/home/index.tsx
+++ b/packages/bridge/src/views/home/index.tsx
@@ -81,7 +81,7 @@ export const HomeView = () => {
style: {},
},
children: (
-
+
{shortenAddress(text, 6)}
),
@@ -98,7 +98,11 @@ export const HomeView = () => {
style: {},
},
children: (
-
+
{shortenAddress(text, 6)}
),
diff --git a/packages/bridge/src/wallet-adapters/metamask.tsx b/packages/bridge/src/wallet-adapters/metamask.tsx
index 44843fa..0fa1d03 100644
--- a/packages/bridge/src/wallet-adapters/metamask.tsx
+++ b/packages/bridge/src/wallet-adapters/metamask.tsx
@@ -1,7 +1,7 @@
import EventEmitter from 'eventemitter3';
import { PublicKey, Transaction } from '@solana/web3.js';
import { notify } from '@oyster/common';
-import { WalletAdapter } from '@solana/wallet-base'
+import { WalletAdapter } from '@solana/wallet-base';
import { ethers } from 'ethers';
export class MetamaskWalletAdapter
@@ -95,8 +95,9 @@ export class MetamaskWalletAdapter
}
disconnect() {
- if (this._publicKey) {
+ if (this._provider) {
this._publicKey = null;
+ this._provider = null;
this.emit('disconnect');
}
}
diff --git a/packages/bridge/src/wallet-adapters/wallet-connect.tsx b/packages/bridge/src/wallet-adapters/wallet-connect.tsx
index bcb6592..002e9c9 100644
--- a/packages/bridge/src/wallet-adapters/wallet-connect.tsx
+++ b/packages/bridge/src/wallet-adapters/wallet-connect.tsx
@@ -1,9 +1,9 @@
import EventEmitter from 'eventemitter3';
import { PublicKey, Transaction } from '@solana/web3.js';
import { notify } from '@oyster/common';
-import { WalletAdapter } from '@solana/wallet-base'
+import { WalletAdapter } from '@solana/wallet-base';
import { ethers } from 'ethers';
-import WalletConnectProvider from "@walletconnect/web3-provider";
+import WalletConnectProvider from '@walletconnect/web3-provider';
export class WalletConnectWalletAdapter
extends EventEmitter
@@ -13,11 +13,13 @@ export class WalletConnectWalletAdapter
_accounts: Array;
_chainID: number;
_provider: any;
+ _walletProvider: any;
constructor() {
super();
this._publicKey = null;
this._provider = null;
+ this._walletProvider = null;
this._accounts = [];
this._chainID = 0;
this._onProcess = false;
@@ -53,44 +55,52 @@ export class WalletConnectWalletAdapter
// Create WalletConnect Provider
const walletConnectProvider = new WalletConnectProvider({
- infuraId: "535ab8649e9f40cface13cbded7d647e",
+ infuraId: '535ab8649e9f40cface13cbded7d647e',
});
- walletConnectProvider.enable().then(()=>{
- const provider = new ethers.providers.Web3Provider(walletConnectProvider);
- const signer = provider.getSigner();
- signer.getAddress().then(account => {
- this._accounts = [account];
- provider.getNetwork().then(network => {
- this._chainID = network.chainId;
- this._provider = provider;
- this.emit('connect');
+ walletConnectProvider
+ .enable()
+ .then(() => {
+ const provider = new ethers.providers.Web3Provider(
+ walletConnectProvider,
+ );
+ const signer = provider.getSigner();
+ signer.getAddress().then(account => {
+ this._accounts = [account];
+ provider.getNetwork().then(network => {
+ this._chainID = network.chainId;
+ this._provider = provider;
+ this._walletProvider = walletConnectProvider;
+ this.emit('connect');
+ });
});
+ // @ts-ignore
+ walletConnectProvider.on(
+ 'disconnect',
+ (code: number, reason: string) => {
+ this.emit('disconnect', { code, reason });
+ },
+ );
+ // @ts-ignore
+ walletConnectProvider.on('accountsChanged', (accounts: string[]) => {
+ this.emit('accountsChanged', accounts);
+ });
+ // @ts-ignore
+ walletConnectProvider.on('chainChanged', (chainId: number) => {
+ this.emit('chainChanged', chainId);
+ });
+ })
+ .catch(() => {
+ this.disconnect();
+ })
+ .finally(() => {
+ this._onProcess = false;
});
- // @ts-ignore
- walletConnectProvider.on('disconnect', (code: number, reason: string) => {
- this.emit('disconnect', {code, reason});
- });
- // @ts-ignore
- walletConnectProvider.on('accountsChanged', (accounts: string[]) => {
- this.emit('accountsChanged', accounts);
- });
- // @ts-ignore
- walletConnectProvider.on('chainChanged', (chainId: number) => {
- this.emit('chainChanged', chainId);
- });
- })
- .catch(() => {
- this.disconnect();
- })
- .finally(() => {
- this._onProcess = false;
- });
-
}
disconnect() {
- if (this._publicKey) {
+ if (this._provider) {
this._publicKey = null;
+ this._walletProvider.disconnect();
this.emit('disconnect');
}
}
diff --git a/packages/common/src/utils/ids.ts b/packages/common/src/utils/ids.ts
index 41582f9..d149880 100644
--- a/packages/common/src/utils/ids.ts
+++ b/packages/common/src/utils/ids.ts
@@ -74,9 +74,9 @@ export const PROGRAM_IDS = [
name: 'testnet',
timelock: () => ({
programAccountId: new PublicKey(
- '32siiZ12jH2i7BM2wtNuTDw2Hs5nBjVQuBh4P8cTSH3i',
+ '7CxEuz8Qtius9aCyJqGnWZyBNvf6WTTNmA8G26BdMTSF',
),
- programId: new PublicKey('5KrVJvesyjdMy6Vq5wfuPSMdw7vWuUvtbHG98wBsEkX6'),
+ programId: new PublicKey('8DevpkpN6CsdczP6rQ64CHraApXFrq96oGm4VjSNCs4q'),
}),
wormhole: () => ({
pubkey: new PublicKey('5gQf5AUhAgWYgUCt9ouShm9H7dzzXUsLdssYwe5krKhg'),
@@ -95,9 +95,9 @@ export const PROGRAM_IDS = [
name: 'devnet',
timelock: () => ({
programAccountId: new PublicKey(
- 'Gc6ktQPgHDxf9GpN6CdLEnkkqj5NfGYJeLDWFLoN3wNb',
+ '8KkpkoDAQaQqjnkCtNXAyk2A8GLmsmWPjBLK7jmahhxZ',
),
- programId: new PublicKey('FmxAXMEKaj7BvgH9zdRNMZZYdAk4mBeRdSQwUoM3QYYw'),
+ programId: new PublicKey('7SH5hE7uBecnfMpGjdPyJupgBhFHaXcNMCEgJbmoVV7t'),
}),
wormhole: () => ({
pubkey: new PublicKey('WormT3McKhFJ2RkiGpdw9GKvNCrB2aB54gb2uV9MfQC'),
diff --git a/packages/proposals/src/actions/addCustomSingleSignerTransaction.ts b/packages/proposals/src/actions/addCustomSingleSignerTransaction.ts
index 82c71c2..1c0bf1e 100644
--- a/packages/proposals/src/actions/addCustomSingleSignerTransaction.ts
+++ b/packages/proposals/src/actions/addCustomSingleSignerTransaction.ts
@@ -89,6 +89,7 @@ export const addCustomSingleSignerTransaction = async (
proposal.pubkey,
sigAccount,
proposal.info.signatoryValidation,
+ proposal.info.config,
transferAuthority.publicKey,
authority,
slot,
diff --git a/packages/proposals/src/actions/createProposal.ts b/packages/proposals/src/actions/createProposal.ts
index 68ddaad..2618cc2 100644
--- a/packages/proposals/src/actions/createProposal.ts
+++ b/packages/proposals/src/actions/createProposal.ts
@@ -70,7 +70,6 @@ export const createProposal = async (
space: TimelockSetLayout.span,
programId: PROGRAM_IDS.timelock.programId,
});
-
signers.push(timelockSetKey);
instructions.push(uninitializedTimelockSetInstruction);
diff --git a/packages/proposals/src/actions/registerProgramGovernance.ts b/packages/proposals/src/actions/registerProgramGovernance.ts
index f5f0d31..71c9118 100644
--- a/packages/proposals/src/actions/registerProgramGovernance.ts
+++ b/packages/proposals/src/actions/registerProgramGovernance.ts
@@ -111,6 +111,7 @@ export const registerProgramGovernance = async (
TimelockType.CustomSingleSignerV1,
uninitializedTimelockConfig.votingEntryRule || VotingEntryRule.Anytime,
uninitializedTimelockConfig.minimumSlotWaitingPeriod || new BN(0),
+ uninitializedTimelockConfig.timeLimit || new BN(0),
uninitializedTimelockConfig.name || '',
),
);
diff --git a/packages/proposals/src/components/Proposal/InstructionCard.tsx b/packages/proposals/src/components/Proposal/InstructionCard.tsx
index 75d83a7..9a41f58 100644
--- a/packages/proposals/src/components/Proposal/InstructionCard.tsx
+++ b/packages/proposals/src/components/Proposal/InstructionCard.tsx
@@ -11,6 +11,7 @@ import { Card, Spin } from 'antd';
import Meta from 'antd/lib/card/Meta';
import React, { useState } from 'react';
import { execute } from '../../actions/execute';
+import { LABELS } from '../../constants';
import {
TimelockSet,
TimelockStateStatus,
@@ -47,7 +48,9 @@ export function InstructionCard({
description={
<>
Instruction: TODO
- Slot: {instruction.info.slot.toNumber()}
+
+ {LABELS.DELAY}: {instruction.info.slot.toNumber()}
+
>
}
/>
@@ -108,7 +111,8 @@ function PlayStatusButton({
};
if (proposal.info.state.status != TimelockStateStatus.Executing) return null;
- if (currSlot < instruction.info.slot.toNumber()) return null;
+ const elapsedTime = currSlot - proposal.info.state.votingEndedAt.toNumber();
+ if (elapsedTime < instruction.info.slot.toNumber()) return null;
if (playing === Playstate.Unplayed)
return (
diff --git a/packages/proposals/src/components/Proposal/NewInstructionCard.tsx b/packages/proposals/src/components/Proposal/NewInstructionCard.tsx
index e54403f..39312f8 100644
--- a/packages/proposals/src/components/Proposal/NewInstructionCard.tsx
+++ b/packages/proposals/src/components/Proposal/NewInstructionCard.tsx
@@ -1,11 +1,16 @@
import React, { useState } from 'react';
import { Card, Progress, Spin } from 'antd';
import { Form, Input } from 'antd';
-import { INSTRUCTION_LIMIT, TimelockSet } from '../../models/timelock';
+import {
+ INSTRUCTION_LIMIT,
+ TimelockConfig,
+ TimelockSet,
+} from '../../models/timelock';
import { contexts, ParsedAccount, hooks, utils } from '@oyster/common';
import { addCustomSingleSignerTransaction } from '../../actions/addCustomSingleSignerTransaction';
import { SaveOutlined } from '@ant-design/icons';
import { Connection, PublicKey } from '@solana/web3.js';
+import { LABELS } from '../../constants';
const { useWallet } = contexts.Wallet;
const { useConnection } = contexts.Connection;
@@ -25,8 +30,10 @@ enum UploadType {
export function NewInstructionCard({
proposal,
position,
+ config,
}: {
proposal: ParsedAccount;
+ config: ParsedAccount;
position: number;
}) {
const [form] = Form.useForm();
@@ -41,7 +48,19 @@ export function NewInstructionCard({
}) => {
if (!values.slot.match(/^\d*$/)) {
notify({
- message: 'Slot can only be numeric',
+ message: LABELS.SLOT_MUST_BE_NUMERIC,
+ type: 'error',
+ });
+ return;
+ }
+
+ if (
+ parseInt(values.slot) < config.info.minimumSlotWaitingPeriod.toNumber()
+ ) {
+ notify({
+ message:
+ LABELS.SLOT_MUST_BE_GREATER_THAN +
+ config.info.minimumSlotWaitingPeriod.toString(),
type: 'error',
});
return;
@@ -69,7 +88,11 @@ export function NewInstructionCard({
actions={[]}
>
+
{
const PROGRAM_IDS = utils.programIds();
@@ -39,6 +40,7 @@ export const initTimelockConfigInstruction = (
BufferLayout.u8('timelockType'),
BufferLayout.u8('votingEntryRule'),
Layout.uint64('minimumSlotWaitingPeriod'),
+ Layout.uint64('timeLimit'),
BufferLayout.seq(BufferLayout.u8(), CONFIG_NAME_LENGTH, 'name'),
]);
@@ -57,6 +59,7 @@ export const initTimelockConfigInstruction = (
timelockType,
votingEntryRule,
minimumSlotWaitingPeriod,
+ timeLimit,
name: nameAsBytes,
},
data,
diff --git a/packages/proposals/src/models/sign.ts b/packages/proposals/src/models/sign.ts
index f02cf4c..5d7e6f6 100644
--- a/packages/proposals/src/models/sign.ts
+++ b/packages/proposals/src/models/sign.ts
@@ -1,4 +1,8 @@
-import { PublicKey, TransactionInstruction } from '@solana/web3.js';
+import {
+ PublicKey,
+ SYSVAR_CLOCK_PUBKEY,
+ TransactionInstruction,
+} from '@solana/web3.js';
import { utils } from '@oyster/common';
import * as BufferLayout from 'buffer-layout';
import { TimelockInstruction } from './timelock';
@@ -14,6 +18,7 @@ import { TimelockInstruction } from './timelock';
/// 4. `[]` Timelock mint authority
/// 5. `[]` Timelock program account pub key.
/// 6. `[]` Token program account.
+/// 7. `[]` Clock sysvar.
export const signInstruction = (
timelockSetAccount: PublicKey,
signatoryAccount: PublicKey,
@@ -46,6 +51,7 @@ export const signInstruction = (
isWritable: false,
},
{ pubkey: PROGRAM_IDS.token, isSigner: false, isWritable: false },
+ { pubkey: SYSVAR_CLOCK_PUBKEY, isSigner: false, isWritable: false },
];
return new TransactionInstruction({
keys,
diff --git a/packages/proposals/src/models/timelock.ts b/packages/proposals/src/models/timelock.ts
index 50a3212..83d122a 100644
--- a/packages/proposals/src/models/timelock.ts
+++ b/packages/proposals/src/models/timelock.ts
@@ -8,7 +8,7 @@ export const DESC_SIZE = 200;
export const NAME_SIZE = 32;
export const CONFIG_NAME_LENGTH = 32;
export const INSTRUCTION_LIMIT = 450;
-export const TRANSACTION_SLOTS = 5;
+export const TRANSACTION_SLOTS = 4;
export const TEMP_FILE_TXN_SIZE = 1000;
export enum TimelockInstruction {
@@ -43,6 +43,8 @@ export interface TimelockConfig {
governanceMint: PublicKey;
/// Program ID that is tied to this config (optional)
program: PublicKey;
+ /// Time limit in slots for proposal to be open to voting
+ timeLimit: BN;
/// Optional name
name: string;
}
@@ -57,6 +59,7 @@ export const TimelockConfigLayout: typeof BufferLayout.Structure = BufferLayout.
Layout.uint64('minimumSlotWaitingPeriod'),
Layout.publicKey('governanceMint'),
Layout.publicKey('program'),
+ Layout.uint64('timeLimit'),
BufferLayout.seq(BufferLayout.u8(), CONFIG_NAME_LENGTH, 'name'),
],
);
@@ -95,6 +98,9 @@ export enum TimelockStateStatus {
/// Deleted
Deleted = 4,
+
+ /// Defeated
+ Defeated = 5,
}
export const STATE_COLOR: Record = {
@@ -103,6 +109,7 @@ export const STATE_COLOR: Record = {
[TimelockStateStatus.Executing]: 'green',
[TimelockStateStatus.Completed]: 'purple',
[TimelockStateStatus.Deleted]: 'gray',
+ [TimelockStateStatus.Defeated]: 'red',
};
export interface TimelockState {
@@ -111,6 +118,10 @@ export interface TimelockState {
timelockTransactions: PublicKey[];
name: string;
descLink: string;
+ votingEndedAt: BN;
+ votingBeganAt: BN;
+ executions: number;
+ usedTxnSlots: number;
}
const timelockTxns = [];
@@ -137,6 +148,10 @@ export const TimelockSetLayout: typeof BufferLayout.Structure = BufferLayout.str
Layout.uint64('totalSigningTokensMinted'),
BufferLayout.seq(BufferLayout.u8(), DESC_SIZE, 'descLink'),
BufferLayout.seq(BufferLayout.u8(), NAME_SIZE, 'name'),
+ Layout.uint64('votingEndedAt'),
+ Layout.uint64('votingBeganAt'),
+ BufferLayout.u8('executions'),
+ BufferLayout.u8('usedTxnSlots'),
...timelockTxns,
],
);
@@ -248,6 +263,10 @@ export const TimelockSetParser = (
descLink: utils.fromUTF8Array(data.descLink).replaceAll('\u0000', ''),
name: utils.fromUTF8Array(data.name).replaceAll('\u0000', ''),
timelockTransactions: timelockTxns,
+ votingEndedAt: data.votingEndedAt,
+ votingBeganAt: data.votingBeganAt,
+ executions: data.executions,
+ usedTxnSlots: data.usedTxnSlots,
},
},
};
@@ -298,9 +317,10 @@ export const TimelockConfigParser = (
executionType: data.executionType,
timelockType: data.timelockType,
votingEntryRule: data.votingEntryRule,
- minimimSlotWaitingPeriod: data.minimimSlotWaitingPeriod,
+ minimumSlotWaitingPeriod: data.minimumSlotWaitingPeriod,
governanceMint: data.governanceMint,
program: data.program,
+ timeLimit: data.timeLimit,
name: utils.fromUTF8Array(data.name).replaceAll('\u0000', ''),
},
};
diff --git a/packages/proposals/src/models/vote.ts b/packages/proposals/src/models/vote.ts
index 5f8912a..286325b 100644
--- a/packages/proposals/src/models/vote.ts
+++ b/packages/proposals/src/models/vote.ts
@@ -1,4 +1,8 @@
-import { PublicKey, TransactionInstruction } from '@solana/web3.js';
+import {
+ PublicKey,
+ SYSVAR_CLOCK_PUBKEY,
+ TransactionInstruction,
+} from '@solana/web3.js';
import { utils } from '@oyster/common';
import * as Layout from '../utils/layout';
@@ -23,6 +27,7 @@ import BN from 'bn.js';
/// 10. `[]` Timelock program mint authority
/// 11. `[]` Timelock program account pub key.
/// 12. `[]` Token program account.
+/// 13. `[]` Clock sysvar.
export const voteInstruction = (
timelockSetAccount: PublicKey,
votingAccount: PublicKey,
@@ -75,6 +80,7 @@ export const voteInstruction = (
isWritable: false,
},
{ pubkey: PROGRAM_IDS.token, isSigner: false, isWritable: false },
+ { pubkey: SYSVAR_CLOCK_PUBKEY, isSigner: false, isWritable: false },
];
return new TransactionInstruction({
diff --git a/packages/proposals/src/views/governance/index.tsx b/packages/proposals/src/views/governance/index.tsx
index 4b39f79..ff1c638 100644
--- a/packages/proposals/src/views/governance/index.tsx
+++ b/packages/proposals/src/views/governance/index.tsx
@@ -20,6 +20,7 @@ import {
import { PublicKey } from '@solana/web3.js';
import { Table } from 'antd';
import MintGovernanceTokens from '../../components/Proposal/MintGovernanceTokens';
+import BN from 'bn.js';
const { useUserAccounts } = hooks;
const columns = [
{
@@ -47,14 +48,21 @@ const columns = [
},
{
title: LABELS.VOTING_ENTRY_RULES,
- dataIndex: 'votingEntryRules',
- key: 'votingEntryRules',
+ dataIndex: 'votingEntryRule',
+ key: 'votingEntryRule',
render: (number: number) => {VotingEntryRule[number]},
},
{
title: LABELS.MINIMUM_SLOT_WAITING_PERIOD,
dataIndex: 'minimumSlotWaitingPeriod',
key: 'minimumSlotWaitingPeriod',
+ render: (number: BN) => {number.toNumber()},
+ },
+ {
+ title: LABELS.TIME_LIMIT,
+ dataIndex: 'timeLimit',
+ key: 'timeLimit',
+ render: (number: BN) => {number.toNumber()},
},
{
title: LABELS.GOVERNANCE_MINT,
diff --git a/packages/proposals/src/views/governance/register.tsx b/packages/proposals/src/views/governance/register.tsx
index 512fa8a..0b64a1a 100644
--- a/packages/proposals/src/views/governance/register.tsx
+++ b/packages/proposals/src/views/governance/register.tsx
@@ -79,18 +79,25 @@ export function NewForm({
consensusAlgorithm: ConsensusAlgorithm;
votingEntryRule: VotingEntryRule;
minimumSlotWaitingPeriod: string;
+ timeLimit: string;
governanceMint: string;
program: string;
name: string;
}) => {
if (!values.minimumSlotWaitingPeriod.match(/^\d*$/)) {
notify({
- message: 'Minimum Slot Waiting Period can only be numeric',
+ message: LABELS.MIN_SLOT_MUST_BE_NUMERIC,
+ type: 'error',
+ });
+ return;
+ }
+ if (!values.timeLimit.match(/^\d*$/)) {
+ notify({
+ message: LABELS.TIME_LIMIT_MUST_BE_NUMERIC,
type: 'error',
});
return;
}
-
const uninitializedConfig = {
timelockType: values.timelockType,
executionType: values.executionType,
@@ -102,6 +109,7 @@ export function NewForm({
: undefined,
program: new PublicKey(values.program),
name: values.name,
+ timeLimit: new BN(values.timeLimit),
};
const newConfig = await registerProgramGovernance(
@@ -143,6 +151,13 @@ export function NewForm({
>
+
+
+