diff --git a/.env.v2 b/.env.v2
index 6fbc4f549..1a40bfc08 100644
--- a/.env.v2
+++ b/.env.v2
@@ -92,7 +92,7 @@ NEXT_PUBLIC_DYNAMIC_API_KEY="b8a5104d-47e0-4965-b56a-0bcc31cf56f4"
# in seconds
-NEXT_PUBLIC_BLOCKTIME="4"
+NEXT_PUBLIC_BLOCKTIME="1.9"
# Honey Addresses ===================================================================
NEXT_PUBLIC_HONEY_ROUTER_ADDRESS="0xAd1782b2a7020631249031618fB1Bd09CD926b31"
diff --git a/apps/hub/src/app/governance/[genre]/components/proposal-sorting.tsx b/apps/hub/src/app/governance/[genre]/components/proposal-sorting.tsx
new file mode 100644
index 000000000..a5834e939
--- /dev/null
+++ b/apps/hub/src/app/governance/[genre]/components/proposal-sorting.tsx
@@ -0,0 +1,47 @@
+import * as React from "react";
+import {
+ DropdownMenu,
+ DropdownMenuCheckboxItem,
+ DropdownMenuContent,
+ DropdownMenuLabel,
+ DropdownMenuSeparator,
+ DropdownMenuTrigger,
+} from "@bera/ui/dropdown-menu";
+import { Icons } from "@bera/ui/icons";
+
+import { OrderByEnum } from "../../types";
+
+export const ProposalSorting = () => {
+ const [sortBy, setSortBy] = React.useState(OrderByEnum.MOST_RECENT);
+
+ return (
+
+
+
+
+
+ {sortBy.replace("-", " ")}
+
+
+
+
+
+ Proposal Status
+
+ {Object.keys(OrderByEnum).map((order) => (
+
+ setSortBy(OrderByEnum[order as keyof typeof OrderByEnum])
+ }
+ >
+ {OrderByEnum[order as keyof typeof OrderByEnum].replace("-", " ")}
+
+ ))}
+
+
+
+ );
+};
diff --git a/apps/hub/src/app/governance/[genre]/components/proposal-status-filter.tsx b/apps/hub/src/app/governance/[genre]/components/proposal-status-filter.tsx
new file mode 100644
index 000000000..d1acc1b3b
--- /dev/null
+++ b/apps/hub/src/app/governance/[genre]/components/proposal-status-filter.tsx
@@ -0,0 +1,57 @@
+import * as React from "react";
+import {
+ DropdownMenu,
+ DropdownMenuCheckboxItem,
+ DropdownMenuContent,
+ DropdownMenuLabel,
+ DropdownMenuSeparator,
+ DropdownMenuTrigger,
+} from "@bera/ui/dropdown-menu";
+import { Icons } from "@bera/ui/icons";
+
+import { StatusEnum } from "../../types";
+
+export const ProposalStatusFilter = () => {
+ const config = Object.keys(StatusEnum).reduce(
+ (acc, curr) => {
+ acc[curr] = true;
+ return acc;
+ },
+ {} as { [key: string]: boolean },
+ );
+ const [statusConfig, setStatusConfig] = React.useState(config);
+
+ return (
+
+
+
+
+
+ Filter by Status
+
+
+
+
+
+ Proposal Status
+
+ {Object.keys(StatusEnum).map((status) => (
+
+ setStatusConfig((prev) => ({
+ ...prev,
+ [status]: !prev[status],
+ }))
+ }
+ >
+ {StatusEnum[status as keyof typeof StatusEnum].replace("-", " ")}
+
+ ))}
+
+
+
+ );
+};
diff --git a/apps/hub/src/app/governance/[genre]/components/proposals-list.tsx b/apps/hub/src/app/governance/[genre]/components/proposals-list.tsx
index fe7b2421f..34033ee8e 100644
--- a/apps/hub/src/app/governance/[genre]/components/proposals-list.tsx
+++ b/apps/hub/src/app/governance/[genre]/components/proposals-list.tsx
@@ -1,40 +1,49 @@
+import { useState } from "react";
import Image from "next/image";
-import { useRouter } from "next/navigation";
+import { useQuery } from "@apollo/client";
import { usePollAllProposals, type Proposal } from "@bera/berajs";
-import { cloudinaryUrl, isIPFS } from "@bera/config";
+import { cloudinaryUrl } from "@bera/config";
+import { getProposalss } from "@bera/graphql";
+import { SearchInput } from "@bera/shared-ui";
import { Skeleton } from "@bera/ui/skeleton";
-
+import { useRouter } from "next/navigation";
import { ProposalCard } from "./proposal-card";
+import { ProposalSorting } from "./proposal-sorting";
+import { ProposalStatusFilter } from "./proposal-status-filter";
+
+const PROPOSALS_PER_PAGE = 10;
export const ProposalsList = () => {
- const { data } = usePollAllProposals();
+ const { data = [], isLoading } = usePollAllProposals();
+ const [page, setPage] = useState(0);
const router = useRouter();
+ const {
+ loading,
+ error,
+ data: proposals,
+ } = useQuery(getProposalss, {
+ variables: {
+ offset: page * PROPOSALS_PER_PAGE,
+ limit: PROPOSALS_PER_PAGE,
+ },
+ pollInterval: 60000, // 1 min
+ });
+
return (
-
-
Proposal
-
Votes
-
Quorum
+
-
- {data?.map((proposal: Proposal) => (
-
- router.push(
- `/governance/proposal${isIPFS ? "?id=" : "/"}${proposal.id}`,
- )
- }
- onMouseOver={() =>
- router.prefetch(
- `/governance/proposal${isIPFS ? "?id=" : "/"}${proposal.id}`,
- )
- }
- />
- ))}
- {!data?.length && (
+
+
+ {isLoading ? (
<>
@@ -42,6 +51,17 @@ export const ProposalsList = () => {
>
+ ) : (
+ data.map((proposal: Proposal) => (
+
{
+ window.open(`/governance/proposal/${proposal.id}`, "_self");
+ }}
+ />
+ ))
)}
diff --git a/apps/hub/src/app/governance/governance-genre-helper.tsx b/apps/hub/src/app/governance/governance-genre-helper.tsx
index be9bdf48a..26886ca44 100644
--- a/apps/hub/src/app/governance/governance-genre-helper.tsx
+++ b/apps/hub/src/app/governance/governance-genre-helper.tsx
@@ -19,7 +19,9 @@ export const NativeDapps: GovernanceTopic[] = [
icon: ,
name: "BeraHub",
slug: "berahub",
- subgraph: governanceSubgraphUrl,
+ // subgraph: governanceSubgraphUrl,
+ subgraph:
+ "https://api.goldsky.com/api/public/project_clq1h5ct0g4a201x18tfte5iv/subgraphs/governance-subgraph/v1/gn",
},
{
id: "honey",
diff --git a/apps/hub/src/app/governance/helper.ts b/apps/hub/src/app/governance/helper.ts
index efc8e2951..c5462a269 100755
--- a/apps/hub/src/app/governance/helper.ts
+++ b/apps/hub/src/app/governance/helper.ts
@@ -1,8 +1,9 @@
import { Proposal } from "@bera/berajs";
import BigNumber from "bignumber.js";
+import graymatter from "gray-matter";
import { decodeFunctionData, formatEther } from "viem";
+
import { ProposalTypeEnum, StatusEnum, VoteColorMap } from "./types";
-import graymatter from "gray-matter";
import { NativeDapps, Others } from "./governance-genre-helper";
import { ComponentProps } from "react";
import { Badge } from "@bera/ui/badge";
@@ -14,10 +15,7 @@ export const getBadgeColor = (
case StatusEnum.PENDING:
return "outline";
case StatusEnum.ACTIVE:
- case StatusEnum.QUEUED:
- return "info";
case StatusEnum.EXECUTED:
- case StatusEnum.SUCCEEDED:
return "success";
case StatusEnum.DEFEATED:
return "destructive";
diff --git a/apps/hub/src/app/governance/proposal/[proposalId]/Status.tsx b/apps/hub/src/app/governance/proposal/[proposalId]/Status.tsx
index a9d8362e8..01f27244f 100644
--- a/apps/hub/src/app/governance/proposal/[proposalId]/Status.tsx
+++ b/apps/hub/src/app/governance/proposal/[proposalId]/Status.tsx
@@ -18,7 +18,7 @@ export const StatusAction = ({
}
return (
- {status === StatusEnum.QUEUED && (
+ {status === StatusEnum.IN_QUEUE && (
= T | null;
+export type InputMaybe = Maybe;
+export type Exact = {
+ [K in keyof T]: T[K];
+};
+export type MakeOptional = Omit & {
+ [SubKey in K]?: Maybe;
+};
+export type MakeMaybe = Omit & {
+ [SubKey in K]: Maybe;
+};
+export type MakeEmpty<
+ T extends { [key: string]: unknown },
+ K extends keyof T,
+> = { [_ in K]?: never };
+export type Incremental =
+ | T
+ | {
+ [P in keyof T]?: P extends " $fragmentName" | "__typename" ? T[P] : never;
+ };
+const defaultOptions = {} as const;
+/** All built-in and custom scalars, mapped to their actual values */
+export type Scalars = {
+ ID: { input: string; output: string };
+ String: { input: string; output: string };
+ Boolean: { input: boolean; output: boolean };
+ Int: { input: number; output: number };
+ Float: { input: number; output: number };
+ BigDecimal: { input: any; output: any };
+ BigInt: { input: any; output: any };
+ Bytes: { input: any; output: any };
+ Int8: { input: any; output: any };
+ Timestamp: { input: any; output: any };
+};
+
+export enum Aggregation_Interval {
+ Day = "day",
+ Hour = "hour",
+}
+
+export type BlockChangedFilter = {
+ number_gte: Scalars["Int"]["input"];
+};
+
+export type Block_Height = {
+ hash?: InputMaybe;
+ number?: InputMaybe;
+ number_gte?: InputMaybe;
+};
+
+export type CallScheduled = {
+ __typename?: "CallScheduled";
+ data: Scalars["Bytes"]["output"];
+ delay: Scalars["BigInt"]["output"];
+ id: Scalars["Int8"]["output"];
+ index: Scalars["BigInt"]["output"];
+ predecessor: Scalars["Bytes"]["output"];
+ target: Scalars["Bytes"]["output"];
+ timelockId: Scalars["Bytes"]["output"];
+ value: Scalars["BigInt"]["output"];
+};
+
+export type CallScheduled_Filter = {
+ /** Filter for the block changed event. */
+ _change_block?: InputMaybe;
+ and?: InputMaybe>>;
+ data?: InputMaybe;
+ data_contains?: InputMaybe;
+ data_gt?: InputMaybe;
+ data_gte?: InputMaybe;
+ data_in?: InputMaybe>;
+ data_lt?: InputMaybe;
+ data_lte?: InputMaybe;
+ data_not?: InputMaybe;
+ data_not_contains?: InputMaybe;
+ data_not_in?: InputMaybe>;
+ delay?: InputMaybe;
+ delay_gt?: InputMaybe;
+ delay_gte?: InputMaybe;
+ delay_in?: InputMaybe>;
+ delay_lt?: InputMaybe;
+ delay_lte?: InputMaybe;
+ delay_not?: InputMaybe;
+ delay_not_in?: InputMaybe>;
+ id?: InputMaybe;
+ id_gt?: InputMaybe;
+ id_gte?: InputMaybe;
+ id_in?: InputMaybe>;
+ id_lt?: InputMaybe;
+ id_lte?: InputMaybe;
+ id_not?: InputMaybe;
+ id_not_in?: InputMaybe>;
+ index?: InputMaybe;
+ index_gt?: InputMaybe;
+ index_gte?: InputMaybe;
+ index_in?: InputMaybe>;
+ index_lt?: InputMaybe;
+ index_lte?: InputMaybe;
+ index_not?: InputMaybe;
+ index_not_in?: InputMaybe>;
+ or?: InputMaybe>>;
+ predecessor?: InputMaybe;
+ predecessor_contains?: InputMaybe;
+ predecessor_gt?: InputMaybe;
+ predecessor_gte?: InputMaybe;
+ predecessor_in?: InputMaybe>;
+ predecessor_lt?: InputMaybe;
+ predecessor_lte?: InputMaybe;
+ predecessor_not?: InputMaybe;
+ predecessor_not_contains?: InputMaybe;
+ predecessor_not_in?: InputMaybe>;
+ target?: InputMaybe;
+ target_contains?: InputMaybe;
+ target_gt?: InputMaybe;
+ target_gte?: InputMaybe;
+ target_in?: InputMaybe>;
+ target_lt?: InputMaybe;
+ target_lte?: InputMaybe;
+ target_not?: InputMaybe;
+ target_not_contains?: InputMaybe;
+ target_not_in?: InputMaybe>;
+ timelockId?: InputMaybe;
+ timelockId_contains?: InputMaybe;
+ timelockId_gt?: InputMaybe;
+ timelockId_gte?: InputMaybe;
+ timelockId_in?: InputMaybe>;
+ timelockId_lt?: InputMaybe;
+ timelockId_lte?: InputMaybe;
+ timelockId_not?: InputMaybe;
+ timelockId_not_contains?: InputMaybe;
+ timelockId_not_in?: InputMaybe>;
+ value?: InputMaybe;
+ value_gt?: InputMaybe;
+ value_gte?: InputMaybe;
+ value_in?: InputMaybe>;
+ value_lt?: InputMaybe;
+ value_lte?: InputMaybe;
+ value_not?: InputMaybe;
+ value_not_in?: InputMaybe>;
+};
+
+export enum CallScheduled_OrderBy {
+ Data = "data",
+ Delay = "delay",
+ Id = "id",
+ Index = "index",
+ Predecessor = "predecessor",
+ Target = "target",
+ TimelockId = "timelockId",
+ Value = "value",
+}
+
+/** Defines the order direction, either ascending or descending */
+export enum OrderDirection {
+ Asc = "asc",
+ Desc = "desc",
+}
+
+export type Proposal = {
+ __typename?: "Proposal";
+ calldatas: Array;
+ canceledAt?: Maybe;
+ canceledAtBlock?: Maybe;
+ createdAt: Scalars["BigInt"]["output"];
+ createdAtBlock: Scalars["BigInt"]["output"];
+ description: Scalars["String"]["output"];
+ executedAt?: Maybe;
+ executedAtBlock?: Maybe;
+ id: Scalars["ID"]["output"];
+ proposalId: Scalars["BigInt"]["output"];
+ proposer: Scalars["Bytes"]["output"];
+ queuedAt?: Maybe;
+ queuedAtBlock?: Maybe;
+ signatures: Array;
+ status: Scalars["String"]["output"];
+ targets: Array;
+ values: Array;
+ voteEnd: Scalars["BigInt"]["output"];
+ voteStart: Scalars["BigInt"]["output"];
+};
+
+export type ProposalVotesAggregated = {
+ __typename?: "ProposalVotesAggregated";
+ id: Scalars["Int8"]["output"];
+ proposalId: Scalars["BigInt"]["output"];
+ support: Scalars["Int"]["output"];
+ timestamp: Scalars["Timestamp"]["output"];
+ weight: Scalars["BigInt"]["output"];
+};
+
+export type ProposalVotesAggregated_Filter = {
+ /** Filter for the block changed event. */
+ _change_block?: InputMaybe;
+ and?: InputMaybe>>;
+ id?: InputMaybe;
+ id_gt?: InputMaybe;
+ id_gte?: InputMaybe;
+ id_in?: InputMaybe>;
+ id_lt?: InputMaybe;
+ id_lte?: InputMaybe;
+ or?: InputMaybe>>;
+ proposalId?: InputMaybe;
+ proposalId_gt?: InputMaybe;
+ proposalId_gte?: InputMaybe;
+ proposalId_in?: InputMaybe>;
+ proposalId_lt?: InputMaybe;
+ proposalId_lte?: InputMaybe;
+ support?: InputMaybe;
+ support_gt?: InputMaybe;
+ support_gte?: InputMaybe;
+ support_in?: InputMaybe>;
+ support_lt?: InputMaybe;
+ support_lte?: InputMaybe;
+ timestamp?: InputMaybe;
+ timestamp_gt?: InputMaybe;
+ timestamp_gte?: InputMaybe;
+ timestamp_in?: InputMaybe>;
+ timestamp_lt?: InputMaybe;
+ timestamp_lte?: InputMaybe;
+};
+
+export type Proposal_Filter = {
+ /** Filter for the block changed event. */
+ _change_block?: InputMaybe;
+ and?: InputMaybe>>;
+ calldatas?: InputMaybe>;
+ calldatas_contains?: InputMaybe>;
+ calldatas_contains_nocase?: InputMaybe>;
+ calldatas_not?: InputMaybe>;
+ calldatas_not_contains?: InputMaybe>;
+ calldatas_not_contains_nocase?: InputMaybe>;
+ canceledAt?: InputMaybe;
+ canceledAtBlock?: InputMaybe;
+ canceledAtBlock_gt?: InputMaybe;
+ canceledAtBlock_gte?: InputMaybe;
+ canceledAtBlock_in?: InputMaybe>;
+ canceledAtBlock_lt?: InputMaybe;
+ canceledAtBlock_lte?: InputMaybe;
+ canceledAtBlock_not?: InputMaybe;
+ canceledAtBlock_not_in?: InputMaybe>;
+ canceledAt_gt?: InputMaybe;
+ canceledAt_gte?: InputMaybe;
+ canceledAt_in?: InputMaybe>;
+ canceledAt_lt?: InputMaybe;
+ canceledAt_lte?: InputMaybe;
+ canceledAt_not?: InputMaybe;
+ canceledAt_not_in?: InputMaybe>;
+ createdAt?: InputMaybe;
+ createdAtBlock?: InputMaybe;
+ createdAtBlock_gt?: InputMaybe;
+ createdAtBlock_gte?: InputMaybe;
+ createdAtBlock_in?: InputMaybe>;
+ createdAtBlock_lt?: InputMaybe;
+ createdAtBlock_lte?: InputMaybe;
+ createdAtBlock_not?: InputMaybe;
+ createdAtBlock_not_in?: InputMaybe>;
+ createdAt_gt?: InputMaybe;
+ createdAt_gte?: InputMaybe;
+ createdAt_in?: InputMaybe>;
+ createdAt_lt?: InputMaybe;
+ createdAt_lte?: InputMaybe;
+ createdAt_not?: InputMaybe;
+ createdAt_not_in?: InputMaybe>;
+ description?: InputMaybe;
+ description_contains?: InputMaybe;
+ description_contains_nocase?: InputMaybe;
+ description_ends_with?: InputMaybe;
+ description_ends_with_nocase?: InputMaybe;
+ description_gt?: InputMaybe;
+ description_gte?: InputMaybe;
+ description_in?: InputMaybe>;
+ description_lt?: InputMaybe;
+ description_lte?: InputMaybe;
+ description_not?: InputMaybe;
+ description_not_contains?: InputMaybe;
+ description_not_contains_nocase?: InputMaybe;
+ description_not_ends_with?: InputMaybe;
+ description_not_ends_with_nocase?: InputMaybe;
+ description_not_in?: InputMaybe>;
+ description_not_starts_with?: InputMaybe;
+ description_not_starts_with_nocase?: InputMaybe;
+ description_starts_with?: InputMaybe;
+ description_starts_with_nocase?: InputMaybe;
+ executedAt?: InputMaybe;
+ executedAtBlock?: InputMaybe;
+ executedAtBlock_gt?: InputMaybe;
+ executedAtBlock_gte?: InputMaybe;
+ executedAtBlock_in?: InputMaybe>;
+ executedAtBlock_lt?: InputMaybe;
+ executedAtBlock_lte?: InputMaybe;
+ executedAtBlock_not?: InputMaybe;
+ executedAtBlock_not_in?: InputMaybe>;
+ executedAt_gt?: InputMaybe;
+ executedAt_gte?: InputMaybe;
+ executedAt_in?: InputMaybe>;
+ executedAt_lt?: InputMaybe;
+ executedAt_lte?: InputMaybe;
+ executedAt_not?: InputMaybe;
+ executedAt_not_in?: InputMaybe>;
+ id?: InputMaybe;
+ id_gt?: InputMaybe;
+ id_gte?: InputMaybe;
+ id_in?: InputMaybe>;
+ id_lt?: InputMaybe;
+ id_lte?: InputMaybe;
+ id_not?: InputMaybe;
+ id_not_in?: InputMaybe>;
+ or?: InputMaybe>>;
+ proposalId?: InputMaybe;
+ proposalId_gt?: InputMaybe;
+ proposalId_gte?: InputMaybe;
+ proposalId_in?: InputMaybe>;
+ proposalId_lt?: InputMaybe;
+ proposalId_lte?: InputMaybe;
+ proposalId_not?: InputMaybe;
+ proposalId_not_in?: InputMaybe>;
+ proposer?: InputMaybe;
+ proposer_contains?: InputMaybe;
+ proposer_gt?: InputMaybe;
+ proposer_gte?: InputMaybe;
+ proposer_in?: InputMaybe>;
+ proposer_lt?: InputMaybe;
+ proposer_lte?: InputMaybe;
+ proposer_not?: InputMaybe;
+ proposer_not_contains?: InputMaybe;
+ proposer_not_in?: InputMaybe>;
+ queuedAt?: InputMaybe;
+ queuedAtBlock?: InputMaybe;
+ queuedAtBlock_gt?: InputMaybe;
+ queuedAtBlock_gte?: InputMaybe;
+ queuedAtBlock_in?: InputMaybe>;
+ queuedAtBlock_lt?: InputMaybe;
+ queuedAtBlock_lte?: InputMaybe;
+ queuedAtBlock_not?: InputMaybe;
+ queuedAtBlock_not_in?: InputMaybe>;
+ queuedAt_gt?: InputMaybe;
+ queuedAt_gte?: InputMaybe;
+ queuedAt_in?: InputMaybe>;
+ queuedAt_lt?: InputMaybe;
+ queuedAt_lte?: InputMaybe;
+ queuedAt_not?: InputMaybe;
+ queuedAt_not_in?: InputMaybe>;
+ signatures?: InputMaybe>;
+ signatures_contains?: InputMaybe>;
+ signatures_contains_nocase?: InputMaybe>;
+ signatures_not?: InputMaybe