Skip to content
Permalink
Browse files

Token Manager: use aragonAPI for React (#764)

Only contains the changes needed to support aragonAPI for React: this is not a full conversion to React Hooks.
  • Loading branch information...
bpierre committed Apr 5, 2019
1 parent c1256f0 commit f7a95385f004bf2e68585b4f55b3affea2d685a3
@@ -5,9 +5,10 @@
"license": "AGPL-3.0-or-later",
"dependencies": {
"@aragon/api": "^1.0.0",
"@aragon/api-react": "^1.0.0-beta.2",
"@aragon/ui": "^0.33.0",
"bn.js": "^4.11.6",
"prop-types": "^15.6.0",
"prop-types": "^15.7.2",
"react": "^16.8.4",
"react-dom": "^16.8.4",
"react-spring": "^7.2.10",
@@ -1,15 +1,13 @@
import React from 'react'
import PropTypes from 'prop-types'
import BN from 'bn.js'
import { map } from 'rxjs/operators'
import { Badge, Main, SidePanel, observe } from '@aragon/ui'
import { Badge, Main, SidePanel } from '@aragon/ui'
import { useAragonApi } from '@aragon/api-react'
import EmptyState from './screens/EmptyState'
import Holders from './screens/Holders'
import AssignVotePanelContent from './components/Panels/AssignVotePanelContent'
import AssignTokensIcon from './components/AssignTokensIcon'
import AppLayout from './components/AppLayout'
import { networkContextType } from './provide-network'
import { hasLoadedTokenSettings } from './token-settings'
import { addressesEqual } from './web3-utils'
import { IdentityProvider } from './components/IdentityManager/IdentityManager'

@@ -18,34 +16,20 @@ const initialAssignTokensConfig = {
holderAddress: '',
}

class App extends React.Component {
class App extends React.PureComponent {
static propTypes = {
app: PropTypes.object.isRequired,
sendMessageToWrapper: PropTypes.func.isRequired,
api: PropTypes.object,
}
static defaultProps = {
appStateReady: false,
holders: [],
network: {},
userAccount: '',
connectedAccount: '',
groupMode: false,
}
state = {
assignTokensConfig: initialAssignTokensConfig,
sidepanelOpened: false,
}
static childContextTypes = {
network: networkContextType,
}
getChildContext() {
const { network } = this.props

return {
network: {
type: network.type,
},
}
}
getHolderBalance = address => {
const { holders } = this.props
const holder = holders.find(holder =>
@@ -54,13 +38,13 @@ class App extends React.Component {
return holder ? holder.balance : new BN('0')
}
handleUpdateTokens = ({ amount, holder, mode }) => {
const { app } = this.props
const { api } = this.props

if (mode === 'assign') {
app.mint(holder, amount)
api.mint(holder, amount)
}
if (mode === 'remove') {
app.burn(holder, amount)
api.burn(holder, amount)
}

this.handleSidepanelClose()
@@ -80,9 +64,6 @@ class App extends React.Component {
sidepanelOpened: true,
})
}
handleMenuPanelOpen = () => {
this.props.sendMessageToWrapper('menuPanel', true)
}
handleSidepanelClose = () => {
this.setState({ sidepanelOpened: false })
}
@@ -92,17 +73,16 @@ class App extends React.Component {
}
}
handleResolveLocalIdentity = address => {
return this.props.app.resolveAddressIdentity(address).toPromise()
return this.props.api.resolveAddressIdentity(address).toPromise()
}
handleShowLocalIdentityModal = address => {
return this.props.app
return this.props.api
.requestAddressIdentityModification(address)
.toPromise()
}
render() {
const {
appStateReady,
contentPadding,
groupMode,
holders,
maxAccountTokens,
@@ -113,7 +93,8 @@ class App extends React.Component {
tokenSupply,
tokenSymbol,
tokenTransfersEnabled,
userAccount,
connectedAccount,
requestMenu,
} = this.props
const { assignTokensConfig, sidepanelOpened } = this.state
return (
@@ -126,7 +107,7 @@ class App extends React.Component {
<AppLayout
title="Token Manager"
afterTitle={tokenSymbol && <Badge.App>{tokenSymbol}</Badge.App>}
onMenuOpen={this.handleMenuPanelOpen}
onMenuOpen={requestMenu}
mainButton={{
label: 'Assign tokens',
icon: <AssignTokensIcon />,
@@ -145,7 +126,7 @@ class App extends React.Component {
tokenSupply={tokenSupply}
tokenSymbol={tokenSymbol}
tokenTransfersEnabled={tokenTransfersEnabled}
userAccount={userAccount}
userAccount={connectedAccount}
onAssignTokens={this.handleLaunchAssignTokens}
onRemoveTokens={this.handleLaunchRemoveTokens}
/>
@@ -184,51 +165,14 @@ class App extends React.Component {
}
}

export default observe(
// Convert tokenSupply and holders balances to BNs,
// and calculate tokenDecimalsBase.
observable =>
observable.pipe(
map(state => {
const appStateReady = hasLoadedTokenSettings(state)
if (!appStateReady) {
return {
...state,
appStateReady,
}
}

const {
holders,
maxAccountTokens,
tokenDecimals,
tokenSupply,
tokenTransfersEnabled,
} = state

const tokenDecimalsBase = new BN(10).pow(new BN(tokenDecimals))

return {
...state,
appStateReady,
tokenDecimalsBase,
// Note that numbers in `numData` are not safe for accurate computations
// (but are useful for making divisions easier)
numData: {
tokenDecimals: parseInt(tokenDecimals, 10),
tokenSupply: parseInt(tokenSupply, 10),
},
holders: holders
? holders
.map(holder => ({ ...holder, balance: new BN(holder.balance) }))
.sort((a, b) => b.balance.cmp(a.balance))
: [],
tokenDecimals: new BN(tokenDecimals),
tokenSupply: new BN(tokenSupply),
maxAccountTokens: new BN(maxAccountTokens),
groupMode: tokenTransfersEnabled && maxAccountTokens === '1',
}
})
),
{}
)(App)
export default () => {
const { api, appState, connectedAccount, requestMenu } = useAragonApi()
return (
<App
api={api}
connectedAccount={connectedAccount}
requestMenu={requestMenu}
{...appState}
/>
)
}
@@ -0,0 +1,48 @@
import BN from 'bn.js'
import { hasLoadedTokenSettings } from './token-settings'

// Convert tokenSupply and holders balances to BNs,
// and calculate tokenDecimalsBase.
function appStateReducer(state) {
const appStateReady = hasLoadedTokenSettings(state)
if (!appStateReady) {
return {
...state,
appStateReady,
}
}

const {
holders,
maxAccountTokens,
tokenDecimals,
tokenSupply,
tokenTransfersEnabled,
} = state

const tokenDecimalsBase = new BN(10).pow(new BN(tokenDecimals))

return {
...state,
appStateReady,
tokenDecimalsBase,

// Note that numbers in `numData` are not safe for accurate computations
// (but are useful for making divisions easier)
numData: {
tokenDecimals: parseInt(tokenDecimals, 10),
tokenSupply: parseInt(tokenSupply, 10),
},
holders: holders
? holders
.map(holder => ({ ...holder, balance: new BN(holder.balance) }))
.sort((a, b) => b.balance.cmp(a.balance))
: [],
tokenDecimals: new BN(tokenDecimals),
tokenSupply: new BN(tokenSupply),
maxAccountTokens: new BN(maxAccountTokens),
groupMode: tokenTransfersEnabled && maxAccountTokens === '1',
}
}

export default appStateReducer
@@ -2,6 +2,7 @@ import React from 'react'
import PropTypes from 'prop-types'
import styled from 'styled-components'
import { AppBar, AppView, Button, ButtonIcon, Viewport, font } from '@aragon/ui'
import { useAragonApi } from '@aragon/api-react'
import MenuButton from './MenuButton/MenuButton'

const AppLayout = ({
@@ -10,9 +11,9 @@ const AppLayout = ({
afterTitle,
smallViewPadding,
largeViewPadding,
onMenuOpen,
mainButton,
}) => {
const { requestMenu, displayMenuButton } = useAragonApi()
return (
<Viewport>
{({ below }) => (
@@ -21,18 +22,24 @@ const AppLayout = ({
appBar={
<AppBar>
<AppBarContainer
style={{ padding: below('medium') ? '0' : '0 30px' }}
style={{ padding: below('medium') ? '0' : '0 30px 0 10px' }}
>
<Title>
{below('medium') && <MenuButton onClick={onMenuOpen} />}
<TitleLabel>{title}</TitleLabel>
{displayMenuButton && <MenuButton onClick={requestMenu} />}
<TitleLabel
css={`
margin-left: ${displayMenuButton ? '0' : '20px'};
`}
>
{title}
</TitleLabel>
{afterTitle}
</Title>
{mainButton &&
(below('medium') ? (
<ButtonIcon
onClick={mainButton.onClick}
title={mainButton.label}
label={mainButton.label}
css={`
width: auto;
height: 100%;
@@ -67,7 +74,6 @@ AppLayout.propTypes = {
children: PropTypes.node,
title: PropTypes.node.isRequired,
afterTitle: PropTypes.node,
onMenuOpen: PropTypes.func.isRequired,
smallViewPadding: PropTypes.number,
largeViewPadding: PropTypes.number,
mainButton: PropTypes.shape({
@@ -9,8 +9,8 @@ import {
TableRow,
theme,
} from '@aragon/ui'
import { useNetwork } from '@aragon/api-react'
import LocalIdentityBadge from './LocalIdentityBadge/LocalIdentityBadge'
import provideNetwork from '../provide-network'
import { formatBalance } from '../utils'
import You from './You'

@@ -114,4 +114,7 @@ const IconWrapper = styled.span`
color: ${theme.textSecondary};
`

export default provideNetwork(HolderRow)
export default props => {
const network = useNetwork()
return <HolderRow network={network} {...props} />
}

This file was deleted.

@@ -1,6 +1,5 @@
import React from 'react'
import { ButtonIcon } from '@aragon/ui'
import IconMenu from './IconMenu'
import { ButtonIcon, IconMenu } from '@aragon/ui'

export default props => (
<ButtonIcon
@@ -11,6 +10,7 @@ export default props => (
padding: 0 10px 0 20px;
margin-right: 8px;
`}
label="Open menu"
>
<IconMenu />
</ButtonIcon>
@@ -1,7 +1,7 @@
import React from 'react'
import styled from 'styled-components'
import { Text, breakpoint, theme } from '@aragon/ui'
import provideNetwork from '../provide-network'
import { useNetwork } from '@aragon/api-react'
import { formatBalance, stakesPercentages } from '../utils'
import TokenBadge from './TokenBadge'
import You from './You'
@@ -216,4 +216,7 @@ const StakesListBullet = styled.span`
}
`

export default provideNetwork(SideBar)
export default props => {
const network = useNetwork()
return <SideBar network={network} {...props} />
}

0 comments on commit f7a9538

Please sign in to comment.
You can’t perform that action at this time.