blowfish/src/renderer/store/AppProvider.jsx

151 lines
4.1 KiB
JavaScript

import React, { PureComponent } from 'react'
import PropTypes from 'prop-types'
import ms from 'ms'
// import { ipcRenderer } from 'electron'
import Store from 'electron-store'
import { AppContext } from './createContext'
import { fetchData } from '../../utils'
import { refreshInterval, conversions, oceanTokenContract } from '../../config'
// construct initial prices Map to get consistent
// order for Ticker and Touchbar
let pricesMap = new Map()
pricesMap.set('ocean', 1)
conversions.map(key => pricesMap.set(key, 0))
export default class AppProvider extends PureComponent {
static propTypes = {
children: PropTypes.any.isRequired
}
store = process.env.NODE_ENV === 'test' ? new Store() : global.store
state = {
isLoading: true,
accounts: [],
currency: 'ocean',
needsConfig: false,
prices: pricesMap,
priceChanges: Object.assign(
...conversions.map(key => ({
[key]: 0
}))
),
toggleCurrencies: currency => this.toggleCurrencies(currency),
setBalances: () => this.setBalances(),
accentColor: '#f6388a'
}
async componentDidMount() {
// listener for accent color
global.ipcRenderer.on('accent-color', (event, accentColor) => {
this.setState({ accentColor })
})
// listener for touchbar
global.ipcRenderer.on('setCurrency', (evt, currency) =>
this.state.toggleCurrencies(currency)
)
const newPrizes = await this.fetchAndSetPrices()
this.setState({ prices: newPrizes })
await this.setBalances()
setInterval(this.fetchAndSetPrices, ms(refreshInterval))
setInterval(this.setBalances, ms(refreshInterval))
this.setState({ isLoading: false })
}
getAccounts() {
let accountsPref
if (this.store.has('accounts')) {
accountsPref = this.store.get('accounts')
!accountsPref.length
? this.setState({ needsConfig: true })
: this.setState({ needsConfig: false })
} else {
accountsPref = []
this.setState({ needsConfig: true })
}
return accountsPref
}
async getBalance(account) {
const json = await fetchData(
`https://api.etherscan.io/api?module=account&action=tokenbalance&contractaddress=${oceanTokenContract}&address=${account}&tag=latest`
)
const balance = json.result / 1e18 // Convert from vodka 10^18
return balance
}
fetchAndSetPrices = async () => {
const currencies = conversions.join(',')
const json = await fetchData(
`https://api.coingecko.com/api/v3/simple/price?ids=ocean-protocol&vs_currencies=${currencies}&include_24hr_change=true`
)
let newPrices = new Map(this.state.prices) // make a shallow copy of the Map
conversions.map(key => newPrices.set(key, json['ocean-protocol'][key])) // modify the copy
const newPriceChanges = await Object.assign(
...conversions.map(key => ({
[key]: json['ocean-protocol'][key + '_24h_change']
}))
)
global.ipcRenderer.send('prices-updated', Array.from(newPrices)) // convert Map to array, ipc messages seem to kill it
this.setState({ prices: newPrices, priceChanges: newPriceChanges })
return newPrices
}
setBalances = async () => {
const accountsPref = await this.getAccounts()
let newAccounts = []
for (const account of accountsPref) {
const oceanBalance = await this.getBalance(account)
const conversionsBalance = Object.assign(
...conversions.map(key => ({
[key]: oceanBalance * this.state.prices.get(key) || 0
}))
)
const newAccount = {
address: account,
balance: {
ocean: oceanBalance,
...conversionsBalance
}
}
newAccounts.push(newAccount)
}
if (newAccounts !== this.state.accounts) {
this.setState({ accounts: newAccounts })
}
}
toggleCurrencies(currency) {
const pricesNew = Array.from(this.state.prices)
global.ipcRenderer.send('currency-updated', pricesNew, currency)
this.setState({ currency })
}
render() {
return (
<AppContext.Provider value={this.state}>
{this.props.children}
</AppContext.Provider>
)
}
}