Skip to content

Commit

Permalink
finance: app state caching, loading indicator, and init (#854)
Browse files Browse the repository at this point in the history
* finance: use updated api to leverage caching

* Add todo about a performance improvement

originates from discssion in aragon/aragon.js#297 (comment)

* Remove old TODO

* Load all token balances on init

* fixup! Load all token balances on init

* Finance - app loading state (#867)

* Use cached state in init and use sync events

* Render syncing state

* Use exported events object from the api

From e027fb419fa62a220034a248bc7c1d1271731519

* Finance: use the SyncIndicator component (#874)

* Finance: use the SyncIndicator component

* Finance: update @aragon/api dependencies

* bump @aragon/api 2.0.0-beta.2

* Upgrade rxjs
  • Loading branch information
2color authored May 29, 2019
1 parent 441b51a commit b07a420
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 40 deletions.
8 changes: 4 additions & 4 deletions apps/finance/app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
"private": true,
"license": "AGPL-3.0-or-later",
"dependencies": {
"@aragon/api": "^1.0.0",
"@aragon/api-react": "^1.0.0-beta.2",
"@aragon/api": "^2.0.0-beta.2",
"@aragon/api-react": "^2.0.0-beta.1",
"@aragon/templates-tokens": "^1.2.0",
"@aragon/ui": "^0.37.0",
"@aragon/ui": "^0.40.0",
"@babel/polyfill": "^7.0.0",
"bn.js": "^4.11.8",
"core-js": "^2.6.5",
Expand All @@ -20,7 +20,7 @@
"react-display-name": "^0.2.3",
"react-dom": "^16.8.4",
"react-spring": "^7.2.8",
"rxjs": "^6.2.1",
"rxjs": "^6.5.2",
"styled-components": "4.1.3",
"web3-utils": "^1.0.0-beta.30"
},
Expand Down
32 changes: 18 additions & 14 deletions apps/finance/app/src/App.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from 'react'
import PropTypes from 'prop-types'
import styled from 'styled-components'
import { EmptyStateCard, Main, SidePanel } from '@aragon/ui'
import { SyncIndicator, EmptyStateCard, Main, SidePanel } from '@aragon/ui'
import { useAragonApi } from '@aragon/api-react'
import Balances from './components/Balances'
import NewTransferPanelContent from './components/NewTransfer/PanelContent'
Expand All @@ -19,6 +19,7 @@ class App extends React.Component {
appState: PropTypes.object,
}
static defaultProps = {
isSyncing: true,
balances: [],
transactions: [],
tokens: [],
Expand Down Expand Up @@ -84,7 +85,7 @@ class App extends React.Component {
}

render() {
const { appState } = this.props
const { appState, isSyncing } = this.props
const { newTransferOpened } = this.state
const { balances, transactions, tokens, proxyAddress } = appState

Expand All @@ -95,6 +96,7 @@ class App extends React.Component {
onResolve={this.handleResolveLocalIdentity}
onShowLocalIdentityModal={this.handleShowLocalIdentityModal}
>
<SyncIndicator visible={isSyncing} />
<AppLayout
title="Finance"
mainButton={{
Expand All @@ -118,17 +120,19 @@ class App extends React.Component {
/>
</SpacedBlock>
)}
{balances.length === 0 && transactions.length === 0 && (
<EmptyScreen>
<EmptyStateCard
icon={<img src={addFundsIcon} alt="" />}
title="There are no funds yet"
text="Create a new transfer to get started."
actionText="New transfer"
onActivate={this.handleNewTransferOpen}
/>
</EmptyScreen>
)}
{!isSyncing &&
balances.length === 0 &&
transactions.length === 0 && (
<EmptyScreen>
<EmptyStateCard
icon={<img src={addFundsIcon} alt="" />}
title="There are no funds yet"
text="Create a new transfer to get started."
actionText="New transfer"
onActivate={this.handleNewTransferOpen}
/>
</EmptyScreen>
)}
</AppLayout>
<SidePanel
opened={newTransferOpened}
Expand Down Expand Up @@ -166,5 +170,5 @@ const SpacedBlock = styled.div`

export default () => {
const { api, appState } = useAragonApi()
return <App api={api} appState={appState} />
return <App api={api} appState={appState} isSyncing={appState.isSyncing} />
}
66 changes: 44 additions & 22 deletions apps/finance/app/src/script.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import Aragon from '@aragon/api'
import Aragon, { events } from '@aragon/api'
import { first } from 'rxjs/operators'
import { of } from 'rxjs'
import { getTestTokenAddresses } from './testnet'
import {
ETHER_TOKEN_FAKE_ADDRESS,
Expand All @@ -24,7 +23,6 @@ const vaultAbi = [].concat(
vaultEventAbi
)

const INITIALIZATION_TRIGGER = Symbol('INITIALIZATION_TRIGGER')
const TEST_TOKEN_ADDRESSES = []
const tokenContracts = new Map() // Addr -> External contract
const tokenDecimals = new Map() // External contract -> decimals
Expand Down Expand Up @@ -92,7 +90,7 @@ async function initialize(vaultAddress, ethAddress) {
tokenNames.set(ETH_CONTRACT, 'Ether')
tokenSymbols.set(ETH_CONTRACT, 'ETH')

return createStore({
const settings = {
network,
ethToken: {
address: ethAddress,
Expand All @@ -101,11 +99,8 @@ async function initialize(vaultAddress, ethAddress) {
address: vaultAddress,
contract: vaultContract,
},
})
}
}

// Hook up the script as an aragon.js store
async function createStore(settings) {
let vaultInitializationBlock

try {
Expand All @@ -124,14 +119,18 @@ async function createStore(settings) {
...state,
}

if (eventName === INITIALIZATION_TRIGGER) {
nextState = await initializeState(nextState, settings)
} else if (addressesEqual(eventAddress, vault.address)) {
if (addressesEqual(eventAddress, vault.address)) {
// Vault event
nextState = await vaultLoadBalance(nextState, event, settings)
} else {
// Finance event
switch (eventName) {
case events.SYNC_STATUS_SYNCING:
nextState.isSyncing = true
break
case events.SYNC_STATUS_SYNCED:
nextState.isSyncing = false
break
case 'ChangePeriodDuration':
nextState.periodDuration = marshallDate(
event.returnValues.newDuration
Expand All @@ -154,12 +153,15 @@ async function createStore(settings) {

return nextState
},
[
// Always initialize the store with our own home-made event
of({ event: INITIALIZATION_TRIGGER }),
// Handle Vault events in case they're not always controlled by this Finance app
settings.vault.contract.events(vaultInitializationBlock),
]
{
init: initializeState(settings),
externals: [
{
contract: settings.vault.contract,
initializationBlock: vaultInitializationBlock,
},
],
}
)
}

Expand All @@ -169,20 +171,40 @@ async function createStore(settings) {
* *
***********************/

async function initializeState(state, settings) {
const nextState = {
...state,
const initializeState = settings => async cachedState => {
const newState = {
...cachedState,
isSyncing: true,
periodDuration: marshallDate(
await app.call('getPeriodDuration').toPromise()
),
vaultAddress: settings.vault.address,
}

const withTestnetState = await loadTestnetState(nextState, settings)
const withTokenBalances = await loadTokenBalances(newState, settings)
const withTestnetState = await loadTestnetState(withTokenBalances, settings)
const withEthBalance = await loadEthBalance(withTestnetState, settings)

return withEthBalance
}

async function loadTokenBalances(state, settings) {
let newState = {
...state,
}
if (!newState.balances) {
return newState
}

const addresses = newState.balances.map(({ address }) => address)
for (const address of addresses) {
newState = {
...newState,
balances: await updateBalances(newState, address, settings),
}
}
return newState
}

async function vaultLoadBalance(state, { returnValues: { token } }, settings) {
return {
...state,
Expand Down

0 comments on commit b07a420

Please sign in to comment.