Skip to content

Commit 1c3ef1c

Browse files
delfipolitosohkai
authored andcommitted
Add UI (#4)
1 parent 45ba3fd commit 1c3ef1c

39 files changed

+2742
-183
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
node_modules
33

44
# build artifacts
5+
.cache
56
build
67
dist
78

LICENSE

+1,383
Large diffs are not rendered by default.

app/.babelrc

+2-10
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,8 @@
44
"@babel/preset-env",
55
{
66
"modules": false,
7-
"targets": {
8-
"browsers": [
9-
"> 1%",
10-
"last 3 versions",
11-
"ie >= 9",
12-
"ios >= 8",
13-
"android >= 4.2"
14-
]
15-
},
16-
"useBuiltIns": false
7+
"useBuiltIns": "entry",
8+
"core-js": 3,
179
}
1810
]
1911
],

app/.eslintrc

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"env": {
3+
"browser": true,
4+
"es6": true
5+
},
6+
"extends": [
7+
"standard",
8+
"standard-react",
9+
"plugin:prettier/recommended",
10+
"prettier/react"
11+
],
12+
"parser": "babel-eslint",
13+
"plugins": ["prettier", "react", "react-hooks"],
14+
"rules": {
15+
"valid-jsdoc": "error",
16+
"react/prop-types": 0,
17+
"react-hooks/rules-of-hooks": "error",
18+
"react-hooks/exhaustive-deps": "warn",
19+
"linebreak-style": ["error", "unix"]
20+
}
21+
}

app/.prettierrc

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"singleQuote": true,
3+
"semi": false,
4+
"trailingComma": "es5",
5+
"bracketSpacing": true,
6+
"jsxBracketSameLine": false
7+
}

app/index.html

+14-8
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,16 @@
11
<!DOCTYPE html>
2-
<html>
3-
<head>
4-
<title>Token Wrapper</title>
5-
</head>
6-
<body>
7-
<div id="root"></div>
8-
<script src="src/index.js"></script>
9-
</body>
2+
<html lang="en">
3+
<head>
4+
<meta charset="utf-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
6+
<meta name="theme-color" content="#000000">
7+
<title>Token Wrapper</title>
8+
</head>
9+
<body>
10+
<noscript>
11+
You need to enable JavaScript to run this app.
12+
</noscript>
13+
<div id="root"></div>
14+
<script src="./src/index.js"></script>
15+
</body>
1016
</html>

app/package.json

+35-11
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,56 @@
11
{
22
"name": "token-wrapper-frontend",
33
"version": "1.0.0",
4-
"main": "src/index.js",
4+
"private": true,
55
"dependencies": {
6-
"@aragon/api": "^2.0.0-beta.7",
7-
"@aragon/api-react": "^2.0.0-beta.6",
8-
"@aragon/ui": "^0.40.1",
6+
"@aragon/api": "^2.0.0-beta.8",
7+
"@aragon/api-react": "^2.0.0-beta.8",
8+
"@aragon/ui": "^1.0.0",
99
"core-js": "^3.1.4",
1010
"react": "^16.8.6",
1111
"react-dom": "^16.8.6",
1212
"regenerator-runtime": "^0.13.2",
1313
"rxjs": "^6.5.2",
14-
"styled-components": "^4.3.2"
14+
"styled-components": "^4.3.2",
15+
"web3-utils": "^1.2.0"
1516
},
1617
"devDependencies": {
17-
"@babel/core": "^7.5.4",
18-
"@babel/plugin-proposal-class-properties": "^7.5.0",
19-
"@babel/preset-env": "^7.5.4",
18+
"@babel/core": "^7.0.0",
19+
"@babel/plugin-proposal-class-properties": "^7.0.0",
20+
"@babel/preset-env": "^7.1.0",
21+
"@babel/preset-react": "^7.0.0",
22+
"babel-eslint": "^10.0.1",
23+
"babel-plugin-styled-components": "^1.10.6",
24+
"bn.js": "^5.0.0",
2025
"copyfiles": "^2.1.1",
21-
"parcel-bundler": "^1.12.3"
26+
"eslint": "^5.6.0",
27+
"eslint-config-prettier": "^3.1.0",
28+
"eslint-config-standard": "^12.0.0",
29+
"eslint-config-standard-react": "^7.0.2",
30+
"eslint-plugin-import": "^2.8.0",
31+
"eslint-plugin-node": "^7.0.1",
32+
"eslint-plugin-prettier": "^2.7.0",
33+
"eslint-plugin-promise": "^4.0.1",
34+
"eslint-plugin-react": "^7.5.1",
35+
"eslint-plugin-react-hooks": "^1.6.0",
36+
"eslint-plugin-standard": "^4.0.0",
37+
"parcel-bundler": "^1.10.1",
38+
"prettier": "^1.11.1"
2239
},
2340
"scripts": {
41+
"lint": "eslint ./src",
2442
"build": "npm run sync-assets && npm run build:app && npm run build:script",
2543
"build:app": "parcel build index.html -d ../dist/ --public-url \".\" --no-cache",
2644
"build:script": "parcel build src/script.js --out-dir ../dist/ --no-cache",
2745
"watch:script": "parcel watch src/script.js --out-dir ../dist/ --no-hmr",
2846
"devserver": "parcel serve index.html -p 8001 --out-dir ../dist/ --no-cache",
29-
"start": "npm run sync-assets && npm run build:script -- --no-minify && npm run devserver",
47+
"start": "npm run sync-assets && npm run watch:script & npm run devserver",
3048
"sync-assets": "copy-aragon-ui-assets ../dist && copyfiles './public/**/*' ../dist"
31-
}
49+
},
50+
"browserslist": [
51+
">2%",
52+
"last 1 edge versions",
53+
"not ie > 0",
54+
"not op_mini all"
55+
]
3256
}

