feat: quick fix for new governor
This commit is contained in:
parent
9eb20624cb
commit
5dd1249ddd
@ -16,10 +16,12 @@ export const V2_ROUTER_ADDRESS: AddressMap = constructSameAddressMap(
|
|||||||
'0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D',
|
'0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D',
|
||||||
false
|
false
|
||||||
)
|
)
|
||||||
export const GOVERNANCE_ADDRESS: AddressMap = constructSameAddressMap(
|
export const GOVERNANCE_ADDRESSES: AddressMap[] = [
|
||||||
'0x5e4be8Bc9637f0EAA1A755019e06A68ce081D58F',
|
constructSameAddressMap('0x5e4be8Bc9637f0EAA1A755019e06A68ce081D58F', false),
|
||||||
false
|
{
|
||||||
)
|
[SupportedChainId.MAINNET]: '0xC4e172459f1E7939D522503B81AFAaC1014CE6F6',
|
||||||
|
},
|
||||||
|
]
|
||||||
export const TIMELOCK_ADDRESS: AddressMap = constructSameAddressMap('0x1a9C8182C09F50C8318d769245beA52c32BE35BC', false)
|
export const TIMELOCK_ADDRESS: AddressMap = constructSameAddressMap('0x1a9C8182C09F50C8318d769245beA52c32BE35BC', false)
|
||||||
export const MERKLE_DISTRIBUTOR_ADDRESS: AddressMap = {
|
export const MERKLE_DISTRIBUTOR_ADDRESS: AddressMap = {
|
||||||
[SupportedChainId.MAINNET]: '0x090D4613473dEE047c3f2706764f49E0821D256e',
|
[SupportedChainId.MAINNET]: '0x090D4613473dEE047c3f2706764f49E0821D256e',
|
||||||
|
@ -1,31 +1,12 @@
|
|||||||
import { GOVERNANCE_ADDRESS, TIMELOCK_ADDRESS, UNI_ADDRESS } from './addresses'
|
import { GOVERNANCE_ADDRESSES, TIMELOCK_ADDRESS, UNI_ADDRESS } from './addresses'
|
||||||
|
|
||||||
export const COMMON_CONTRACT_NAMES: { [chainId: number]: { [address: string]: string } } = {
|
export const COMMON_CONTRACT_NAMES: { [chainId: number]: { [address: string]: string } } = {
|
||||||
[1]: {
|
[1]: {
|
||||||
[UNI_ADDRESS[1]]: 'UNI',
|
[UNI_ADDRESS[1]]: 'UNI',
|
||||||
[GOVERNANCE_ADDRESS[1]]: 'Governance',
|
[GOVERNANCE_ADDRESSES[0][1]]: 'Governance (V0)',
|
||||||
|
[GOVERNANCE_ADDRESSES[1][1]]: 'Governance',
|
||||||
[TIMELOCK_ADDRESS[1]]: 'Timelock',
|
[TIMELOCK_ADDRESS[1]]: 'Timelock',
|
||||||
},
|
},
|
||||||
[4]: {
|
|
||||||
[UNI_ADDRESS[4]]: 'Rinkeby UNI',
|
|
||||||
[GOVERNANCE_ADDRESS[4]]: 'Rinkeby Governance',
|
|
||||||
[TIMELOCK_ADDRESS[4]]: 'Rinkeby Timelock',
|
|
||||||
},
|
|
||||||
[3]: {
|
|
||||||
[UNI_ADDRESS[3]]: 'Ropsten UNI',
|
|
||||||
[GOVERNANCE_ADDRESS[3]]: 'Ropsten Governance',
|
|
||||||
[TIMELOCK_ADDRESS[3]]: 'Ropsten Timelock',
|
|
||||||
},
|
|
||||||
[42]: {
|
|
||||||
[UNI_ADDRESS[42]]: 'Kovan UNI',
|
|
||||||
[GOVERNANCE_ADDRESS[42]]: 'Kovan Governance',
|
|
||||||
[TIMELOCK_ADDRESS[42]]: 'Kovan Timelock',
|
|
||||||
},
|
|
||||||
[5]: {
|
|
||||||
[UNI_ADDRESS[5]]: 'Goerli UNI',
|
|
||||||
[GOVERNANCE_ADDRESS[5]]: 'Goerli Governance',
|
|
||||||
[TIMELOCK_ADDRESS[5]]: 'Goerli Timelock',
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const DEFAULT_AVERAGE_BLOCK_TIME_IN_SECS = 13
|
export const DEFAULT_AVERAGE_BLOCK_TIME_IN_SECS = 13
|
||||||
|
@ -1,6 +0,0 @@
|
|||||||
import { UNISWAP_GRANTS_PROPOSAL_DESCRIPTION } from './uniswap_grants_proposal_description'
|
|
||||||
|
|
||||||
// Proposals are 0-indexed
|
|
||||||
export const PROPOSAL_DESCRIPTION_TEXT: { [proposalId: number]: string } = {
|
|
||||||
[2]: UNISWAP_GRANTS_PROPOSAL_DESCRIPTION,
|
|
||||||
}
|
|
@ -27,7 +27,7 @@ import {
|
|||||||
V3_CORE_FACTORY_ADDRESSES,
|
V3_CORE_FACTORY_ADDRESSES,
|
||||||
V3_MIGRATOR_ADDRESSES,
|
V3_MIGRATOR_ADDRESSES,
|
||||||
ARGENT_WALLET_DETECTOR_ADDRESS,
|
ARGENT_WALLET_DETECTOR_ADDRESS,
|
||||||
GOVERNANCE_ADDRESS,
|
GOVERNANCE_ADDRESSES,
|
||||||
MERKLE_DISTRIBUTOR_ADDRESS,
|
MERKLE_DISTRIBUTOR_ADDRESS,
|
||||||
MULTICALL2_ADDRESSES,
|
MULTICALL2_ADDRESSES,
|
||||||
V2_ROUTER_ADDRESS,
|
V2_ROUTER_ADDRESS,
|
||||||
@ -116,8 +116,11 @@ export function useMerkleDistributorContract() {
|
|||||||
return useContract(MERKLE_DISTRIBUTOR_ADDRESS, MERKLE_DISTRIBUTOR_ABI, true)
|
return useContract(MERKLE_DISTRIBUTOR_ADDRESS, MERKLE_DISTRIBUTOR_ABI, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useGovernanceContract() {
|
export function useGovernanceContracts(): (Contract | null)[] {
|
||||||
return useContract(GOVERNANCE_ADDRESS, GOVERNANCE_ABI, true)
|
return [
|
||||||
|
useContract(GOVERNANCE_ADDRESSES[0], GOVERNANCE_ABI, false),
|
||||||
|
useContract(GOVERNANCE_ADDRESSES[1], GOVERNANCE_ABI, true),
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useUniContract() {
|
export function useUniContract() {
|
||||||
|
@ -120,7 +120,8 @@ export default function Vote() {
|
|||||||
const toggleDelegateModal = useToggleDelegateModal()
|
const toggleDelegateModal = useToggleDelegateModal()
|
||||||
|
|
||||||
// get data to list all proposals
|
// get data to list all proposals
|
||||||
const allProposals: ProposalData[] = useAllProposalData()
|
// TODO don't hardcode for first gov alpha
|
||||||
|
const allProposals: ProposalData[] = useAllProposalData()[0]
|
||||||
|
|
||||||
// user data
|
// user data
|
||||||
const availableVotes: CurrencyAmount<Token> | undefined = useUserVotes()
|
const availableVotes: CurrencyAmount<Token> | undefined = useUserVotes()
|
||||||
@ -248,7 +249,7 @@ export default function Vote() {
|
|||||||
</TYPE.subHeader>
|
</TYPE.subHeader>
|
||||||
</EmptyProposals>
|
</EmptyProposals>
|
||||||
)}
|
)}
|
||||||
{allProposals?.map((p: ProposalData, i) => {
|
{allProposals?.reverse()?.map((p: ProposalData, i) => {
|
||||||
return (
|
return (
|
||||||
<Proposal as={Link} to={'/vote/' + p.id} key={i}>
|
<Proposal as={Link} to={'/vote/' + p.id} key={i}>
|
||||||
<ProposalNumber>{p.id}</ProposalNumber>
|
<ProposalNumber>{p.id}</ProposalNumber>
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
import { CurrencyAmount, Token } from '@uniswap/sdk-core'
|
import { CurrencyAmount, Token } from '@uniswap/sdk-core'
|
||||||
import { isAddress } from 'ethers/lib/utils'
|
import { isAddress } from 'ethers/lib/utils'
|
||||||
import { PROPOSAL_DESCRIPTION_TEXT } from '../../constants/proposals'
|
|
||||||
import { UNI } from '../../constants/tokens'
|
import { UNI } from '../../constants/tokens'
|
||||||
import { useGovernanceContract, useUniContract } from '../../hooks/useContract'
|
import { useGovernanceContracts, useUniContract } from '../../hooks/useContract'
|
||||||
import { calculateGasMargin } from '../../utils/calculateGasMargin'
|
import { calculateGasMargin } from '../../utils/calculateGasMargin'
|
||||||
import { useSingleCallResult, useSingleContractMultipleData } from '../multicall/hooks'
|
import { useSingleCallResult, useSingleContractMultipleData } from '../multicall/hooks'
|
||||||
import { useActiveWeb3React } from '../../hooks/web3'
|
import { useActiveWeb3React } from '../../hooks/web3'
|
||||||
@ -11,6 +10,7 @@ import { TransactionResponse } from '@ethersproject/providers'
|
|||||||
import { useTransactionAdder } from '../transactions/hooks'
|
import { useTransactionAdder } from '../transactions/hooks'
|
||||||
import { useState, useEffect, useCallback, useMemo } from 'react'
|
import { useState, useEffect, useCallback, useMemo } from 'react'
|
||||||
import { abi as GOV_ABI } from '@uniswap/governance/build/GovernorAlpha.json'
|
import { abi as GOV_ABI } from '@uniswap/governance/build/GovernorAlpha.json'
|
||||||
|
import { UNISWAP_GRANTS_PROPOSAL_DESCRIPTION } from 'constants/proposals/uniswap_grants_proposal_description'
|
||||||
|
|
||||||
interface ProposalDetail {
|
interface ProposalDetail {
|
||||||
target: string
|
target: string
|
||||||
@ -43,10 +43,9 @@ export enum ProposalState {
|
|||||||
Executed,
|
Executed,
|
||||||
}
|
}
|
||||||
|
|
||||||
// get count of all proposals made
|
// get count of all proposals made on the given governor alpha
|
||||||
export function useProposalCount(): number | undefined {
|
function useProposalCount(govContract: ethers.Contract | null): number | undefined {
|
||||||
const gov = useGovernanceContract()
|
const res = useSingleCallResult(govContract, 'proposalCount')
|
||||||
const res = useSingleCallResult(gov, 'proposalCount')
|
|
||||||
if (res.result && !res.loading) {
|
if (res.result && !res.loading) {
|
||||||
return parseInt(res.result[0])
|
return parseInt(res.result[0])
|
||||||
}
|
}
|
||||||
@ -58,15 +57,15 @@ export function useProposalCount(): number | undefined {
|
|||||||
* new proposal event.
|
* new proposal event.
|
||||||
*/
|
*/
|
||||||
const eventParser = new ethers.utils.Interface(GOV_ABI)
|
const eventParser = new ethers.utils.Interface(GOV_ABI)
|
||||||
export function useDataFromEventLogs() {
|
function useDataFromEventLogs(govContract: ethers.Contract | null) {
|
||||||
const { library, chainId } = useActiveWeb3React()
|
const { library, chainId } = useActiveWeb3React()
|
||||||
const [formattedEvents, setFormattedEvents] =
|
const [formattedEvents, setFormattedEvents] =
|
||||||
useState<{ description: string; details: { target: string; functionSig: string; callData: string }[] }[]>()
|
useState<{ description: string; details: { target: string; functionSig: string; callData: string }[] }[]>()
|
||||||
const govContract = useGovernanceContract()
|
|
||||||
|
|
||||||
// create filter for these specific events
|
// create filter for these specific events
|
||||||
const filter = useMemo(
|
const filter = useMemo(
|
||||||
() => (govContract ? { ...govContract.filters.ProposalCreated(), fromBlock: 0, toBlock: 'latest' } : undefined),
|
() =>
|
||||||
|
govContract ? { ...govContract.filters.ProposalCreated(), fromBlock: 10861678, toBlock: 'latest' } : undefined,
|
||||||
[govContract]
|
[govContract]
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -79,28 +78,25 @@ export function useDataFromEventLogs() {
|
|||||||
.getLogs(filter)
|
.getLogs(filter)
|
||||||
.then((proposalEvents) => {
|
.then((proposalEvents) => {
|
||||||
if (stale) return
|
if (stale) return
|
||||||
// reverse events to get them from newest to odlest
|
const formattedEventData = proposalEvents?.map((event) => {
|
||||||
const formattedEventData = proposalEvents
|
const eventParsed = eventParser.parseLog(event).args
|
||||||
?.map((event) => {
|
return {
|
||||||
const eventParsed = eventParser.parseLog(event).args
|
description: eventParsed.description,
|
||||||
return {
|
details: eventParsed.targets.map((target: string, i: number) => {
|
||||||
description: eventParsed.description,
|
const signature = eventParsed.signatures[i]
|
||||||
details: eventParsed.targets.map((target: string, i: number) => {
|
const [name, types] = signature.substr(0, signature.length - 1).split('(')
|
||||||
const signature = eventParsed.signatures[i]
|
|
||||||
const [name, types] = signature.substr(0, signature.length - 1).split('(')
|
|
||||||
|
|
||||||
const calldata = eventParsed.calldatas[i]
|
const calldata = eventParsed.calldatas[i]
|
||||||
const decoded = utils.defaultAbiCoder.decode(types.split(','), calldata)
|
const decoded = utils.defaultAbiCoder.decode(types.split(','), calldata)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
target,
|
target,
|
||||||
functionSig: name,
|
functionSig: name,
|
||||||
callData: decoded.join(', '),
|
callData: decoded.join(', '),
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.reverse()
|
|
||||||
setFormattedEvents(formattedEventData)
|
setFormattedEvents(formattedEventData)
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
@ -118,55 +114,93 @@ export function useDataFromEventLogs() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// get data for all past and active proposals
|
// get data for all past and active proposals
|
||||||
export function useAllProposalData() {
|
export function useAllProposalData(): ProposalData[][] {
|
||||||
const proposalCount = useProposalCount()
|
// fetch all governance contracts
|
||||||
const govContract = useGovernanceContract()
|
const govContracts = useGovernanceContracts()
|
||||||
|
|
||||||
const proposalIndexes = []
|
// fetch the proposal count on the active contract
|
||||||
for (let i = 1; i <= (proposalCount ?? 0); i++) {
|
const proposalCount = useProposalCount(govContracts[govContracts.length - 1])
|
||||||
proposalIndexes.push([i])
|
|
||||||
}
|
|
||||||
|
|
||||||
// get metadata from past events
|
// get all proposals for all contracts
|
||||||
const formattedEvents = useDataFromEventLogs()
|
const proposalsIndicesByGovContract = [
|
||||||
|
[1, 2, 3, 4], // hardcoded for first governor alpha
|
||||||
|
typeof proposalCount === 'number' ? new Array(proposalCount).fill(0).map((_, i) => i + 1) : [], // dynamic for current governor alpha
|
||||||
|
]
|
||||||
|
|
||||||
// get all proposal entities
|
// get all proposal entities
|
||||||
const allProposals = useSingleContractMultipleData(govContract, 'proposals', proposalIndexes)
|
const allProposalsByGovContract = [
|
||||||
|
useSingleContractMultipleData(
|
||||||
|
govContracts[0],
|
||||||
|
'proposals',
|
||||||
|
proposalsIndicesByGovContract[0].map((i) => [i])
|
||||||
|
),
|
||||||
|
useSingleContractMultipleData(
|
||||||
|
govContracts[1],
|
||||||
|
'proposals',
|
||||||
|
proposalsIndicesByGovContract[1].map((i) => [i])
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
||||||
// get all proposal states
|
// get all proposal states
|
||||||
const allProposalStates = useSingleContractMultipleData(govContract, 'state', proposalIndexes)
|
const allProposalStatesByGovContract = [
|
||||||
|
useSingleContractMultipleData(
|
||||||
|
govContracts[0],
|
||||||
|
'state',
|
||||||
|
proposalsIndicesByGovContract[0].map((i) => [i])
|
||||||
|
),
|
||||||
|
useSingleContractMultipleData(
|
||||||
|
govContracts[1],
|
||||||
|
'state',
|
||||||
|
proposalsIndicesByGovContract[1].map((i) => [i])
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
||||||
if (formattedEvents && allProposals && allProposalStates) {
|
// get metadata from past events
|
||||||
allProposals.reverse()
|
const formattedEventsByGovContract = [useDataFromEventLogs(govContracts[0]), useDataFromEventLogs(govContracts[1])]
|
||||||
allProposalStates.reverse()
|
|
||||||
|
|
||||||
return allProposals
|
const returnData: ProposalData[][] = []
|
||||||
.filter((p, i) => {
|
|
||||||
return Boolean(p.result) && Boolean(allProposalStates[i]?.result) && Boolean(formattedEvents[i])
|
for (let governorIndex = 0; governorIndex < allProposalsByGovContract.length; governorIndex++) {
|
||||||
})
|
const allProposals = allProposalsByGovContract[governorIndex]
|
||||||
.map((p, i) => {
|
const allProposalStates = allProposalStatesByGovContract[governorIndex]
|
||||||
const description = PROPOSAL_DESCRIPTION_TEXT[allProposals.length - i - 1] || formattedEvents[i].description
|
const formattedEvents = formattedEventsByGovContract[governorIndex]
|
||||||
const formattedProposal: ProposalData = {
|
|
||||||
id: allProposals[i]?.result?.id.toString(),
|
if (
|
||||||
title: description?.split(/# |\n/g)[1] || 'Untitled',
|
allProposals?.every((p) => Boolean(p.result)) &&
|
||||||
description: description || 'No description.',
|
allProposalStates?.every((p) => Boolean(p.result)) &&
|
||||||
proposer: allProposals[i]?.result?.proposer,
|
formattedEvents?.every((p) => Boolean(p))
|
||||||
status: allProposalStates[i]?.result?.[0] ?? ProposalState.Undetermined,
|
) {
|
||||||
forCount: parseFloat(ethers.utils.formatUnits(allProposals[i]?.result?.forVotes.toString(), 18)),
|
returnData.push(
|
||||||
againstCount: parseFloat(ethers.utils.formatUnits(allProposals[i]?.result?.againstVotes.toString(), 18)),
|
allProposals.map((proposal, i): ProposalData => {
|
||||||
startBlock: parseInt(allProposals[i]?.result?.startBlock?.toString()),
|
let description = formattedEvents[i].description
|
||||||
endBlock: parseInt(allProposals[i]?.result?.endBlock?.toString()),
|
// overwrite broken description
|
||||||
details: formattedEvents[i].details,
|
if (governorIndex === 0 && i === 2) description = UNISWAP_GRANTS_PROPOSAL_DESCRIPTION
|
||||||
}
|
|
||||||
return formattedProposal
|
return {
|
||||||
})
|
id: proposal?.result?.id.toString(),
|
||||||
} else {
|
title: description?.split(/# |\n/g)[1] ?? 'Untitled',
|
||||||
return []
|
description: description ?? 'No description.',
|
||||||
|
proposer: proposal?.result?.proposer,
|
||||||
|
status: allProposalStates[i]?.result?.[0] ?? ProposalState.Undetermined,
|
||||||
|
forCount: parseFloat(ethers.utils.formatUnits(proposal?.result?.forVotes.toString(), 18)),
|
||||||
|
againstCount: parseFloat(ethers.utils.formatUnits(proposal?.result?.againstVotes.toString(), 18)),
|
||||||
|
startBlock: parseInt(proposal?.result?.startBlock?.toString()),
|
||||||
|
endBlock: parseInt(proposal?.result?.endBlock?.toString()),
|
||||||
|
details: formattedEvents[i].details,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
returnData.push([])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return returnData
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useProposalData(id: string): ProposalData | undefined {
|
export function useProposalData(id: string): ProposalData | undefined {
|
||||||
const allProposalData = useAllProposalData()
|
// TODO don't hardcode for first gov alpha
|
||||||
|
const allProposalData = useAllProposalData()[0]
|
||||||
return allProposalData?.find((p) => p.id === id)
|
return allProposalData?.find((p) => p.id === id)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -232,7 +266,10 @@ export function useVoteCallback(): {
|
|||||||
} {
|
} {
|
||||||
const { account } = useActiveWeb3React()
|
const { account } = useActiveWeb3React()
|
||||||
|
|
||||||
const govContract = useGovernanceContract()
|
// we only care about voting on the active governance contract
|
||||||
|
const govContracts = useGovernanceContracts()
|
||||||
|
const govContract = govContracts[govContracts.length - 1]
|
||||||
|
|
||||||
const addTransaction = useTransactionAdder()
|
const addTransaction = useTransactionAdder()
|
||||||
|
|
||||||
const voteCallback = useCallback(
|
const voteCallback = useCallback(
|
||||||
|
Loading…
Reference in New Issue
Block a user