switch currencies, balance component

This commit is contained in:
Matthias Kretschmann 2019-05-06 00:10:28 +02:00
parent a296148f5b
commit 8f42243539
Signed by: m
GPG Key ID: 606EEEF3C479A91F
13 changed files with 187 additions and 113 deletions

View File

@ -1,24 +1,26 @@
# ocean-balance
> Simple Electron-based desktop app to retrieve and display your total Ocean balances.
> Simple Electron-based desktop app to retrieve and display your total Ocean Token balances.
> https://oceanprotocol.com
## Usage
Clone and run:
Clone, add adresses, and run:
```bash
# Clone this repository
git clone git@github.com:kremalicious/ocean-balance.git
cd ocean-balance
# Add one or more Ethereum addresses to config file
vi config.js
# Install dependencies
npm install
# Run the app in dev mode
npm start
```
## Configuration
## Build package
```bash

View File

@ -55,11 +55,25 @@ html.fullscreen {
transform: translate3d(0, -36px, 0);
}
.main {
width: 100%;
padding: 5%;
background: #303030;
border-radius: 5px;
border: .1rem solid #41474e;
min-height: 186px;
display: flex;
align-items: center;
flex-wrap: wrap;
position: relative;
}
.number-unit-wrap {
display: flex;
width: 100%;
flex-wrap: wrap;
justify-content: space-around;
position: relative;
}
.number-unit {
@ -92,6 +106,20 @@ html.fullscreen {
font-size: .85rem;
display: block;
white-space: nowrap;
margin-top: .3rem;
}
.number-unit-wrap--accounts {
min-height: 55px;
}
.number-unit--main {
padding-bottom: 5%;
border-bottom: 1px solid #41474e;
}
.number-unit--main .number {
font-size: 2.5rem;
}
@keyframes updated {

View File

@ -1,9 +1,12 @@
import './App.css'
import React, { PureComponent } from 'react'
import { webFrame } from 'electron'
import AppProvider from './store/AppProvider'
import { Consumer } from './store/createContext'
import Titlebar from './components/Titlebar'
import Accounts from './components/Accounts'
import Total from './components/Total'
import Account from './components/Account'
import Actions from './components/Actions'
import './App.css'
//
// Disable zooming
@ -11,17 +14,28 @@ import Accounts from './components/Accounts'
webFrame.setVisualZoomLevelLimits(1, 1)
webFrame.setLayoutZoomLevelLimits(0, 0)
class App extends PureComponent {
export default class App extends PureComponent {
render() {
return (
<AppProvider>
<Titlebar />
<div className="app__content">
<Accounts />
<main className="main">
<Actions />
<Total />
<div className="number-unit-wrap number-unit-wrap--accounts">
<Consumer>
{({ accounts }) =>
accounts.map((account, i) => (
<Account key={i} account={account} />
))
}
</Consumer>
</div>
</main>
</div>
</AppProvider>
)
}
}
export default App

View File

@ -1,33 +1,27 @@
import React, { PureComponent } from 'react'
import PropTypes from 'prop-types'
import { fiatFormatter, numberFormatter } from '../util/moneyFormatter'
import Balance from './Balance'
class Account extends PureComponent {
export default class Account extends PureComponent {
static propTypes = {
isNativeShown: PropTypes.bool.isRequired,
account: PropTypes.shape({
address: PropTypes.string.isRequired,
balance: PropTypes.shape({
ocean: PropTypes.number.isRequired,
eur: PropTypes.number.isRequired
eur: PropTypes.number.isRequired,
usd: PropTypes.number.isRequired
}).isRequired
})
}
render() {
const { balance, address } = this.props.account
const { ocean, eur } = balance
const { account } = this.props
const { balance, address } = account
return (
<div className="number-unit">
<h1 className="number">
{this.props.isNativeShown ? (
<span className="balance-native">{fiatFormatter('EUR', eur)}</span>
) : (
<span className="balance" title={numberFormatter(ocean)}>
{numberFormatter(ocean) || 0} Ọ
</span>
)}
<Balance balance={balance} />
</h1>
<span className="label" title={address}>
{address.substring(0, 12)}...
@ -36,5 +30,3 @@ class Account extends PureComponent {
)
}
}
export default Account

View File

@ -1,29 +0,0 @@
.main {
width: 100%;
padding: 5%;
background: #303030;
border-radius: 5px;
border: .1rem solid #41474e;
min-height: 186px;
display: flex;
align-items: center;
flex-wrap: wrap;
position: relative;
}
.number-unit-wrap--accounts {
min-height: 55px;
}
.number-unit--main {
padding-bottom: 5%;
border-bottom: 1px solid #41474e;
}
.number-unit--main .number {
font-size: 2.5rem;
}
.number-unit--main .label {
font-size: .95rem;
}

View File

@ -1,40 +0,0 @@
import React, { PureComponent } from 'react'
import { Consumer } from '../store/createContext'
import Total from './Total'
import Account from './Account'
import './Accounts.css'
export default class Accounts extends PureComponent {
state = {
isNativeShown: false
}
toggleBalances = () => {
this.setState({ isNativeShown: !this.state.isNativeShown })
}
render() {
return (
<main className="main">
<Total />
<div
className="number-unit-wrap number-unit-wrap--accounts"
onClick={this.toggleBalances}
>
<Consumer>
{({ accounts }) =>
accounts.map((account, i) => (
<Account
key={i}
account={account}
isNativeShown={this.state.isNativeShown}
/>
))
}
</Consumer>
</div>
</main>
)
}
}

View File

@ -0,0 +1,17 @@
.actions {
width: 100%;
text-align: right;
position: absolute;
top: -2rem;
right: 0;
}
button {
background: none;
border: 0;
box-shadow: none;
margin: 0;
outline: 0;
color: #f6388a;
font-size: .85rem;
}

View File

@ -0,0 +1,21 @@
import React, { PureComponent } from 'react'
import { Consumer } from '../store/createContext'
import './Actions.css'
export default class Actions extends PureComponent {
render() {
return (
<div className="actions">
<Consumer>
{({ toggleCurrencies }) => (
<>
<button onClick={() => toggleCurrencies('ocean')}>OCEAN</button>
<button onClick={() => toggleCurrencies('eur')}>EUR</button>
<button onClick={() => toggleCurrencies('usd')}>USD</button>
</>
)}
</Consumer>
</div>
)
}
}

View File

@ -0,0 +1,34 @@
import React from 'react'
import PropTypes from 'prop-types'
import { Consumer } from '../store/createContext'
import { numberFormatter, fiatFormatter } from '../util/moneyFormatter'
const Balance = ({ balance }) => {
const { ocean, eur, usd } = balance
return (
<Consumer>
{({ currency }) =>
currency === 'ocean' ? (
<span className="balance" title={numberFormatter(ocean)}>
Ọ {numberFormatter(ocean) || 0}
</span>
) : currency === 'eur' ? (
<span className="balance">{fiatFormatter('EUR', eur)}</span>
) : (
<span className="balance">{fiatFormatter('USD', usd)}</span>
)
}
</Consumer>
)
}
Balance.propTypes = {
balance: PropTypes.shape({
ocean: PropTypes.number.isRequired,
eur: PropTypes.number.isRequired,
usd: PropTypes.number.isRequired
})
}
export default Balance

View File

@ -1,12 +1,12 @@
import React from 'react'
import { Consumer } from '../store/createContext'
import { numberFormatter } from '../util/moneyFormatter'
import Balance from './Balance'
const calculateTotalBalance = accounts => {
const calculateTotalBalance = (accounts, currency) => {
const balanceTotalArray = []
for (const account of accounts) {
balanceTotalArray.push(account.balance.ocean)
balanceTotalArray.push(account.balance[currency])
}
// Convert array to numbers and add numbers together
@ -15,15 +15,28 @@ const calculateTotalBalance = accounts => {
0
)
return numberFormatter(balanceTotal)
return balanceTotal
}
const Total = () => (
<div className="number-unit number-unit--main">
<Consumer>
{({ accounts }) => {
const total = calculateTotalBalance(accounts)
return <h1 className="number">{total || 0} Ọ</h1>
const totalOcean = calculateTotalBalance(accounts, 'ocean')
const totalEur = calculateTotalBalance(accounts, 'eur')
const totalUsd = calculateTotalBalance(accounts, 'usd')
const balance = {
ocean: totalOcean,
eur: totalEur,
usd: totalUsd
}
return (
<h1 className="number">
<Balance balance={balance} />
</h1>
)
}}
</Consumer>
<span className="label">Total balance</span>

View File

@ -2,7 +2,7 @@ import React, { PureComponent } from 'react'
import PropTypes from 'prop-types'
import ms from 'ms'
import { Provider } from './createContext'
import { accounts, refreshInterval, oceanTokenContract } from '../../constants'
import { accounts, refreshInterval, oceanTokenContract } from '../../config'
export default class AppProvider extends PureComponent {
static propTypes = {
@ -10,7 +10,9 @@ export default class AppProvider extends PureComponent {
}
state = {
accounts: []
accounts: [],
currency: 'ocean',
toggleCurrencies: currency => this.setState({ currency })
}
componentDidMount() {
@ -26,11 +28,9 @@ export default class AppProvider extends PureComponent {
this.setState({ accounts: [] })
}
fetchBalance = async account => {
async fetch(url) {
try {
const response = await fetch(
`https://api.etherscan.io/api?module=account&action=tokenbalance&contractaddress=${oceanTokenContract}&address=${account}`
)
const response = await fetch(url)
if (response.status !== 200) {
return console.log('Non-200 response: ' + response.status) // eslint-disable-line
@ -39,16 +39,37 @@ export default class AppProvider extends PureComponent {
const json = await response.json()
if (!json) return
const balance = (json.result /= 1000000000000000000) // Convert from wei 10^18
return balance
return json
} catch (error) {
console.log('Error parsing etherscan.io json:' + error) // eslint-disable-line
console.log('Error parsing json:' + error) // eslint-disable-line
}
}
setBalances = () => {
fetchBalance = async account => {
const json = await this.fetch(
`https://api.etherscan.io/api?module=account&action=tokenbalance&contractaddress=${oceanTokenContract}&address=${account}&tag=latest`
)
const balance = (json.result /= 1000000000000000000) // Convert from wei 10^18
return balance
}
fetchPrice = async () => {
const json = await this.fetch(
'https://api.coingecko.com/api/v3/simple/price?ids=ocean-protocol&vs_currencies=usd,eur'
)
const { usd, eur } = json['ocean-protocol']
return { usd, eur }
}
setBalances = async () => {
// TODO: make this less lazy and update numbers in place
// when they are changed instead of resetting all to 0 here
this.clearAccounts()
const { usd, eur } = await this.fetchPrice()
accounts.map(async account => {
const oceanBalance = await this.fetchBalance(account)
@ -56,7 +77,8 @@ export default class AppProvider extends PureComponent {
address: account,
balance: {
ocean: oceanBalance || 0,
eur: 0
eur: oceanBalance / eur || 0,
usd: oceanBalance / usd || 0
}
}

View File

@ -4,14 +4,14 @@ const locale = navigator.language
const numberFormatter = number =>
new Intl.NumberFormat(locale, {
minimumFractionDigits: 0,
maximumFractionDigits: 2
maximumFractionDigits: 4
}).format(number)
const fiatFormatter = (currency, number) =>
new Intl.NumberFormat(locale, {
style: 'currency',
currency,
minimumFractionDigits: 0,
minimumFractionDigits: 2,
maximumFractionDigits: 2
}).format(number)