From 2ebdd62218456407b70b0bea5dd54d4fe4ffeeb1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Sojka?= Date: Mon, 26 Aug 2024 18:50:08 +0200 Subject: [PATCH] Add proposal that updates default prop params (see #127) --- frontend/src/components/NewProposalForm.tsx | 48 +++++----- frontend/src/components/Proposal.tsx | 40 ++++---- .../proposal-form/ConfigProposal.tsx | 91 +++++++++++++++++++ .../src/components/proposal-form/Treasury.tsx | 11 +-- frontend/src/constants/amm.ts | 1 - frontend/src/constants/config.json | 1 - frontend/src/lib/config.ts | 2 +- 7 files changed, 145 insertions(+), 49 deletions(-) create mode 100644 frontend/src/components/proposal-form/ConfigProposal.tsx diff --git a/frontend/src/components/NewProposalForm.tsx b/frontend/src/components/NewProposalForm.tsx index 7f5eb29c..6b7f5977 100644 --- a/frontend/src/components/NewProposalForm.tsx +++ b/frontend/src/components/NewProposalForm.tsx @@ -4,8 +4,9 @@ import { CONTRACT_ADDR } from "../lib/config"; import { useAccount, useContractWrite } from "@starknet-react/core"; //import CustomProposal from "./CustomProposal"; import Treasury from "./proposal-form/Treasury"; +import Config from "./proposal-form/ConfigProposal"; -const proposalTypes = ["airdrop", "signal vote", "AMM", "governance", "treasury"]; +const proposalTypes = ["airdrop", "signal vote", "AMM", "governance", "treasury", "config"]; export default function NewProposalForm({ setIsModalOpen, @@ -56,36 +57,37 @@ export default function NewProposalForm({ key={type} type="button" onClick={() => setSelectedType(type)} - className={`px-4 py-2 rounded flex-1 ${ - selectedType === type ? "bg-blue-500 text-white" : "bg-gray-200" - }`} + className={`px-4 py-2 rounded flex-1 ${selectedType === type ? "bg-blue-500 text-white" : "bg-gray-200" + }`} > {type} ))} - - {selectedType && selectedType !== "treasury" && ( + + {selectedType && selectedType !== "treasury" && selectedType !== "config" && (
- - setPayload(e.target.value)} - /> - + + setPayload(e.target.value)} + /> +
)} - - {selectedType === "treasury" && } + + {selectedType === "config" && } + + {selectedType === "treasury" && } ); } diff --git a/frontend/src/components/Proposal.tsx b/frontend/src/components/Proposal.tsx index a6945b34..dd8a6e8f 100644 --- a/frontend/src/components/Proposal.tsx +++ b/frontend/src/components/Proposal.tsx @@ -10,6 +10,28 @@ import toast from "react-hot-toast"; import NewcommentCommentForm from "./NewProposalCommentForm"; import Comments from "./Comments"; +// Convert the proposal type from number to string +const getProposalName = (type: number, payload: number) => { + const proposalTypes = { + 0: "amm", + 1: "governance", + 2: "CARM token", + 3: "merkle tree root", + 4: "no-op/signal vote", + 5: "custom", + }; + + const customProposalTypes = { + 0: "treasury distribution", + 1: "default proposal parameters" + }; + + return type === 5 + ? customProposalTypes[payload] || "unknown" + : proposalTypes[type] || "unknown"; +}; + + export default function Proposal({ proposalId, }: { @@ -31,20 +53,6 @@ export default function Proposal({ retry: false }); - // Convert the proposal type from number to string - const proposal_type = { - 0: "amm", - 1: "governance", - 2: "CARM token", - 3: "merkle tree root", - 4: "no-op/signal vote", - 5: "custom" - }; - - const custom_proposal_type = { - 0: "treasury distribution" - } - const { writeAsync: write_yes } = useContractWrite({ calls: [ { @@ -114,9 +122,7 @@ export default function Proposal({ className="flex-grow font-bold hover:underline cursor-pointer" onClick={() => setIsCommentModalOpen(true)} > - {data.valueOf()["to_upgrade"] == 5 - ? custom_proposal_type[data.valueOf()["payload"]] || "unknown" - : proposal_type[data.valueOf()["to_upgrade"]]} + {getProposalName(data.valueOf()["to_upgrade"], data.valueOf()["payload"])} diff --git a/frontend/src/components/proposal-form/ConfigProposal.tsx b/frontend/src/components/proposal-form/ConfigProposal.tsx new file mode 100644 index 00000000..0709091e --- /dev/null +++ b/frontend/src/components/proposal-form/ConfigProposal.tsx @@ -0,0 +1,91 @@ +import React, { useState } from "react"; +import { toast } from 'react-hot-toast'; +import { useContractWrite } from "@starknet-react/core"; +import { CONTRACT_ADDR } from "../../lib/config"; + +interface ConfigProposalProps { + setIsModalOpen: React.Dispatch>; +} + +export const ConfigProposal: React.FC = ({ setIsModalOpen }) => { + const [quorum, setQuorum] = useState(""); + const [proposalVotingSeconds, setProposalVotingSeconds] = useState(""); + + const { writeAsync } = useContractWrite({ + calls: [{ + contractAddress: CONTRACT_ADDR, + entrypoint: "submit_custom_proposal", + calldata: [1, 2, quorum, proposalVotingSeconds], + }], + }); + + const handleSubmit = (e: React.FormEvent) => { + e.preventDefault(); + + const quorumValue = parseInt(quorum); + if (isNaN(quorumValue) || quorumValue < 0 || quorumValue > 50) { + toast.error('Quorum must be a number between 0 and 50'); + return; + } + + const votingSeconds = parseInt(proposalVotingSeconds); + if (isNaN(votingSeconds) || votingSeconds <= 0) { + toast.error('Proposal voting seconds must be a positive number'); + return; + } + + if (votingSeconds <= 60 * 60) { + toast.error('Voting should be longer than 1 hour. Enter seconds'); + return; + } + + writeAsync() + .then(() => { + toast.success("Config proposal submitted"); + setIsModalOpen(false); + }) + .catch((e) => { + toast.error("Something went wrong"); + console.error(e); + }); + }; + + return ( +
+

