From 1f305ae16576aaba2cfe0ed6cebd7bd6c810e724 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20B=C3=A9ranger?= Date: Wed, 28 Feb 2024 19:09:22 +0100 Subject: [PATCH] Add update manifesto support (#65) add manifesto edit --- src/components/layout/Header.tsx | 7 + src/pages/index.tsx | 6 + src/pages/manifesto/index.tsx | 212 +++++++++++++++++++++++++++++-- 3 files changed, 213 insertions(+), 12 deletions(-) diff --git a/src/components/layout/Header.tsx b/src/components/layout/Header.tsx index 7b9f437..dfb8610 100644 --- a/src/components/layout/Header.tsx +++ b/src/components/layout/Header.tsx @@ -15,6 +15,10 @@ export function Header(props: Props) { const [selectedPage, setSelectedPage] = useState('Explore') + const switchToHome = async () => { + setSelectedPage('Explore') + } + const switchToPropose = async () => { setSelectedPage('ETH transfer') } @@ -67,6 +71,9 @@ export function Header(props: Props) { {selectedPage} + + Home + Manifesto diff --git a/src/pages/index.tsx b/src/pages/index.tsx index 1a25799..d34aa1a 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -304,6 +304,12 @@ export default function Home() {
+ + +
+
) diff --git a/src/pages/manifesto/index.tsx b/src/pages/manifesto/index.tsx index 6e432af..5410baf 100644 --- a/src/pages/manifesto/index.tsx +++ b/src/pages/manifesto/index.tsx @@ -1,23 +1,47 @@ -import { Heading, Button, Badge, Text, FormControl, FormLabel, Textarea, Input, FormHelperText, useToast, Flex } from '@chakra-ui/react' +import { + Heading, + Button, + Badge, + FormControl, + FormLabel, + Textarea, + ListItem, + UnorderedList, + Input, + FormHelperText, + Checkbox, + useToast, + Text, +} from '@chakra-ui/react' +import { LockIcon } from '@chakra-ui/icons' import { Head } from '../../components/layout/Head' -import Image from 'next/image' import { useState, useEffect } from 'react' import { useEthersSigner, useEthersProvider } from '../../hooks/ethersAdapter' import { ethers } from 'ethers' -import { nftAbi, GOV_CONTRACT_ADDRESS, GOV_CONTRACT_ABI } from '../../utils/config' +import { GOV_CONTRACT_ADDRESS, GOV_CONTRACT_ABI, nftAbi, ERC20_CONTRACT_ABI, ERC20_CONTRACT_ADRESS } from '../../utils/config' +import { useRouter } from 'next/router' import ReactMarkdown from 'react-markdown' +import { HeadingComponent } from 'components/layout/HeadingComponent' + +// const baseUrl = 'https://www.tally.xyz/gov/' + TALLY_DAO_NAME + '/proposal/' export default function Manifesto() { - const [initialized, setInitialized] = useState(true) const [loading, setLoading] = useState(false) - const [loadingDelegateToSelf, setLoadingDelegateToSelf] = useState(false) - const [currentDelegate, setCurrentDelegate] = useState(false) - const [isDelegatedToSelf, setIsDelegatedToSelf] = useState(true) - const [targetAddress, setTargetAddress] = useState('') + const [amount, setAmount] = useState('0') + const [title, setTitle] = useState('Manifesto update') + const [newManifesto, setNewManifesto] = useState('https://bafkreifnnreoxxgkhty7v2w3qwiie6cfxpv3vcco2xldekfvbiem3nm6dm.ipfs.w3s.link/ ') + const [targets, setTargets] = useState('') + const [description, setDescription] = useState("Let's edit the manifesto!") + const [encryptionRequested, setEncryptionRequested] = useState(false) + const [name, setName] = useState('') + const [plaintext, setPlaintext] = useState('') + const [initialized, setInitialized] = useState(true) const [manifesto, setManifesto] = useState('') + + const toast = useToast() + const router = useRouter() const provider = useEthersProvider() const signer = useEthersSigner() - const toast = useToast() useEffect(() => { const init = async () => { @@ -42,18 +66,182 @@ export default function Manifesto() { setManifesto(manifestoContent) } - return initialized ? ( + const submitProposal = async (e: any) => { + e.preventDefault() + setLoading(true) + + console.log('submitProposal triggered') + // console.log('file name:', name) + console.log('encryptionRequested:', encryptionRequested) + + let fileToAddInDescription: string = '' + let plaintextString = '' + + // if encryption is not requested, upload the file to ipfs + // fileToAddInDescription = await UploadFile(plaintext, name) + // console.log('[no encryption] fileToAddInDescription:', fileToAddInDescription) + // } + + try { + // prepare Gov + const gov = new ethers.Contract(GOV_CONTRACT_ADDRESS, GOV_CONTRACT_ABI, signer) + + // prepare calldatas + const setManifesto = gov.interface.encodeFunctionData('setManifesto', [newManifesto]) + const calldatas = [setManifesto.toString()] + + // prepare proposal description + let PROPOSAL_DESCRIPTION: string + // console.log('fileToAddInDescription:', fileToAddInDescription) + // console.log('encryptionRequested:', encryptionRequested) + // console.log('plaintextString:', plaintextString) + + if (fileToAddInDescription) { + // won't work if no file attached + if (plaintextString) { + PROPOSAL_DESCRIPTION = '' + title + '\n' + description + '\n\n[View attached document](' + fileToAddInDescription + ')' + if (encryptionRequested) { + PROPOSAL_DESCRIPTION += ' encrypted' /*+ (cipherId === null ? "没有" : cipherId)*/ + } else { + PROPOSAL_DESCRIPTION = '' + title + '\n' + description + '' + } + } else { + PROPOSAL_DESCRIPTION = '' + title + '\n' + description + '\n\n[View attached document](' + fileToAddInDescription + ')' + } + } else { + PROPOSAL_DESCRIPTION = '' + title + '\n' + description + '' + } + + // console.log('PROPOSAL_DESCRIPTION:', PROPOSAL_DESCRIPTION) + + PROPOSAL_DESCRIPTION = PROPOSAL_DESCRIPTION + + // set targets and values + const values = [0] + + console.log(amount) + console.log(description) + setAmount(amount) + + console.log('encryptionRequested:', encryptionRequested) + + // delegate to self before calling propose + await delegateToMyself() + + // call propose + console.log('caller address:', await signer?.getAddress()) + const propose = await gov.propose([GOV_CONTRACT_ADDRESS], values, calldatas, PROPOSAL_DESCRIPTION) + console.log('Propose triggered') + const proposeReceipt: any = await propose.wait(1) + const proposals: any = await gov.queryFilter('ProposalCreated' as any, proposeReceipt.blockNumber) // TODO: fix type casting + const proposalId: any = proposals[0].args?.proposalId.toString() + console.log('proposalId:', proposalId) + // console.log('Tally link:', baseUrl + proposalId) + const targetURL = '/proposal/' + proposalId + setLoading(false) + router.push(targetURL) + } catch (e) { + console.log('error:', e) + setLoading(false) + } + } + + const handleFileChange = (event: any) => { + if (encryptionRequested) { + console.log('handleFileChange:', event) + const file = event + setName(file.name) + const reader = new FileReader() + reader.readAsDataURL(file) + reader.onload = (event) => { + const plaintext = String(event.target?.result) + setPlaintext(plaintext) + } + reader.onerror = (error) => { + console.log('File Input Error: ', error) + } + } else { + console.log('event:', event) + const file = event + setName(file.name) + setPlaintext(file) + } + } + + const hasDelegated = async () => { + const gov = new ethers.Contract(GOV_CONTRACT_ADDRESS, GOV_CONTRACT_ABI, signer) + const delegateTo = await signer?.getAddress() + const nftAddress = await gov.token() + const nft = new ethers.Contract(nftAddress, nftAbi, signer) + const delegate = await nft.delegates(await signer?.getAddress()) + if (delegate === delegateTo) { + return true + } + } + + const delegateToMyself = async () => { + if ((await hasDelegated()) === true) { + return true + } else { + console.log('delegating to self...') + const delegateTo = await signer?.getAddress() + console.log('hello signer address:', await signer?.getAddress()) + const gov = new ethers.Contract(GOV_CONTRACT_ADDRESS, GOV_CONTRACT_ABI, signer) + const nftAddress = await gov.token() + const nft = new ethers.Contract(nftAddress, nftAbi, signer) + const delegate = await nft.delegate(delegateTo) + const receippt = await delegate.wait(1) + console.log('delegate receipt:', receippt) + return true + } + } + + return ( <> +
+
Manifesto
{manifesto} +
+
+
+ + Update the manifesto +
+ + + Name of the proposal + setTitle(e.target.value)} placeholder={title} /> + How should we refer to your proposal? +
+
+ + Description +