diff --git a/packages/govern-console/.eslintrc.js b/packages/govern-console/.eslintrc.js
index a893cb905..4910dbde5 100644
--- a/packages/govern-console/.eslintrc.js
+++ b/packages/govern-console/.eslintrc.js
@@ -36,7 +36,7 @@ module.exports = {
settings: {
react: {
pragma: 'React',
- version: '16.6',
+ version: '16.13.1',
},
'import/parsers': {
'@typescript-eslint/parser': ['.ts', '.tsx'],
diff --git a/packages/govern-console/package.json b/packages/govern-console/package.json
index d82eb07b0..312efe935 100644
--- a/packages/govern-console/package.json
+++ b/packages/govern-console/package.json
@@ -19,7 +19,7 @@
"apollo-link-http": "^1.5.17",
"bn.js": "^5.1.3",
"clipboard-polyfill": "^2.8.6",
- "dayjs": "^1.8.35",
+ "date-fns": "^2.16.1",
"ethers": "^5.0.14",
"graphql": "^15.0.0",
"graphql-tag": "^2.10.3",
diff --git a/packages/govern-console/src/App.tsx b/packages/govern-console/src/App.tsx
index 847295495..ee364fffe 100644
--- a/packages/govern-console/src/App.tsx
+++ b/packages/govern-console/src/App.tsx
@@ -2,9 +2,9 @@ import React from 'react'
import { HashRouter as Router, Route, Switch } from 'react-router-dom'
import 'styled-components/macro'
import TopHeader from './components/Header/Header'
-import DaoSelector from './pages/DaoSelector'
-import DaoView from './pages/DaoView'
-import ErcTool from './Tools/Erc'
+import SelectDao from './pages/SelectDao'
+import ViewDao from './pages/ViewDao'
+import ErcTool from './apps/Erc'
function App() {
return (
@@ -19,13 +19,13 @@ function App() {
-
+
-
+
diff --git a/packages/govern-console/src/Tools/Erc.tsx b/packages/govern-console/src/apps/Erc.tsx
similarity index 100%
rename from packages/govern-console/src/Tools/Erc.tsx
rename to packages/govern-console/src/apps/Erc.tsx
diff --git a/packages/govern-console/src/components/Frame/Frame.tsx b/packages/govern-console/src/components/Frame/Frame.tsx
new file mode 100644
index 000000000..d2d8595c7
--- /dev/null
+++ b/packages/govern-console/src/components/Frame/Frame.tsx
@@ -0,0 +1,32 @@
+import * as React from 'react'
+import 'styled-components/macro'
+
+type FrameProps = {
+ children: React.ReactNode
+}
+
+export default function Frame({ children }: FrameProps) {
+ return (
+
+ {children}
+
+ )
+}
diff --git a/packages/govern-console/src/components/Info/Info.tsx b/packages/govern-console/src/components/Info/Info.tsx
new file mode 100644
index 000000000..1f5581c26
--- /dev/null
+++ b/packages/govern-console/src/components/Info/Info.tsx
@@ -0,0 +1,32 @@
+import React from 'react'
+import 'styled-components/macro'
+
+type InfoProps = {
+ mode: 'error' | 'info' | 'success' | ''
+ children: React.ReactNode
+}
+
+function resolveColorsFromStatus(mode: string): string {
+ if (mode === 'error') {
+ return 'red'
+ }
+ if (mode === 'success') {
+ return 'green'
+ }
+ return 'cyan'
+}
+
+export default function Info({ mode, children }: InfoProps) {
+ return (
+
+ {children}
+
+ )
+}
diff --git a/packages/govern-console/src/components/NewAction.tsx b/packages/govern-console/src/components/NewAction/NewAction.tsx
similarity index 67%
rename from packages/govern-console/src/components/NewAction.tsx
rename to packages/govern-console/src/components/NewAction/NewAction.tsx
index 4b3ef06f2..3156236ee 100644
--- a/packages/govern-console/src/components/NewAction.tsx
+++ b/packages/govern-console/src/components/NewAction/NewAction.tsx
@@ -4,11 +4,14 @@ import { useWallet } from 'use-wallet'
import abiCoder from 'web3-eth-abi'
import { toHex } from 'web3-utils'
import 'styled-components/macro'
-import Button from './Button'
-import { useContract } from '../lib/web3-contracts'
-import queueAbi from '../lib/abi/GovernQueue.json'
+import Button from '../Button'
+import Frame from '../Frame/Frame'
+import { useContract } from '../../lib/web3-contracts'
+import queueAbi from '../../lib/abi/GovernQueue.json'
const EMPTY_BYTES = '0x00'
+const EMPTY_FAILURE_MAP =
+ '0x0000000000000000000000000000000000000000000000000000000000000000'
type Input = {
name: string | undefined
@@ -37,6 +40,9 @@ export default function NewAction({
const [contractAddress, setContractAddress] = useState('')
const [parsedAbi, setParsedAbi] = useState([])
const [proof, setProof] = useState('')
+ const [executionResult, setExecutionResult] = useState('')
+ const [type, setType] = useState('')
+
const queueContract = useContract(queueAddress, queueAbi)
const handleParseAbi = useCallback(
@@ -52,6 +58,24 @@ export default function NewAction({
[abi],
)
+ const handleSetExecutionResult = useCallback(
+ (result, message) => {
+ if (result === 'confirmed') {
+ setType('green')
+ setExecutionResult(message)
+ }
+ if (result === 'info') {
+ setType('cyan')
+ setExecutionResult(message)
+ }
+ if (result === 'error') {
+ setType('red')
+ setExecutionResult(message)
+ }
+ },
+ [setExecutionResult],
+ )
+
return (
<>
New action
-
+
+ {executionResult && (
+
+ {executionResult}
+
+ )}
+
>
)
}
@@ -174,6 +186,7 @@ type ContractCallHandlerProps = {
contractAddress: string
config: any
executor: string
+ handleSetExecutionResult: (result: string, v: string) => void
inputs: Input[] | any[]
name: string
proof: string
@@ -185,6 +198,7 @@ function ContractCallHandler({
config,
contractAddress,
executor,
+ handleSetExecutionResult,
inputs,
name,
proof,
@@ -238,48 +252,61 @@ function ContractCallHandler({
const bnNonce = new BN(nonce.toString())
const newNonce = bnNonce.add(new BN('1'))
- // Right now + 120 seconds into the future (in the future, this should be configurable)
- const currentDate = Math.round(Date.now() / 1000) + 120
-
- const tx = await queueContract['schedule'](
- {
- payload: {
- nonce: newNonce.toString(),
- executionTime: currentDate,
- submitter: account,
- executor,
- actions: [
- {
- to: contractAddress,
- value: EMPTY_BYTES,
- data: encodedFunctionCall,
- },
- ],
- allowFailuresMap: '0x0000000000000000000000000000000000000000000000000000000000000000',
- proof: proof ? toHex(proof) : EMPTY_BYTES,
- },
- config: {
- executionDelay: config.executionDelay,
- scheduleDeposit: {
- token: config.scheduleDeposit.token.id,
- amount: config.scheduleDeposit.amount,
- },
- challengeDeposit: {
- token: config.challengeDeposit.token.id,
- amount: config.challengeDeposit.amount,
+ // TODO: handle token approvals
+ // Current time + 30 secs buffer.
+ // This is necessary for DAOs with lower execution delays, in which
+ // the tx getting picked up by a later block can make the tx fail.
+ const currentDate =
+ Math.ceil(Date.now() / 1000) + Number(config.executionDelay) + 30
+ const container = {
+ payload: {
+ nonce: newNonce.toString(),
+ executionTime: currentDate,
+ submitter: account,
+ executor,
+ actions: [
+ {
+ to: contractAddress,
+ value: EMPTY_BYTES,
+ data: encodedFunctionCall,
},
- resolver: config.resolver,
- rules: config.rules,
- },
+ ],
+ allowFailuresMap: EMPTY_FAILURE_MAP,
+ proof: proof ? toHex(proof) : EMPTY_BYTES,
},
- {
- gasLimit: 500000,
+ config: {
+ executionDelay: config.executionDelay,
+ scheduleDeposit: {
+ token: config.scheduleDeposit.token,
+ amount: config.scheduleDeposit.amount,
+ },
+ challengeDeposit: {
+ token: config.challengeDeposit.token,
+ amount: config.challengeDeposit.amount,
+ },
+ resolver: config.resolver,
+ rules: config.rules,
},
- )
+ }
+
+ const tx = await queueContract.schedule(container, {
+ gasLimit: 500000,
+ })
+
+ handleSetExecutionResult('info', `Sending transaction.`)
+ await tx.wait(1)
setResult(tx.hash)
+ handleSetExecutionResult(
+ 'confirmed',
+ `Transaction sent successfully. hash: ${tx.hash}`,
+ )
} catch (e) {
console.error(e)
+ handleSetExecutionResult(
+ 'error',
+ `There was an error with the transaction.`,
+ )
}
},
[
@@ -287,8 +314,9 @@ function ContractCallHandler({
config,
contractAddress,
executor,
- proof,
+ handleSetExecutionResult,
queueContract,
+ proof,
rawAbiItem,
values,
],
diff --git a/packages/govern-console/src/components/ViewAction/ViewAction.tsx b/packages/govern-console/src/components/ViewAction/ViewAction.tsx
new file mode 100644
index 000000000..9cbcf2d20
--- /dev/null
+++ b/packages/govern-console/src/components/ViewAction/ViewAction.tsx
@@ -0,0 +1,376 @@
+import React, { useMemo, useCallback, useState } from 'react'
+import { useParams } from 'react-router-dom'
+import 'styled-components/macro'
+import Button from '../Button'
+import Frame from '../Frame/Frame'
+import Info from '../Info/Info'
+import { useContract } from '../../lib/web3-contracts'
+import { shortenAddress } from '../../lib/web3-utils'
+import queueAbi from '../../lib/abi/GovernQueue.json'
+import { useWallet } from '../../Providers/Wallet'
+
+const EMPTY_FAILURE_MAP =
+ '0x0000000000000000000000000000000000000000000000000000000000000000'
+
+type Collateral = {
+ token: string
+ amount: string
+}
+
+type Config = {
+ executionDelay: string
+ scheduleDeposit: Collateral
+ challengeDeposit: Collateral
+ resolver: string
+ rules: string
+}
+
+type Action = {
+ id: string
+ to: string
+ value: string
+ data: string
+}
+
+type Payload = {
+ id: string
+ nonce: string
+ executionTime: string
+ submitter: string
+ executor: any
+ actions: Action[]
+ proof: string
+}
+
+type ContainerEventChallenge = {
+ id: string
+ container: any
+ createdAt: string
+ actor: string
+ collateral: Collateral
+ disputeId: string
+ reason: string
+ resolver: string
+}
+
+type ContainerEventExecute = {
+ id: string
+ container: any
+ createdAt: string
+ execResults: string[]
+}
+
+type ContainerEventResolve = {
+ id: string
+ container: any
+ createdAt: string
+ approved: Boolean
+}
+
+type ContainerEventRule = {
+ id: string
+ container: any
+ createdAt: string
+ ruling: string
+}
+
+type ContainerEventSchedule = {
+ id: string
+ container: any
+ createdAt: string
+ collateral: Collateral
+}
+
+type ContainerEventSubmitEvidence = {
+ id: string
+ container: any
+ createdAt: string
+ evidence: string
+ submitter: string
+ finished: Boolean
+}
+
+type ContainerEventVeto = {
+ id: string
+ container: any
+ created: string
+ reason: string
+}
+
+type ContainerEvent =
+ | ContainerEventChallenge
+ | ContainerEventExecute
+ | ContainerEventResolve
+ | ContainerEventRule
+ | ContainerEventSchedule
+ | ContainerEventSubmitEvidence
+ | ContainerEventVeto
+
+type Container = {
+ id: string
+ queue: string
+ state: string
+ config: Config
+ payload: Payload
+ history: ContainerEvent[]
+}
+
+type ViewActionWrapperProps = {
+ containers: Container[]
+ queueAddress: string
+}
+
+type ViewActionProps = {
+ container: Container
+ queueAddress: string
+}
+
+function ViewAction({ container, queueAddress }: ViewActionProps) {
+ const { wallet } = useWallet()
+ const { status: accountStatus } = wallet
+ const [executionStatus, setExecutionStatus] = useState('')
+ const [statusType, setStatusType] = useState<
+ 'error' | 'info' | 'success' | ''
+ >('')
+ const queueContract = useContract(queueAddress, queueAbi)
+
+ const handleSetExecutionStatus = useCallback(
+ (result, message) => {
+ setStatusType(result)
+ setExecutionStatus(message)
+ },
+ [setExecutionStatus, setStatusType],
+ )
+
+ const execute = useCallback(async () => {
+ if (accountStatus !== 'connected') {
+ alert('Executing actions requires a signer. Please connect your account.')
+ return
+ }
+ const payloadActions = container.payload.actions.map((action: Action) => ({
+ to: action.to,
+ value: action.value,
+ data: action.data,
+ }))
+ const craftedContainer = {
+ payload: {
+ nonce: container.payload.nonce,
+ executionTime: container.payload.executionTime,
+ submitter: container.payload.submitter,
+ executor: container.payload.executor.address,
+ actions: payloadActions,
+ allowFailuresMap: EMPTY_FAILURE_MAP,
+ proof: container.payload.proof,
+ },
+ config: {
+ executionDelay: container.config.executionDelay,
+ scheduleDeposit: {
+ token: container.config.scheduleDeposit.token,
+ amount: container.config.scheduleDeposit.amount,
+ },
+ challengeDeposit: {
+ token: container.config.challengeDeposit.token,
+ amount: container.config.challengeDeposit.amount,
+ },
+ resolver: container.config.resolver,
+ rules: container.config.rules,
+ },
+ }
+
+ try {
+ const tx = await queueContract!.execute(craftedContainer, {
+ gasLimit: 500000,
+ })
+ handleSetExecutionStatus('info', `Sending transaction.`)
+ await tx.wait(1)
+ handleSetExecutionStatus(
+ 'success',
+ `Transaction sent successfully. hash: ${tx.hash}`,
+ )
+ } catch (err) {
+ console.log(err)
+ handleSetExecutionStatus(
+ 'error',
+ `There was an error with the transaction.`,
+ )
+ }
+ }, [accountStatus, container, handleSetExecutionStatus, queueContract])
+
+ const veto = useCallback(async () => {
+ if (accountStatus !== 'connected') {
+ alert('Executing actions requires a signer. Please connect your account.')
+ return
+ }
+ try {
+ const containerHash = container.id
+ const tx = await queueContract!.veto(containerHash, '0x00', {
+ gasLimit: 500000,
+ })
+ handleSetExecutionStatus('info', `Sending transaction.`)
+ await tx.wait(1)
+ handleSetExecutionStatus(
+ 'success',
+ `Transaction sent successfully. hash: ${tx.hash}`,
+ )
+ } catch (err) {
+ console.log(err)
+ handleSetExecutionStatus(
+ 'error',
+ `There was an error with the transaction.`,
+ )
+ }
+ }, [accountStatus, container, handleSetExecutionStatus, queueContract])
+
+ const challenge = useCallback(async () => {
+ if (accountStatus !== 'connected') {
+ alert('Executing actions requires a signer. Please connect your account.')
+ return
+ }
+ const payloadActions = container.payload.actions.map((action: Action) => ({
+ to: action.to,
+ value: action.value,
+ data: action.data,
+ }))
+ // TODO: handle token approvals first
+ const craftedContainer = {
+ payload: {
+ nonce: container.payload.nonce,
+ executionTime: container.payload.executionTime,
+ submitter: container.payload.submitter,
+ executor: container.payload.executor.address,
+ actions: payloadActions,
+ allowFailuresMap: EMPTY_FAILURE_MAP,
+ proof: container.payload.proof,
+ },
+ config: {
+ executionDelay: container.config.executionDelay,
+ scheduleDeposit: {
+ token: container.config.scheduleDeposit.token,
+ amount: container.config.scheduleDeposit.amount,
+ },
+ challengeDeposit: {
+ token: container.config.challengeDeposit.token,
+ amount: container.config.challengeDeposit.amount,
+ },
+ resolver: container.config.resolver,
+ rules: container.config.rules,
+ },
+ }
+ try {
+ const tx = await queueContract!.challenge(craftedContainer, '0x00', {
+ gasLimit: 500000,
+ })
+ handleSetExecutionStatus('info', `Sending transaction.`)
+ await tx.wait(1)
+ handleSetExecutionStatus(
+ 'success',
+ `Transaction sent successfully. hash: ${tx.hash}`,
+ )
+ } catch (err) {
+ console.log(err)
+ handleSetExecutionStatus(
+ 'error',
+ `There was an error with the transaction.`,
+ )
+ }
+ }, [accountStatus, container, handleSetExecutionStatus, queueContract])
+
+ return (
+ <>
+
+ Action {shortenAddress(container.id)}
+ Status
+ {container.state}
+ {executionStatus && {executionStatus}}
+
+
+
+ Available actions
+
+
+
+
+
+
+ Action Payload
+ Nonce
+ {container.payload.nonce}
+ Execution time
+ {container.payload.executionTime}
+ Submitter
+ {container.payload.submitter}
+ Proof (Justification)
+ {container.payload.proof}
+ On-chain actions
+
+
+ {container.payload.actions.map((action: Action) => (
+
+ - to: {action.to}
+ - value: {action.value}
+ - data: {action.data}
+
+ ))}
+
+
+
+
+
+ Action Configuration
+ Execution Delay
+ {container.config.executionDelay}
+ Schedule deposit
+ Token: {container.config.scheduleDeposit.token}
+ Amount: {container.config.scheduleDeposit.amount}
+ Challenge deposit
+ Token: {container.config.challengeDeposit.token}
+ Amount: {container.config.challengeDeposit.amount}
+ Resolver
+ {container.config.resolver}
+ Rules
+ {container.config.rules}
+
+ >
+ )
+}
+
+export default function ViewActionWrapper({
+ containers,
+ queueAddress,
+}: ViewActionWrapperProps) {
+ const { containerId }: any = useParams()
+ const container = useMemo(() => {
+ return containers.find(container => container.id === containerId)
+ }, [containerId, containers])
+
+ if (!container) {
+ return Container not found.
+ }
+
+ return
+}
diff --git a/packages/govern-console/src/components/ViewDao/ViewDao.tsx b/packages/govern-console/src/components/ViewDao/ViewDao.tsx
new file mode 100644
index 000000000..e430693dc
--- /dev/null
+++ b/packages/govern-console/src/components/ViewDao/ViewDao.tsx
@@ -0,0 +1,150 @@
+import React, { useCallback, useMemo } from 'react'
+import { useHistory, useParams } from 'react-router-dom'
+import 'styled-components/macro'
+import Button from '../Button'
+import Frame from '../Frame/Frame'
+import { KNOWN_GOVERN_ROLES, KNOWN_QUEUE_ROLES } from '../../lib/known-roles'
+import { shortenAddress, ETH_ANY_ADDRESS } from '../../lib/web3-utils'
+
+type ViewDaoProps = {
+ dao: any
+}
+
+export default function ViewDao({ dao }: ViewDaoProps) {
+ const { daoAddress }: any = useParams()
+ const history = useHistory()
+
+ const handleNewAction = useCallback(() => {
+ history.push(`/${daoAddress}/new-action`)
+ }, [history, daoAddress])
+
+ const hasActions = useMemo(() => dao.queue.queued.length > 0, [dao])
+
+ return (
+ <>
+
+ Info for {daoAddress}
+
+
+ Govern Executor
+ Address
+ {dao.executor.address}
+ Govern Queue
+ Address
+ {dao.queue.address}
+ Config
+ Execution delay: {dao.queue.config.executionDelay}
+ Schedule collateral:
+
+ - Token: {dao.queue.config.scheduleDeposit.token}
+ - Amount: {dao.queue.config.scheduleDeposit.amount}
+
+ Challenge collateral:
+
+ - Token: {dao.queue.config.challengeDeposit.token}
+ - Amount: {dao.queue.config.challengeDeposit.amount}
+
+
+
+ Actions
+ {hasActions
+ ? dao.queue.queued.map(({ id }: { id: string }) => (
+
+ ))
+ : 'No actions.'}
+
+
+
+
+
+ Permissions for Govern
+ {dao.executor.roles.map((role: any) => {
+ return (
+
+
+ {KNOWN_GOVERN_ROLES.get(role.selector)} - {role.selector}
+
+
+ Who has permission:{' '}
+ {role.who === ETH_ANY_ADDRESS ? 'Anyone' : role.who}
+
+
+ )
+ })}
+
+
+ Permissions for GovernQueue
+ {dao.queue.roles.map((role: any) => {
+ return (
+
+
+ {KNOWN_QUEUE_ROLES.get(role.selector)} - {role.selector}
+
+
+ Who has permission:{' '}
+ {role.who === ETH_ANY_ADDRESS ? 'Anyone' : role.who}
+
+
+ )
+ })}
+
+ >
+ )
+}
+
+type ActionCardProps = {
+ id: string
+}
+
+function ActionCard({ id }: ActionCardProps) {
+ const history = useHistory()
+ const { daoAddress }: any = useParams()
+
+ const handleCardClick = useCallback(() => {
+ history.push(`${daoAddress}/view-action/${id}`)
+ }, [daoAddress, history, id])
+
+ return (
+
+ )
+}
diff --git a/packages/govern-console/src/environment.ts b/packages/govern-console/src/environment.ts
index b6ff3e85d..04971bcb9 100644
--- a/packages/govern-console/src/environment.ts
+++ b/packages/govern-console/src/environment.ts
@@ -1,10 +1,8 @@
-// rinkeby
const CHAIN_ID_DEFAULT = 4
const ENV_VARS = {
CHAIN_ID() {
- // @ts-ignore
- const chainId = parseInt(process.env.REACT_APP_CHAIN_ID)
+ const chainId = parseInt(process.env.REACT_APP_CHAIN_ID ?? '4')
return isNaN(chainId) ? CHAIN_ID_DEFAULT : chainId
},
ENABLE_SENTRY() {
diff --git a/packages/govern-console/src/index.tsx b/packages/govern-console/src/index.tsx
index 66c25adfa..b84f347bc 100644
--- a/packages/govern-console/src/index.tsx
+++ b/packages/govern-console/src/index.tsx
@@ -4,22 +4,26 @@ import { createGlobalStyle } from 'styled-components'
import 'styled-components/macro'
import {
ApolloClient,
+ ApolloProvider,
InMemoryCache,
NormalizedCacheObject,
- ApolloProvider
-} from '@apollo/client';
+} from '@apollo/client'
import App from './App'
import GeneralProvider from './Providers/GeneralProvider'
-export const rinkebyClient: ApolloClient = new ApolloClient({
- uri: 'https://api.thegraph.com/subgraphs/name/aragon/aragon-govern-rinkeby',
- cache: new InMemoryCache()
-});
+export const rinkebyClient: ApolloClient = new ApolloClient(
+ {
+ uri: 'https://api.thegraph.com/subgraphs/name/evalir/aragon-govern-rinkeby',
+ cache: new InMemoryCache(),
+ },
+)
-export const mainnetClient: ApolloClient = new ApolloClient({
- uri: 'https://api.thegraph.com/subgraphs/name/aragon/aragon-govern-mainnet',
- cache: new InMemoryCache()
-})
+export const mainnetClient: ApolloClient = new ApolloClient(
+ {
+ uri: 'https://api.thegraph.com/subgraphs/name/aragon/aragon-govern-mainnet',
+ cache: new InMemoryCache(),
+ },
+)
const GlobalStyle = createGlobalStyle`
*, *:before, *:after {
@@ -68,7 +72,6 @@ render(
-
- ,
+ ,
document.getElementById('root'),
)
diff --git a/packages/govern-console/src/lib/date-utils.js b/packages/govern-console/src/lib/date-utils.js
deleted file mode 100644
index 742a89b36..000000000
--- a/packages/govern-console/src/lib/date-utils.js
+++ /dev/null
@@ -1,15 +0,0 @@
-import dayjs from 'dayjs'
-
-export function getExecutionTimeFromUnix(futureTimestamp) {
- const now = dayjs()
- const executionTime = dayjs.unix(Number(futureTimestamp))
-
- const minutesDiff = executionTime.diff(now, 'm')
-
- if (minutesDiff <= 0) {
- const secondsDiff = executionTime.diff(now, 's')
- return executionTime.diff(now, 's') <= 0 ? 'None' : `0m ${secondsDiff}s`
- }
-
- return `${minutesDiff}m`
-}
diff --git a/packages/govern-console/src/lib/known-contracts.js b/packages/govern-console/src/lib/known-contracts.ts
similarity index 82%
rename from packages/govern-console/src/lib/known-contracts.js
rename to packages/govern-console/src/lib/known-contracts.ts
index c3eb2e84c..66e41748f 100644
--- a/packages/govern-console/src/lib/known-contracts.js
+++ b/packages/govern-console/src/lib/known-contracts.ts
@@ -12,11 +12,12 @@ const KNOWN_CONTRACTS_BY_ENV = new Map([
const ABIS = new Map([
['AGREEMENT', agreementAbi],
- ['TOKEN', erc20Abi]
+ ['TOKEN', erc20Abi],
])
-export function getKnownContract(name) {
+export function getKnownContract(name: string): any {
const knownContracts = KNOWN_CONTRACTS_BY_ENV.get('4') || {}
+ // @ts-ignore
return [knownContracts[name] || null, ABIS.get(name) || []]
}
diff --git a/packages/govern-console/src/lib/known-roles.ts b/packages/govern-console/src/lib/known-roles.ts
new file mode 100644
index 000000000..611165af6
--- /dev/null
+++ b/packages/govern-console/src/lib/known-roles.ts
@@ -0,0 +1,10 @@
+export const KNOWN_QUEUE_ROLES = new Map([
+ ['0x977d8964', 'schedule'],
+ ['0x3a139c71', 'execute'],
+ ['0x70576158', 'challenge'],
+ ['0x72896761', 'configure'],
+ ['0xc04c87b8', 'veto'],
+ ['0x586df604', 'ROOT_ROLE'],
+])
+
+export const KNOWN_GOVERN_ROLES = new Map([['0xc2d85afc', 'exec']])
diff --git a/packages/govern-console/src/lib/theme.ts b/packages/govern-console/src/lib/theme.ts
new file mode 100644
index 000000000..5ea60925b
--- /dev/null
+++ b/packages/govern-console/src/lib/theme.ts
@@ -0,0 +1,3 @@
+export default {
+
+}
diff --git a/packages/govern-console/src/lib/utils.ts b/packages/govern-console/src/lib/utils.ts
new file mode 100644
index 000000000..56012e8f1
--- /dev/null
+++ b/packages/govern-console/src/lib/utils.ts
@@ -0,0 +1,8 @@
+export function log(...params) {
+ if (
+ process.env.NODE_ENV !== 'production' &&
+ process.env.NODE_ENV !== 'test'
+ ) {
+ console.log(...params)
+ }
+}
diff --git a/packages/govern-console/src/lib/web3-contracts.js b/packages/govern-console/src/lib/web3-contracts.js
index cb769ebf7..591533536 100644
--- a/packages/govern-console/src/lib/web3-contracts.js
+++ b/packages/govern-console/src/lib/web3-contracts.js
@@ -6,7 +6,7 @@ import {
getDefaultProvider,
} from 'ethers'
import { useWallet } from 'use-wallet'
-import { getKnownContract } from './known-contracts.js'
+import { getKnownContract } from './known-contracts'
import { useChainId } from '../Providers/ChainId'
import { bigNum, getNetworkNode } from './web3-utils'
diff --git a/packages/govern-console/src/lib/web3-utils.js b/packages/govern-console/src/lib/web3-utils.js
index ddcd3acbf..8585880cc 100644
--- a/packages/govern-console/src/lib/web3-utils.js
+++ b/packages/govern-console/src/lib/web3-utils.js
@@ -1,7 +1,9 @@
import env from '../environment'
import { utils as EthersUtils } from 'ethers'
+
export const DEFAULT_LOCAL_CHAIN = 'private'
export const ETH_FAKE_ADDRESS = `0x${''.padEnd(40, '0')}`
+export const ETH_ANY_ADDRESS = '0xffffffffffffffffffffffffffffffffffffffff'
const ETH_ADDRESS_SPLIT_REGEX = /(0x[a-fA-F0-9]{40}(?:\b|\.|,|\?|!|;))/g
const ETH_ADDRESS_TEST_REGEX = /(0x[a-fA-F0-9]{40}(?:\b|\.|,|\?|!|;))/g
@@ -113,8 +115,9 @@ export function isLocalOrUnknownNetwork(chainId = env('CHAIN_ID')) {
export function hexToAscii(hexx) {
const hex = hexx.toString()
let str = ''
- for (let i = 0; i < hex.length && hex.substr(i, 2) !== '00'; i += 2)
+ for (let i = 0; i < hex.length && hex.substr(i, 2) !== '00'; i += 2) {
str += String.fromCharCode(parseInt(hex.substr(i, 2), 16))
+ }
return str
}
diff --git a/packages/govern-console/src/pages/DaoView.tsx b/packages/govern-console/src/pages/DaoView.tsx
deleted file mode 100644
index 7c2bc8a55..000000000
--- a/packages/govern-console/src/pages/DaoView.tsx
+++ /dev/null
@@ -1,343 +0,0 @@
-import React, { useCallback, useMemo } from 'react'
-import {
- Route,
- Switch,
- useHistory,
- useRouteMatch,
- useParams,
-} from 'react-router-dom'
-import 'styled-components/macro'
-import { gql, useQuery } from '@apollo/client'
-import Button from '../components/Button'
-import NewAction from '../components/NewAction'
-import { useChainId } from '../Providers/ChainId'
-import { rinkebyClient, mainnetClient } from '../index'
-
-const ANY_ADDRESS = '0xffffffffffffffffffffffffffffffffffffffff'
-
-const KNOWN_QUEUE_ROLES = new Map([
- ['0x977d8964', 'schedule'],
- ['0x3a139c71', 'execute'],
- ['0x70576158', 'challenge'],
- ['0x72896761', 'configure'],
- ['0xc04c87b8', 'veto'],
- ['0x586df604', 'ROOT_ROLE'],
-])
-
-const KNOWN_GOVERN_ROLES = new Map([['0xc2d85afc', 'exec']])
-
-const DAO_QUERY = gql`
- query DAOQuery($name: String) {
- registryEntry(id: $name) {
- name
- executor {
- address
- roles {
- selector
- who
- frozen
- }
- }
- queue {
- address
- roles {
- selector
- who
- frozen
- }
- queued {
- id
- state
- payload {
- nonce
- executionTime
- submitter
- proof
- }
- }
- config {
- executionDelay
- scheduleDeposit {
- token
- amount
- }
- challengeDeposit {
- token
- amount
- }
- resolver
- rules
- }
- }
- }
- }
-`
-
-export default function DaoView() {
- const { chainId } = useChainId()
- const { daoAddress }: any = useParams()
- const { path } = useRouteMatch()
- const { data, loading, error } = useQuery(DAO_QUERY, {
- variables: {
- name: daoAddress,
- },
- client: chainId === 4 ? rinkebyClient : mainnetClient,
- })
-
- if (loading) {
- return Loading...
- }
-
- if (error) {
- console.error(error)
- return Error
- }
-
- if (!data.registryEntry) {
- return DAO not found.
- }
-
- return (
-
-
-
-
-
-
-
-
-
-
- Route not found :(
-
-
- )
-}
-
-type DaoInfoProps = {
- dao: any
-}
-
-function DaoInfo({ dao }: DaoInfoProps) {
- const { daoAddress }: any = useParams()
-
- return (
- <>
-
- Info for {daoAddress}
-
-
-
Govern Executor
-
Address
-
{dao.executor.address}
-
Govern Queue
-
Address
-
{dao.queue.address}
-
Config
-
Execution delay: {dao.queue.config.executionDelay}
-
Schedule collateral:
-
- - Token: {dao.queue.config.scheduleDeposit.token}
- - Amount: {dao.queue.config.scheduleDeposit.amount}
-
-
Challenge collateral:
-
- - Token: {dao.queue.config.challengeDeposit.token}
- - Amount: {dao.queue.config.challengeDeposit.amount}
-
-
- >
- )
-}
-
-function Actions({ dao }: DaoInfoProps) {
- const history = useHistory()
- const { daoAddress }: any = useParams()
-
- const handleNewAction = useCallback(() => {
- history.push(`/${daoAddress}/new-action`)
- }, [history, daoAddress])
-
- const hasActions = useMemo(() => dao.queue.queued.length > 0, [dao])
-
- return (
-
-
Actions
- {hasActions
- ? dao.queue.queued.map(({ id }: { id: string }) => (
-
- ))
- : 'No actions.'}
-
-
- )
-}
-
-type PermissionsProps = {
- dao: any
-}
-
-function Permissions({ dao }: PermissionsProps) {
- return (
- <>
-
-
Permissions for Govern
- {dao.executor.roles.map((role: any) => {
- return (
-
-
- {KNOWN_GOVERN_ROLES.get(role.selector)} - {role.selector}
-
-
- Who has permission:{' '}
- {role.who === ANY_ADDRESS ? 'Anyone' : role.who}
-
-
- )
- })}
-
-
-
Permissions for GovernQueue
- {dao.queue.roles.map((role: any) => {
- return (
-
-
- {KNOWN_QUEUE_ROLES.get(role.selector)} - {role.selector}
-
-
- Who has permission:{' '}
- {role.who === ANY_ADDRESS ? 'Anyone' : role.who}
-
-
- )
- })}
-
- >
- )
-}
-
-type ActionCardProps = {
- id: string
-}
-
-function ActionCard({ id }: ActionCardProps) {
- const history = useHistory()
-
- const handleCardClick = useCallback(() => {
- history.push(`/tools/${id}`)
- }, [history, id])
-
- return (
-
- )
-}
diff --git a/packages/govern-console/src/pages/DaoSelector.tsx b/packages/govern-console/src/pages/SelectDao.tsx
similarity index 92%
rename from packages/govern-console/src/pages/DaoSelector.tsx
rename to packages/govern-console/src/pages/SelectDao.tsx
index cf1579e9d..a2cc8456c 100644
--- a/packages/govern-console/src/pages/DaoSelector.tsx
+++ b/packages/govern-console/src/pages/SelectDao.tsx
@@ -48,10 +48,7 @@ export default function DaoSelector() {
`}
/>
-