app/public/meta/details.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
An application for Aragon that allows locking/unlocking any ERC20 token to mint/burn organization tokens.
1+
An Aragon application that allows any ERC20 token to be converted to and from a MiniMe governance token.
22

33
**Features**
4-
- Lock ERC20 tokens to mint organization tokens.
5-
- Burn organization tokens to unlock ERC20 tokens.
4+
- Deposit ERC20 tokens to mint governance tokens.
5+
- Burn governance tokens to withdraw ERC20 tokens.

app/src/App.js

+134-63
Original file line numberDiff line numberDiff line change
@@ -1,74 +1,145 @@
11
import React from 'react'
22
import { useAragonApi } from '@aragon/api-react'
3-
import { Main, Button } from '@aragon/ui'
4-
import styled from 'styled-components'
5-
import BN from 'bn.js'
3+
import {
4+
Button,
5+
IconPlus,
6+
Header,
7+
Split,
8+
GU,
9+
textStyle,
10+
useLayout,
11+
useTheme,
12+
Tag,
13+
SyncIndicator,
14+
} from '@aragon/ui'
15+
import { AppLogicProvider, useAppLogic } from './app-logic'
16+
import NoWrappedTokens from './screens/NoWrappedTokens'
17+
import Holders from './screens/Holders'
18+
import Panel from './components/ActionsPanel'
19+
import InfoBox from './components/InfoBox'
20+
import { IdentityProvider } from './components/IdentityManager/IdentityManager'
621