Default proposal configuration

+
+
+ + setQuorum(e.target.value)} + /> +
+
+ + setProposalVotingSeconds(e.target.value)} + /> +
+ +
+
+ ); +}; + +export default ConfigProposal; \ No newline at end of file diff --git a/frontend/src/components/proposal-form/Treasury.tsx b/frontend/src/components/proposal-form/Treasury.tsx index 0ef06c4d..8e324c0c 100644 --- a/frontend/src/components/proposal-form/Treasury.tsx +++ b/frontend/src/components/proposal-form/Treasury.tsx @@ -5,12 +5,12 @@ import { toast } from 'react-hot-toast'; import { CONTRACT_ADDR } from "../../lib/config"; const treasuryProposalTypes = ["distribution", "zklend", "nostra", "carmine"]; -const treasuryProposalTypetoId = {"distribution": 0, "zklend": 1, "nostra": 2, "carmine": 3} +const treasuryProposalTypetoId = { "distribution": 0, "zklend": 2, "nostra": 3, "carmine": 4 } export default function Treasury({ setIsModalOpen, }: { - setIsModalOpen: React.Dispatch>; + setIsModalOpen: React.Dispatch>; }) { const [selectedType, setSelectedType] = useState(null); const { isConnected } = useAccount(); @@ -29,7 +29,7 @@ export default function Treasury({ } const selectedTypeId = treasuryProposalTypetoId[selectedType]; - + if (!selectedType || newCalldata.length === 0) return []; const calls = [{ contractAddress: CONTRACT_ADDR, @@ -60,9 +60,8 @@ export default function Treasury({ key={type} type="button" onClick={() => setSelectedType(type)} - className={`px-4 py-2 rounded flex-1 ${ - selectedType === type ? "bg-blue-500 text-white" : "bg-gray-200" - }`} + className={`px-4 py-2 rounded flex-1 ${selectedType === type ? "bg-blue-500 text-white" : "bg-gray-200" + }`} > {type} diff --git a/frontend/src/constants/amm.ts b/frontend/src/constants/amm.ts index db64eeb6..ef9ffec4 100644 --- a/frontend/src/constants/amm.ts +++ b/frontend/src/constants/amm.ts @@ -3,7 +3,6 @@ import config from "./config.json"; export const NETWORK = config.NETWORK as "mainnet" | "testnet"; export const API_URL = config.API_URL; export const AMM_ADDRESS = config.AMM_ADDRESS; -export const GOVERNANCE_ADDRESS = config.GOVERNANCE_ADDRESS; export const ETH_ADDRESS = config.ETH_ADDRESS; export const USDC_ADDRESS = config.USDC_ADDRESS; export const BTC_ADDRESS = config.BTC_ADDRESS; diff --git a/frontend/src/constants/config.json b/frontend/src/constants/config.json index 66508463..72b330af 100644 --- a/frontend/src/constants/config.json +++ b/frontend/src/constants/config.json @@ -2,7 +2,6 @@ "NETWORK": "sepolia", "API_URL": "https://api.carmine.finance", "AMM_ADDRESS": "0x047472e6755afc57ada9550b6a3ac93129cc4b5f98f51c73e0644d129fd208d9", - "GOVERNANCE_ADDRESS": "0x057dfabb5a506bfd1937062562a1adf45c7c4c62d0377ccfc59a0b42d7ab3212", "TREASURY_ADDRESS": "0x4c990da03da72bdfb10db5c04e8aaa9d5404a07fe454037facb7744c132d42c", "ETH_ADDRESS": "0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", "USDC_ADDRESS": "0x053c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", diff --git a/frontend/src/lib/config.ts b/frontend/src/lib/config.ts index 09beca7a..4b701343 100644 --- a/frontend/src/lib/config.ts +++ b/frontend/src/lib/config.ts @@ -1,6 +1,6 @@ export const CONTRACT_ADDR = // mainnet: "0x001405ab78ab6ec90fba09e6116f373cda53b0ba557789a4578d8c1ec374ba0f"; - "0x057dfabb5a506bfd1937062562a1adf45c7c4c62d0377ccfc59a0b42d7ab3212"; // sepolia with treasury + "0x02ba6e05d06a9e7398ae71c330b018415f93710c58e99fb04fa761f97712ec76"; // sepolia with treasury export const TOKEN_CONTRACT = "0x2b91dd683bc4bcae7a9c5d0cbeba0e8d62fa657742e4640f1e8163dc10e9bd7";