Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reject pool #500

Merged
merged 6 commits into from
Dec 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion apps/web/components/Badge.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ type BadgeProps = {
className?: string;
icon?: React.ReactNode;
isCapitalize?: boolean;
tooltip?: string;
};

// Styles for different pool badge types
Expand Down Expand Up @@ -39,6 +40,7 @@ export function Badge({
status,
label,
className,
tooltip,
icon,
}: BadgeProps): JSX.Element {
const isStatusBadge = status !== undefined;
Expand Down Expand Up @@ -70,7 +72,8 @@ export function Badge({

return (
<div
className={`${BASE_STYLES} ${styles} ${className} flex items-center gap-2`}
className={`${BASE_STYLES} ${styles} ${tooltip ? "tooltip" : ""} ${className} flex items-center gap-2`}
data-tip={tooltip}
>
{iconIncluded && (
<div className="h-6 w-6 text-inherit">{iconIncluded}</div>
Expand Down
6 changes: 3 additions & 3 deletions apps/web/components/Button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,12 @@ const btnStyles: BtnStyles = {
},
outline: {
primary:
"text-primary-content border border-primary-content hover:text-primary-hover-content hover:outline-primary-hover-content",
"text-primary-content border border-primary-content hover:text-primary-hover-content hover:border-primary-hover-content",
secondary:
"text-secondary-content border border-secondary-content hover:text-secondary-hover-content hover:outline-secondary-hover-content",
"text-secondary-content border border-secondary-content hover:text-secondary-hover-content hover:border-secondary-hover-content",
tertiary: "",
danger:
"text-danger-button border border-danger-button hover:text-danger-hover-content hover:outline-danger-hover-content",
"text-danger-button border border-danger-button hover:text-danger-hover-content hover:border-danger-hover-content",
disabled: "text-neutral-soft-content border border-neutral-soft-content",
},
link: {
Expand Down
19 changes: 7 additions & 12 deletions apps/web/components/Forms/PoolForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@ import { FormRadioButton } from "./FormRadioButton";
import { FormSelect } from "./FormSelect";
import { EthAddress } from "../EthAddress";
import { Button } from "@/components/Button";
import { DEFAULT_RULING_TIMEOUT_SEC } from "@/configs/constants";
import {
DEFAULT_RULING_TIMEOUT_SEC,
VOTING_POINT_SYSTEM_DESCRIPTION,
} from "@/configs/constants";
import { QUERY_PARAMS } from "@/constants/query-params";
import { usePubSubContext } from "@/contexts/pubsub.context";
import { useChainFromPath } from "@/hooks/useChainFromPath";
Expand Down Expand Up @@ -595,14 +598,6 @@ export function PoolForm({ token, communityAddr }: Props) {
}
}, [customTokenData, watchedAddress, trigger]);

const votingWeightSystemDescriptions = {
fixed: "Everyone has the same voting weight, limited to registration stake",
capped: "Voting weight is equal to tokens staked, up to a limit",
unlimited: "Voting weight is equal to tokens staked, no limit.",
quadratic:
"Voting weight increases as more tokens are staked, following a quadratic curve.",
};

return (
<form onSubmit={handleSubmit(handlePreview)} className="w-full">
{showPreview ?
Expand Down Expand Up @@ -676,18 +671,18 @@ export function PoolForm({ token, communityAddr }: Props) {
<span className="ml-1">*</span>
</label>
<div className="ml-2 flex flex-col gap-2">
{Object.entries(PointSystems).map(([value, label], i) => (
{Object.entries(PointSystems).map(([value, id], i) => (
<div key={value}>
<FormRadioButton
value={value}
label={capitalize(label)}
label={capitalize(id)}
inline={true}
onChange={() =>
setValue("pointSystemType", parseInt(value))
}
checked={parseInt(value) === pointSystemType}
registerKey="pointSystemType"
description={votingWeightSystemDescriptions[label]}
description={VOTING_POINT_SYSTEM_DESCRIPTION[id]}
/>
{PointSystems[pointSystemType] === "capped" &&
i === Object.values(PointSystems).indexOf("capped") && (
Expand Down
167 changes: 130 additions & 37 deletions apps/web/components/PoolHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,18 @@ import {
ChartBarIcon,
CheckIcon,
ClockIcon,
Cog6ToothIcon,
InformationCircleIcon,
Square3Stack3DIcon,
} from "@heroicons/react/24/outline";
import { StopIcon } from "@heroicons/react/24/solid";
import {
ArchiveBoxIcon,
NoSymbolIcon,
StopIcon,
Cog6ToothIcon,
} from "@heroicons/react/24/solid";
import { FetchTokenResult } from "@wagmi/core";
import Image from "next/image";
import { usePathname, useRouter } from "next/navigation";
import { Address, zeroAddress } from "viem";
import { useAccount, useContractRead } from "wagmi";
import {
Expand All @@ -32,6 +37,7 @@ import { Skeleton } from "./Skeleton";
import { Statistic } from "./Statistic";
import { blueLand, grassLarge } from "@/assets";
import { chainConfigMap } from "@/configs/chains";
import { VOTING_POINT_SYSTEM_DESCRIPTION } from "@/configs/constants";
import { usePubSubContext } from "@/contexts/pubsub.context";
import { useChainFromPath } from "@/hooks/useChainFromPath";
import { useContractWriteWithConfirmations } from "@/hooks/useContractWriteWithConfirmations";
Expand Down Expand Up @@ -95,7 +101,6 @@ function calculateMinimumConviction(weight: number, spendingLimit: number) {

return minimumConviction;
}

export default function PoolHeader({
ipfsResult,
poolId,
Expand All @@ -110,6 +115,9 @@ export default function PoolHeader({
const { address } = useAccount();
const { publish } = usePubSubContext();
const { id: chainId, safePrefix } = useChainFromPath()!;
const router = useRouter();
const path = usePathname();
const isArchived = strategy.archived;

const { data: passportStrategyData } =
useSubgraphQuery<getPassportStrategyQuery>({
Expand All @@ -128,7 +136,6 @@ export default function PoolHeader({
passportStrategy?.threshold ?
Number(passportStrategy?.threshold) / CV_PASSPORT_THRESHOLD_SCALE
: null;

const blockTime = chainConfigMap[chainId!].blockTime;
const spendingLimitPct =
(Number(strategy.config.maxRatio || 0) / CV_SCALE_PRECISION) * 100;
Expand Down Expand Up @@ -275,6 +282,31 @@ export default function PoolHeader({
},
});

const { write: rejectPoolWrite } = useContractWriteWithConfirmations({
address: communityAddr,
abi: registryCommunityABI,
contractName: "Registry Community",
functionName: "rejectPool",
fallbackErrorMessage: "Error rejecting pool, please report a bug.",
args: [strategy.id as Address],
onConfirmations: () => {
publish({
topic: "pool",
function: "rejectPool",
type: "update",
containerId: communityAddr,
chainId: chainId,
});
const pathSegments = path.split("/");
pathSegments.pop();
if (pathSegments.length === 6) {
pathSegments.pop();
}
const newPath = pathSegments.join("/");
router.push(newPath);
},
});

const { write: addStrategyByPoolId } = useContractWriteWithConfirmations({
address: communityAddr,
abi: registryCommunityABI,
Expand Down Expand Up @@ -338,22 +370,6 @@ export default function PoolHeader({
</h2>
{(!!isCouncilMember || isCouncilSafe) && (
<div className="flex gap-2 flex-wrap">
<div className="flex flex-col gap-1 p-1 w-48">
<a
href={`https://app.safe.global/transactions/queue?safe=${safePrefix}:${strategy.registryCommunity.councilSafe}`}
className="text-info whitespace-nowrap flex flex-nowrap gap-1 items-center"
target="_blank"
rel="noreferrer"
>
Council safe
<ArrowTopRightOnSquareIcon width={16} height={16} />
</a>
<EthAddress
address={strategy.registryCommunity.councilSafe as Address}
shortenAddress={true}
actions="copy"
/>
</div>
<Button
btnStyle="outline"
icon={<Cog6ToothIcon height={24} width={24} />}
Expand All @@ -365,39 +381,110 @@ export default function PoolHeader({
>
Edit
</Button>
{isEnabled ?
{isArchived ?
<Button
icon={<StopIcon height={24} width={24} />}
disabled={
!isConnected || missmatchUrl || disableCouncilSafeButtons
}
tooltip={tooltipMessage}
onClick={() => removeStrategyByPoolId()}
btnStyle="outline"
color="danger"
>
Disable
</Button>
: <Button
icon={<CheckIcon height={24} width={24} />}
disabled={
!isConnected || missmatchUrl || disableCouncilSafeButtons
}
tooltip={tooltipMessage}
tooltip={
tooltipMessage ?? "Restore the pool will also enable it."
}
showToolTip={true}
onClick={() => addStrategyByPoolId()}
>
Approve
Restore
</Button>
: isEnabled ?
<>
<Button
icon={<StopIcon height={24} width={24} />}
disabled={
!isConnected || missmatchUrl || disableCouncilSafeButtons
}
tooltip={
tooltipMessage ??
"Disable pool will pause all interactions with this pool. It is possible to enable it back."
}
showToolTip={true}
onClick={() => removeStrategyByPoolId()}
btnStyle="outline"
color="secondary"
>
Disable
</Button>
<Button
icon={<ArchiveBoxIcon height={24} width={24} />}
disabled={
!isConnected || missmatchUrl || disableCouncilSafeButtons
}
tooltip={
tooltipMessage ??
"Archive pool will remove it from the list of pools. Need to contact the Gardens team to restore it."
}
showToolTip={true}
onClick={() => rejectPoolWrite()}
btnStyle="outline"
color="danger"
>
Archive
</Button>
</>
: <>
<Button
icon={<CheckIcon height={24} width={24} />}
disabled={
!isConnected || missmatchUrl || disableCouncilSafeButtons
}
tooltip={tooltipMessage ?? "Approve pool to enable it."}
showToolTip={true}
onClick={() => addStrategyByPoolId()}
>
Approve
</Button>
<Button
icon={<NoSymbolIcon height={24} width={24} />}
disabled={
!isConnected || missmatchUrl || disableCouncilSafeButtons
}
tooltip={
tooltipMessage ??
"Reject pool will remove it from the list. \nNeed to contact the Gardens team to\n restore it."
}
showToolTip={true}
onClick={() => rejectPoolWrite()}
btnStyle="outline"
color="danger"
>
Reject
</Button>
</>
}
</div>
)}
</div>
<div>
<div className="w-full flex flex-col gap-2">
<EthAddress
icon={false}
address={strategy.id as Address}
label="Pool address"
/>
<div className="flex flex-col gap-1 p-1 w-48">
<a
href={`https://app.safe.global/transactions/queue?safe=${safePrefix}:${strategy.registryCommunity.councilSafe}`}
className="text-info whitespace-nowrap flex flex-nowrap gap-1 items-center"
target="_blank"
rel="noreferrer"
>
Council safe
<ArrowTopRightOnSquareIcon width={16} height={16} />
</a>
<EthAddress
address={strategy.registryCommunity.councilSafe as Address}
shortenAddress={true}
actions="copy"
/>
</div>
</div>
<Modal
title={`Edit ${ipfsResult?.title} #${poolId}`}
Expand Down Expand Up @@ -455,7 +542,13 @@ export default function PoolHeader({
className="text-secondary-content"
icon={<ChartBarIcon />}
/>
<Badge label={PointSystems[pointSystem]} icon={<BoltIcon />} />
<Badge
label={PointSystems[pointSystem]}
tooltip={
VOTING_POINT_SYSTEM_DESCRIPTION[PointSystems[pointSystem]]
}
icon={<BoltIcon />}
/>
</div>
</Statistic>
</div>
Expand Down
24 changes: 13 additions & 11 deletions apps/web/components/PoolMetrics.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -153,17 +153,19 @@ export const PoolMetrics: FC<PoolMetricsProps> = ({
className="subtitle2 text-primary-content"
/>
</div>
<div className="flex gap-3">
<p className="subtitle2">Wallet balance:</p>
<Skeleton isLoading={!balance}>
<DisplayNumber
number={[balance?.value ?? BigInt(0), poolToken.decimals]}
tokenSymbol={poolToken.symbol}
compact={true}
className="subtitle2 text-primary-content"
/>
</Skeleton>
</div>
{accountAddress && (
<div className="flex gap-3">
<p className="subtitle2">Wallet balance:</p>
<Skeleton isLoading={!balance}>
<DisplayNumber
number={[balance?.value ?? BigInt(0), poolToken.decimals]}
tokenSymbol={poolToken.symbol}
compact={true}
className="subtitle2 text-primary-content"
/>
</Skeleton>
</div>
)}
</div>
<form
className="flex gap-2 flex-wrap"
Expand Down
9 changes: 8 additions & 1 deletion apps/web/configs/constants.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
export const DEFAULT_RULING_TIMEOUT_SEC = +(
(process.env.NEXT_PUBLIC_DEFAULT_RULING_TIMEOUT ?? 604800) // 7 days
);
);
export const VOTING_POINT_SYSTEM_DESCRIPTION = {
fixed: "Everyone has the same voting weight, limited to registration stake",
capped: "Voting weight is equal to tokens staked, up to a limit",
unlimited: "Voting weight is equal to tokens staked, no limit.",
quadratic:
"Voting weight increases as more tokens are staked, following a quadratic curve.",
} as const;
2 changes: 1 addition & 1 deletion apps/web/styles/globals.scss
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ caption {
}

.page-layout {
@apply flex w-full max-w-6xl flex-col gap-10 p-4 md:p-8 overflow-x-hidden;
@apply flex w-full max-w-6xl flex-col gap-10 p-4 md:p-8 overflow-x-visible;
}

.tooltip {
Expand Down
Loading
Loading