Skip to content

Commit

Permalink
Console: Phase 2 (#192)
Browse files Browse the repository at this point in the history
* chore: minor code tidyup

* feature: see and interact with actions

* Fix types

* Update subgraph endpoint for rinkeby for temp fix, update subgraph query

* console: add ability to interact with existing actions, better error reporting

* Wait for transaction to actually be mined before alert

* Refactor 1: file structure
  • Loading branch information
Evalir authored Nov 9, 2020
1 parent ac8700b commit 3145174
Show file tree
Hide file tree
Showing 22 changed files with 876 additions and 462 deletions.
2 changes: 1 addition & 1 deletion packages/govern-console/.eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ module.exports = {
settings: {
react: {
pragma: 'React',
version: '16.6',
version: '16.13.1',
},
'import/parsers': {
'@typescript-eslint/parser': ['.ts', '.tsx'],
Expand Down
2 changes: 1 addition & 1 deletion packages/govern-console/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
10 changes: 5 additions & 5 deletions packages/govern-console/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
Expand All @@ -19,13 +19,13 @@ function App() {
<Router>
<Switch>
<Route exact path="/">
<DaoSelector />
<SelectDao />
</Route>
<Route exact path="/tools/erc">
<ErcTool />
</Route>
<Route path="/:daoAddress">
<DaoView />
<ViewDao />
</Route>
</Switch>
</Router>
Expand Down
File renamed without changes.
32 changes: 32 additions & 0 deletions packages/govern-console/src/components/Frame/Frame.tsx
Original file line number Diff line number Diff line change
@@ -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 (
<div
css={`
margin-top: 32px;
border: 2px solid rgba(255, 255, 255, 0.2);
padding: 8px;
h2 {
font-weight: bold;
font-size: 24px;
}
h3 {
font-weight: bold;
font-size: 18px;
}
p {
margin-bottom: 16px;
margin-top: 16px;
}
`}
>
{children}
</div>
)
}
32 changes: 32 additions & 0 deletions packages/govern-console/src/components/Info/Info.tsx
Original file line number Diff line number Diff line change
@@ -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 (
<div
css={`
padding: 8px;
margin-top: 32px;
margin-bottom: 32px;
border: 1px solid ${resolveColorsFromStatus(mode)};
`}
>
{children}
</div>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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(
Expand All @@ -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 (
<>
<h2
Expand All @@ -61,25 +85,19 @@ export default function NewAction({
>
New action
</h2>
<div
css={`
padding: 8px;
margin-top: 32px;
border: 2px solid rgba(255, 255, 255, 0.2);
h2 {
font-weight: bold;
font-size: 24px;
}
h3 {
font-weight: bold;
font-size: 18px;
}
p {
margin-bottom: 16px;
margin-top: 16px;
}
`}
>
<Frame>
{executionResult && (
<div
css={`
padding: 8px;
margin-top: 32px;
margin-bottom: 32px;
border: 1px solid ${type};
`}
>
{executionResult}
</div>
)}
<form
css={`
padding: 8px;
Expand Down Expand Up @@ -144,28 +162,22 @@ export default function NewAction({
parsedAbi!.map(
(abiItem: any) =>
abiItem?.type === 'function' && (
<div
key={abiItem.name}
css={`
padding: 8px;
margin-top: 8px;
border: 1px solid whitesmoke;
`}
>
<Frame key={abiItem.name}>
<ContractCallHandler
config={config}
contractAddress={contractAddress}
executor={executorAddress}
handleSetExecutionResult={handleSetExecutionResult}
inputs={abiItem.inputs}
name={abiItem.name}
proof={proof}
queueContract={queueContract}
rawAbiItem={abiItem}
/>
</div>
</Frame>
),
)}
</div>
</Frame>
</>
)
}
Expand All @@ -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
Expand All @@ -185,6 +198,7 @@ function ContractCallHandler({
config,
contractAddress,
executor,
handleSetExecutionResult,
inputs,
name,
proof,
Expand Down Expand Up @@ -238,57 +252,71 @@ 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.`,
)
}
},
[
account,
config,
contractAddress,
executor,
proof,
handleSetExecutionResult,
queueContract,
proof,
rawAbiItem,
values,
],
Expand Down
Loading

0 comments on commit 3145174

Please sign in to comment.