Skip to content

Commit

Permalink
Add update manifesto support (#65)
Browse files Browse the repository at this point in the history
add manifesto edit
  • Loading branch information
julienbrg authored Feb 28, 2024
1 parent 919310c commit 1f305ae
Show file tree
Hide file tree
Showing 3 changed files with 213 additions and 12 deletions.
7 changes: 7 additions & 0 deletions src/components/layout/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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')
}
Expand Down Expand Up @@ -67,6 +71,9 @@ export function Header(props: Props) {
{selectedPage}
</MenuButton>
<MenuList>
<LinkComponent href="/">
<MenuItem onClick={switchToHome}>Home</MenuItem>
</LinkComponent>
<LinkComponent href="/manifesto">
<MenuItem onClick={switchToManifesto}>Manifesto</MenuItem>
</LinkComponent>
Expand Down
6 changes: 6 additions & 0 deletions src/pages/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,12 @@ export default function Home() {
</Button>
<br />
</LinkComponent>
<LinkComponent href="/manifesto">
<Button mt={5} rightIcon={<AddIcon />} colorScheme="green" variant="outline">
Edit the manifesto
</Button>
<br />
</LinkComponent>
</main>
</>
)
Expand Down
212 changes: 200 additions & 12 deletions src/pages/manifesto/index.tsx
Original file line number Diff line number Diff line change
@@ -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 () => {
Expand All @@ -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 (
<>
<Head />

<main>
<br />
<Heading as="h2">Manifesto</Heading>
<br />
<Text>
<ReactMarkdown>{manifesto}</ReactMarkdown>
</Text>
<br />
<br />
<br />

<HeadingComponent as="h3">Update the manifesto</HeadingComponent>
<br />

<FormControl>
<FormLabel>Name of the proposal</FormLabel>
<Input value={title} onChange={(e) => setTitle(e.target.value)} placeholder={title} />
<FormHelperText>How should we refer to your proposal?</FormHelperText>
<br />
<br />

<FormLabel>Description</FormLabel>
<Textarea value={description} onChange={(e) => setDescription(e.target.value)} placeholder="" />
<FormHelperText>Supports markdown.</FormHelperText>
<br />
<br />
<FormLabel>New Manifesto URL</FormLabel>
<Input value={newManifesto} onChange={(e) => setNewManifesto(e.target.value)} placeholder={newManifesto} />
<FormHelperText>The URL of the newly edited manifesto</FormHelperText>
<br />

{!loading ? (
<Button mt={4} colorScheme="blue" variant="outline" type="submit" onClick={submitProposal}>
Submit proposal
</Button>
) : (
<Button isLoading loadingText="Submitting proposal..." mt={4} colorScheme="blue" variant="outline" type="submit" onClick={submitProposal}>
Submit proposal
</Button>
)}
</FormControl>
</main>
</>
) : (
<Image priority width="400" height="400" alt="loader" src="/reggae-loader.svg" />
)
}

0 comments on commit 1f305ae

Please sign in to comment.