722
function App() {
8-
const { api, appState } = useAragonApi()
9-
const {
10-
token,
11-
erc20,
12-
tokenBalance,
13-
erc20Balance,
14-
isSyncing
15-
} = appState
23+
const { appState } = useAragonApi()
24+
const { holders, isSyncing, outsideToken, wrappedToken } = appState
25+
const { actions, wrapTokensPanel, unwrapTokensPanel } = useAppLogic()
26+
const { layoutName } = useLayout()
27+
const theme = useTheme()
1628

17-
// TODO: Read this from an input component
18-
const amount = '10000000'
29+
const appStateReady = outsideToken && wrappedToken
30+
const showHolders = appStateReady && holders && holders.length > 0
1931

2032
return (
21-
<Main>
22-
<BaseLayout>
23-
{isSyncing && <Syncing />}
24-
<Buttons>
25-
<Button mode="secondary" onClick={
26-
async () => {
27-
const app = (await api.currentApp().toPromise()).appAddress
28-
const intentParams = { token: { address: erc20, value: amount, spender: app } }
29-
await api.lock(amount, intentParams).toPromise()
33+
<React.Fragment>
34+
{showHolders && <SyncIndicator visible={isSyncing} />}
35+
<Header
36+
primary={
37+
<div
38+
css={`
39+
display: flex;
40+
align-items: center;
41+
flex: 1 1 auto;
42+
width: 0;
43+
`}
44+
>
45+
<h1
46+
css={`
47+
${textStyle(layoutName === 'small' ? 'title3' : 'title2')};
48+
flex: 0 1 auto;
49+
overflow: hidden;
50+
text-overflow: ellipsis;
51+
white-space: nowrap;
52+
color: ${theme.content};
53+
margin-right: ${1 * GU}px;
54+
`}
55+
>
56+
Token Wrapper
57+
</h1>
58+
<div css="flex-shrink: 0">
59+
{wrappedToken && wrappedToken.symbol && (
60+
<Tag mode="identifier">{wrappedToken.symbol}</Tag>
61+
)}
62+
</div>
63+
</div>
64+
}
65+
secondary={
66+
showHolders && (
67+
<Button
68+
mode="strong"
69+
label="Wrap tokens"
70+
icon={<IconPlus />}
71+
onClick={wrapTokensPanel.requestOpen}
72+
display={layoutName === 'small' ? 'icon' : 'label'}
73+
/>
74+
)
75+
}
76+
/>
77+
<Split
78+
primary={
79+
showHolders ? (
80+
<Holders
81+
holders={holders}
82+
onUnwrapTokens={unwrapTokensPanel.requestOpen}
83+
wrappedToken={wrappedToken}
84+
/>
85+
) : (
86+
<NoWrappedTokens
87+
isSyncing={isSyncing}
88+
onWrapTokens={wrapTokensPanel.requestOpen}
89+
/>
90+
)
91+
}
92+
secondary={
93+
appStateReady && (
94+
<InfoBox outsideToken={outsideToken} wrappedToken={wrappedToken} />
95+
)
96+
}
97+
/>
98+
99+
{appStateReady && (
100+
<React.Fragment>
101+
<Panel
102+
panelState={wrapTokensPanel}
103+
onAction={actions.wrapTokens}
104+
outsideToken={outsideToken}
105+
wrappedToken={wrappedToken}
106+
action="Wrap"
107+
info={
108+
<React.Fragment>
109+
<p>
110+
Wrap {outsideToken.symbol} into an ERC20-compliant token used
111+
for governance within this organization.
112+
</p>
113+
<p
114+
css={`
115+
margin-top: ${1 * GU}px;
116+
`}
117+
>
118+
1 {outsideToken.symbol} = 1 {wrappedToken.symbol}.
119+
</p>
120+
</React.Fragment>
30121
}
31-
}>
32-
Lock tokens
33-
</Button>
34-
<Button mode="secondary" onClick={
35-
async () => await api.unlock(amount).toPromise()
36-
}>
37-
Unlock tokens
38-
</Button>
39-
</Buttons>
40-
<div>
41-
<Count>Org token: {token} balance: {tokenBalance}</Count>
42-
<Count>Wrapped token: {erc20} balance: {erc20Balance}</Count>
43-
</div>
44-
</BaseLayout>
45-
</Main>
122+
/>
123+
<Panel
124+
panelState={unwrapTokensPanel}
125+
onAction={actions.unwrapTokens}
126+
outsideToken={outsideToken}
127+
wrappedToken={wrappedToken}
128+
action="Unwrap"
129+
info={`Recover your ${outsideToken.symbol} by unwrapping your ${wrappedToken.symbol}.`}
130+
/>
131+
</React.Fragment>
132+
)}
133+
</React.Fragment>
46134
)
47135
}
48136

49-
const BaseLayout = styled.div`
50-
display: flex;
51-
align-items: center;
52-
justify-content: center;
53-
height: 100vh;
54-
flex-direction: column;
55-
`
56-
57-
const Count = styled.h1`
58-
font-size: 30px;
59-
`
60-
61-
const Buttons = styled.div`
62-
display: grid;
63-
grid-auto-flow: column;
64-
grid-gap: 40px;
65-
margin-top: 20px;
66-
`
67-
68-
const Syncing = styled.div.attrs({ children: 'Syncing…' })`
69-
position: absolute;
70-
top: 15px;
71-
right: 20px;
72-
`
73-
74-
export default App
137+
export default function TokenWrapper() {
138+
return (
139+
<AppLogicProvider>
140+
<IdentityProvider>
141+
<App />
142+
</IdentityProvider>
143+
</AppLogicProvider>
144+
)
145+
}

app/src/abi/token-decimals.json

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
[
2+
{
3+
"constant": true,
4+
"inputs": [],
5+
"name": "decimals",
6+
"outputs": [
7+
{
8+
"name": "",
9+
"type": "uint8"
10+
}
11+
],
12+
"payable": false,
13+
"stateMutability": "view",
14+
"type": "function"
15+
}
16+
]

0 commit comments

Comments
 (0)