Browse Source

Merge pull request #306 from gre/migrate-live-common

Integrate live-common library
master
Gaëtan Renaudeau 7 years ago
committed by GitHub
parent
commit
64087c87f6
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 6
      .circleci/config.yml
  2. 1
      .eslintrc
  3. 4
      README.md
  4. 14
      package.json
  5. 2
      scripts/postinstall.sh
  6. 2
      src/actions/accounts.js
  7. 36
      src/actions/counterValues.js
  8. 9
      src/components/AccountPage/AccountHeader.js
  9. 15
      src/components/AccountPage/index.js
  10. 2
      src/components/BalanceSummary/BalanceInfos.js
  11. 6
      src/components/BalanceSummary/index.js
  12. 2
      src/components/CalculateBalance.js
  13. 36
      src/components/CounterValue/index.js
  14. 4
      src/components/CounterValue/stories.js
  15. 19
      src/components/CryptoCurrencyIcon.js
  16. 17
      src/components/DashboardPage/AccountCard.js
  17. 15
      src/components/DashboardPage/index.js
  18. 2
      src/components/DeviceCheckAddress.js
  19. 15
      src/components/DeviceConnect/index.js
  20. 2
      src/components/DeviceMonit/index.js
  21. 14
      src/components/DeviceMonitNew/index.js
  22. 2
      src/components/IsUnlocked.js
  23. 6
      src/components/OperationsList/Operation.js
  24. 4
      src/components/OperationsList/index.js
  25. 2
      src/components/OperationsList/stories.js
  26. 2
      src/components/QRCodeExporter.js
  27. 2
      src/components/ReceiveBox.js
  28. 19
      src/components/RequestAmount/index.js
  29. 6
      src/components/SelectAccount/index.js
  30. 26
      src/components/SelectAccount/stories.js
  31. 28
      src/components/SelectCurrency/index.js
  32. 18
      src/components/SettingsPage/sections/Currencies.js
  33. 7
      src/components/SettingsPage/sections/Display.js
  34. 6
      src/components/SideBar/index.js
  35. 2
      src/components/base/Chart/Tooltip.js
  36. 2
      src/components/base/Chart/index.js
  37. 2
      src/components/base/Chart/refreshDraw.js
  38. 4
      src/components/base/Chart/stories.js
  39. 7
      src/components/base/FlipTicker/stories.js
  40. 4
      src/components/base/FormattedVal/__tests__/FormattedVal.test.js
  41. 16
      src/components/base/FormattedVal/index.js
  42. 4
      src/components/base/InputCurrency/index.js
  43. 5
      src/components/base/InputCurrency/stories.js
  44. 2
      src/components/base/InputPassword/index.js
  45. 4
      src/components/base/Modal/ConfirmModal.js
  46. 26
      src/components/modals/AddAccount/01-step-currency.js
  47. 10
      src/components/modals/AddAccount/03-step-import.js
  48. 18
      src/components/modals/AddAccount/index.js
  49. 2
      src/components/modals/OperationDetails.js
  50. 2
      src/components/modals/Receive/01-step-account.js
  51. 2
      src/components/modals/Receive/03-step-confirm-address.js
  52. 2
      src/components/modals/Receive/04-step-receive-funds.js
  53. 2
      src/components/modals/Receive/index.js
  54. 2
      src/components/modals/Send/01-step-amount.js
  55. 2
      src/components/modals/Send/03-step-verification.js
  56. 2
      src/components/modals/Send/Footer.js
  57. 2
      src/components/modals/Send/index.js
  58. 2
      src/components/modals/SettingsAccount.js
  59. 17
      src/components/modals/StepConnectDevice.js
  60. 137
      src/helpers/__tests__/balance.test.js
  61. 5
      src/helpers/balance.js
  62. 19
      src/helpers/btc.js
  63. 1
      src/helpers/db.js
  64. 29
      src/internals/usb/wallet/accounts.js
  65. 24
      src/internals/usb/wallet/index.js
  66. 2
      src/main/counterValuesSync.js
  67. 30
      src/reducers/accounts.js
  68. 4
      src/reducers/counterValues.js
  69. 48
      src/reducers/settings.js
  70. 11
      src/renderer/events.js
  71. 2
      src/renderer/init.js
  72. 16
      src/stories/currencies.stories.js
  73. 2
      src/types/common.js
  74. 18
      yarn.lock

6
.circleci/config.yml

@ -15,12 +15,6 @@ jobs:
- run:
name: Dependencies
command: yarn
- run:
name: Flow typed
command: yarn flow-typed
- run:
name: Temporary remove broken flow definitions
command: rm flow-typed/npm/{react-i18next_v7.x.x.js,react-redux_v5.x.x.js,styled-components_v3.x.x.js}
- run:
name: Lint
command: yarn lint

1
.eslintrc

@ -51,6 +51,7 @@
"react/jsx-filename-extension": 0,
"react/jsx-no-target-blank": 0,
"react/prefer-stateless-function": 0,
"react/require-default-props": 0,
},
"settings": {
"import/resolver": {

4
README.md

@ -16,11 +16,7 @@ Project has been tested under [NodeJS](https://nodejs.org) v9.3.0, with [Yarn](h
1. Install dependencies
```bash
# app dependencies
yarn
# npm packages flow definitions
yarn flow-typed
```
2. Create `.env` file

14
package.json

@ -12,10 +12,8 @@
"dist": "yarn compile && electron-builder",
"test": "jest",
"flow": "flow",
"flow-typed": "flow-typed install -s --overwrite",
"lint": "eslint src webpack .storybook",
"postinstall": "bash ./scripts/postinstall.sh",
"precommit": "lint-staged",
"prettier": "prettier --write \"{src,webpack,.storybook}/**/*.js\"",
"publish-storybook": "bash ./scripts/publish-storybook.sh",
"release": "build",
@ -23,13 +21,6 @@
"storybook": "NODE_ENV=development STORYBOOK_ENV=1 start-storybook -s ./static -p 4444",
"trans": "node scripts/trans"
},
"lint-staged": {
"*.js": [
"eslint --fix",
"prettier --write",
"git add"
]
},
"electronWebpack": {
"title": true,
"renderer": {
@ -44,12 +35,11 @@
"webpack-sources": "1.0.1"
},
"dependencies": {
"@ledgerhq/currencies": "^4.10.1",
"@ledgerhq/hw-app-btc": "^4.7.3",
"@ledgerhq/hw-app-eth": "^4.7.3",
"@ledgerhq/hw-transport": "^4.7.3",
"@ledgerhq/hw-transport-node-hid": "^4.7.6",
"@ledgerhq/wallet-common": "^1.2.0",
"@ledgerhq/live-common": "^2.0.0-rc4",
"axios": "^0.18.0",
"babel-runtime": "^6.26.0",
"bcryptjs": "^2.4.3",
@ -89,6 +79,7 @@
"redux": "^4.0.0",
"redux-actions": "^2.3.0",
"redux-thunk": "^2.2.0",
"reselect": "^3.0.1",
"smooth-scrollbar": "^8.2.7",
"source-map": "0.7.2",
"source-map-support": "^0.5.4",
@ -140,7 +131,6 @@
"husky": "^0.14.3",
"jest": "^22.4.3",
"js-yaml": "^3.10.0",
"lint-staged": "^7.0.4",
"node-loader": "^0.6.0",
"prettier": "^1.12.1",
"react-hot-loader": "^4.1.0",

2
scripts/postinstall.sh

@ -1,3 +1,5 @@
#/bin/bash
flow-typed install -s --overwrite
rm flow-typed/npm/{react-i18next_v7.x.x.js,react-redux_v5.x.x.js,styled-components_v3.x.x.js}
electron-builder install-app-deps

2
src/actions/accounts.js

@ -1,7 +1,7 @@
// @flow
import sortBy from 'lodash/sortBy'
import type { Account } from '@ledgerhq/wallet-common/lib/types'
import type { Account } from '@ledgerhq/live-common/lib/types'
import db from 'helpers/db'

36
src/actions/counterValues.js

@ -1,12 +1,13 @@
// @flow
import { getFiatUnit } from '@ledgerhq/currencies'
import { fetchHistodayRates } from '@ledgerhq/wallet-common/lib/api/countervalue'
import type { Currency } from '@ledgerhq/currencies'
import type { Dispatch } from 'redux'
import { fetchHistodayRates } from '@ledgerhq/live-common/lib/api/countervalue'
import type { CryptoCurrency, Currency } from '@ledgerhq/live-common/lib/types'
import { counterValueCurrencySelector } from 'reducers/settings'
import { currenciesSelector } from 'reducers/accounts'
import db from 'helpers/db'
import type { State } from 'reducers'
export type InitCounterValues = () => { type: string, payload: Object }
export const initCounterValues: InitCounterValues = () => ({
@ -20,18 +21,23 @@ export const updateCounterValues: UpdateCounterValues = payload => ({
payload,
})
export type FetchCounterValues = (?(Currency[])) => (Dispatch<*>, Function) => Promise<any>
export const fetchCounterValues: FetchCounterValues = (currencies: ?(Currency[])) => async (
dispatch,
getState,
) => {
const { accounts, settings } = getState()
if (!currencies) {
currencies = accounts.map(a => a.currency)
function cryptoCurrenciesToCurrencies(currencies: CryptoCurrency[]): Currency[] {
// $FlowFixMe this function is just to fix flow types. array contravariant issue.
return currencies
}
const { counterValue } = settings
const fiatUnit = getFiatUnit(counterValue)
const counterValues = await fetchHistodayRates(currencies, fiatUnit)
export type FetchCounterValues = (
currencies?: Currency[],
) => (Dispatch<*>, () => State) => Promise<any>
export const fetchCounterValues: FetchCounterValues = currencies => async (dispatch, getState) => {
const state = getState()
const currency = counterValueCurrencySelector(state)
if (!currency) return
if (!currencies) {
// TODO this should be default, there is no need to provide the currencies in parameter
currencies = cryptoCurrenciesToCurrencies(currenciesSelector(state))
}
const counterValues = await fetchHistodayRates(currencies, currency)
dispatch(updateCounterValues(counterValues))
}

9
src/components/AccountPage/AccountHeader.js

@ -1,13 +1,13 @@
// @flow
import React, { PureComponent } from 'react'
import { getIconByCoinType } from '@ledgerhq/currencies/react'
import styled from 'styled-components'
import type { Account } from '@ledgerhq/wallet-common/lib/types'
import type { Account } from '@ledgerhq/live-common/lib/types'
import Box from 'components/base/Box'
import Text from 'components/base/Text'
import CryptoCurrencyIcon from '../CryptoCurrencyIcon'
const CurName = styled(Text).attrs({
ff: 'Open Sans|SemiBold',
@ -32,14 +32,11 @@ type Props = {
class AccountHeader extends PureComponent<Props> {
render() {
const { account } = this.props
const Icon = getIconByCoinType(account.currency.coinType)
return (
<Box horizontal align="center" flow={2}>
{Icon && (
<Box color={account.currency.color}>
<Icon size={24} />
<CryptoCurrencyIcon currency={account.currency} size={24} />
</Box>
)}
<Box>
<CurName>{account.currency.name}</CurName>
<AccountName>{account.name}</AccountName>

15
src/components/AccountPage/index.js

@ -7,9 +7,12 @@ import { connect } from 'react-redux'
import { translate } from 'react-i18next'
import { Redirect } from 'react-router'
import styled from 'styled-components'
import { formatCurrencyUnit, getFiatUnit } from '@ledgerhq/currencies'
import {
formatCurrencyUnit,
getFiatCurrencyByTicker,
} from '@ledgerhq/live-common/lib/helpers/currencies'
import type { Account } from '@ledgerhq/wallet-common/lib/types'
import type { Account } from '@ledgerhq/live-common/lib/types'
import { MODAL_SEND, MODAL_RECEIVE, MODAL_SETTINGS_ACCOUNT } from 'config/constants'
@ -95,9 +98,13 @@ class AccountPage extends PureComponent<Props, State> {
currency: formatCurrencyUnit(account.unit, account.balance, {
showCode: true,
}),
counterValue: formatCurrencyUnit(getFiatUnit(counterValue), data.totalBalance, {
counterValue: formatCurrencyUnit(
getFiatCurrencyByTicker(counterValue).units[0],
data.totalBalance,
{
showCode: true,
}),
},
),
},
})
}

2
src/components/BalanceSummary/BalanceInfos.js

@ -3,7 +3,7 @@
import React from 'react'
import styled from 'styled-components'
import type { Unit } from '@ledgerhq/currencies'
import type { Unit } from '@ledgerhq/live-common/lib/types'
import type { T } from 'types/common'
import Box from 'components/base/Box'

6
src/components/BalanceSummary/index.js

@ -1,8 +1,8 @@
// @flow
import React, { Fragment } from 'react'
import type { Account } from '@ledgerhq/wallet-common/lib/types'
import { getFiatUnit } from '@ledgerhq/currencies'
import type { Account } from '@ledgerhq/live-common/lib/types'
import { getFiatCurrencyByTicker } from '@ledgerhq/live-common/lib/helpers/currencies'
import Chart from 'components/base/Chart'
import Box, { Card } from 'components/base/Box'
@ -30,7 +30,7 @@ const BalanceSummary = ({
renderHeader,
selectedTime,
}: Props) => {
const unit = getFiatUnit(counterValue)
const unit = getFiatCurrencyByTicker(counterValue).units[0]
return (
<Card p={0} py={6}>
<CalculateBalance

2
src/components/CalculateBalance.js

@ -5,7 +5,7 @@ import { connect } from 'react-redux'
import noop from 'lodash/noop'
import type { Account } from '@ledgerhq/wallet-common/lib/types'
import type { Account } from '@ledgerhq/live-common/lib/types'
import calculateBalance from 'helpers/balance'

36
src/components/CounterValue/index.js

@ -2,9 +2,9 @@
import React, { PureComponent } from 'react'
import { connect } from 'react-redux'
import { getFiatUnit } from '@ledgerhq/currencies'
import type { CryptoCurrency } from '@ledgerhq/live-common/lib/types'
import { getCounterValueCode } from 'reducers/settings'
import { counterValueCurrencySelector } from 'reducers/settings'
import { calculateCounterValueSelector } from 'reducers/counterValues'
import FormattedVal from 'components/base/FormattedVal'
@ -13,19 +13,16 @@ type Props = {
// wich market to query
ticker: string,
// the value :)
value: number,
// when? if not given: take latest
date?: Date,
// from reducers
counterValueCode: string,
getCounterValue: Function,
counterValueCurrency: CryptoCurrency,
value: number,
}
const mapStateToProps = (state, props) => {
const { ticker } = props
const { ticker, value, date } = props
// TODO: in wallet-common, stop using currency.
// always use ticker and remove that hack
@ -36,13 +33,15 @@ const mapStateToProps = (state, props) => {
console.warn('`currency` is deprecated in CounterValue. use `ticker` instead.') // eslint-disable-line no-console
}
const counterValueCode = getCounterValueCode(state)
const counterValueUnit = getFiatUnit(counterValueCode)
const getCounterValue = calculateCounterValueSelector(state)(currency, counterValueUnit)
const counterValueCurrency = counterValueCurrencySelector(state)
const counterValue =
!counterValueCurrency || !currency
? 0
: calculateCounterValueSelector(state)(currency, counterValueCurrency)(value, date)
return {
counterValueCode,
getCounterValue,
counterValueCurrency,
value: counterValue,
}
}
@ -53,10 +52,15 @@ class CounterValue extends PureComponent<Props> {
}
render() {
const { getCounterValue, counterValueCode, date, value, ...props } = this.props
const counterValue = getCounterValue(value, date)
const { value, counterValueCurrency, date, ...props } = this.props
return (
<FormattedVal val={counterValue} fiat={counterValueCode} showCode alwaysShowSign {...props} />
<FormattedVal
val={value}
fiat={counterValueCurrency.units[0].code}
showCode
alwaysShowSign
{...props}
/>
)
}
}

4
src/components/CounterValue/stories.js

@ -1,7 +1,7 @@
// @flow
import React from 'react'
import { getCurrencyByCoinType } from '@ledgerhq/currencies'
import { getCryptoCurrencyById } from '@ledgerhq/live-common/lib/helpers/currencies'
import { storiesOf } from '@storybook/react'
import { number } from '@storybook/addon-knobs'
@ -9,7 +9,7 @@ import CounterValue from 'components/CounterValue'
const stories = storiesOf('Components', module)
const currency = getCurrencyByCoinType(0)
const currency = getCryptoCurrencyById('bitcoin')
stories.add('CounterValue', () => (
<CounterValue ticker={currency.units[0].code} value={Number(number('value', 100000000) || 0)} />

19
src/components/CryptoCurrencyIcon.js

@ -0,0 +1,19 @@
// @flow
import React, { PureComponent } from 'react'
import { getCryptoCurrencyIcon } from '@ledgerhq/live-common/lib/react'
import type { CryptoCurrency } from '@ledgerhq/live-common/lib/types'
type Props = {
currency: CryptoCurrency,
size: number,
}
class CryptoCurrencyIcon extends PureComponent<Props> {
render() {
const { currency, size } = this.props
const IconCurrency = getCryptoCurrencyIcon(currency)
return IconCurrency ? <IconCurrency size={size} /> : null
}
}
export default CryptoCurrencyIcon

17
src/components/DashboardPage/AccountCard.js

@ -2,15 +2,15 @@
import React from 'react'
import styled from 'styled-components'
import { getIconByCoinType } from '@ledgerhq/currencies/react'
import type { Account } from '@ledgerhq/wallet-common/lib/types'
import type { Account } from '@ledgerhq/live-common/lib/types'
import Chart from 'components/base/Chart'
import Bar from 'components/base/Bar'
import Box, { Card } from 'components/base/Box'
import CalculateBalance from 'components/CalculateBalance'
import FormattedVal from 'components/base/FormattedVal'
import CryptoCurrencyIcon from 'components/CryptoCurrencyIcon'
const Wrapper = styled(Card).attrs({
p: 4,
@ -30,18 +30,12 @@ const AccountCard = ({
account: Account,
onClick?: Function,
daysCount: number,
}) => {
const Icon = getIconByCoinType(account.currency.coinType)
return (
}) => (
<Wrapper onClick={onClick} {...props}>
<Box flow={4}>
<Box horizontal ff="Open Sans|SemiBold" flow={3} alignItems="center">
<Box
alignItems="center"
justifyContent="center"
style={{ color: account.currency.color }}
>
{Icon && <Icon size={20} />}
<Box alignItems="center" justifyContent="center" style={{ color: account.currency.color }}>
<CryptoCurrencyIcon currency={account.currency} size={20} />
</Box>
<Box>
<Box style={{ textTransform: 'uppercase' }} fontSize={0} color="graphite">
@ -104,7 +98,6 @@ const AccountCard = ({
/>
</Wrapper>
)
}
AccountCard.defaultProps = {
onClick: undefined,

15
src/components/DashboardPage/index.js

@ -6,9 +6,12 @@ import { compose } from 'redux'
import { translate } from 'react-i18next'
import { connect } from 'react-redux'
import { push } from 'react-router-redux'
import { formatCurrencyUnit, getFiatUnit } from '@ledgerhq/currencies'
import {
formatCurrencyUnit,
getFiatCurrencyByTicker,
} from '@ledgerhq/live-common/lib/helpers/currencies'
import type { Account } from '@ledgerhq/wallet-common/lib/types'
import type { Account } from '@ledgerhq/live-common/lib/types'
import chunk from 'lodash/chunk'
@ -94,9 +97,13 @@ class DashboardPage extends PureComponent<Props, State> {
text: 'Total balance',
color: colors.wallet,
balance: {
counterValue: formatCurrencyUnit(getFiatUnit(counterValue), data.totalBalance, {
counterValue: formatCurrencyUnit(
getFiatCurrencyByTicker(counterValue).units[0],
data.totalBalance,
{
showCode: true,
}),
},
),
},
})
}

2
src/components/DeviceCheckAddress.js

@ -3,7 +3,7 @@
import { PureComponent } from 'react'
import { ipcRenderer } from 'electron'
import type { Account } from '@ledgerhq/wallet-common/lib/types'
import type { Account } from '@ledgerhq/live-common/lib/types'
import type { Device } from 'types/common'
import { sendEvent } from 'renderer/events'

15
src/components/DeviceConnect/index.js

@ -3,14 +3,14 @@
import React, { PureComponent } from 'react'
import styled from 'styled-components'
import { Trans, translate } from 'react-i18next'
import { getCurrencyByCoinType } from '@ledgerhq/currencies'
import { getIconByCoinType } from '@ledgerhq/currencies/react'
import type { CryptoCurrency } from '@ledgerhq/live-common/lib/types'
import type { T, Device, Devices } from 'types/common'
import noop from 'lodash/noop'
import Box from 'components/base/Box'
import CryptoCurrencyIcon from 'components/CryptoCurrencyIcon'
import IconCheck from 'icons/Check'
import IconExclamationCircle from 'icons/ExclamationCircle'
@ -138,7 +138,7 @@ StepCheck.defaultProps = {
type Props = {
accountName: null | string,
appOpened: null | 'success' | 'fail',
coinType: number,
currency: CryptoCurrency,
devices: Devices,
deviceSelected: Device | null,
onChangeDevice: Function,
@ -180,16 +180,13 @@ class DeviceConnect extends PureComponent<Props> {
}
render() {
const { deviceSelected, accountName, coinType, t, onChangeDevice, devices } = this.props
const { deviceSelected, accountName, currency, t, onChangeDevice, devices } = this.props
const appState = this.getAppState()
const hasDevice = devices.length > 0
const hasMultipleDevices = devices.length > 1
const { name: appName } = getCurrencyByCoinType(coinType)
const IconCurrency = getIconByCoinType(coinType)
return (
<Box flow={4}>
<Step validated={hasDevice}>
@ -240,13 +237,13 @@ class DeviceConnect extends PureComponent<Props> {
<StepContent>
<StepIcon>
<WrapperIconCurrency>
<IconCurrency size={12} />
<CryptoCurrencyIcon currency={currency} size={12} />
</WrapperIconCurrency>
</StepIcon>
<Box grow shrink>
<Trans i18nKey="deviceConnect:step2.open" parent="div">
{'Open '}
<strong>{appName}</strong>
<strong>{currency.name}</strong>
{' App on your device'}
</Trans>
</Box>

2
src/components/DeviceMonit/index.js

@ -3,7 +3,7 @@
import React, { PureComponent } from 'react'
import { connect } from 'react-redux'
import { ipcRenderer } from 'electron'
import type { Account } from '@ledgerhq/wallet-common/lib/types'
import type { Account } from '@ledgerhq/live-common/lib/types'
import { sendEvent } from 'renderer/events'
import { getCurrentDevice } from 'reducers/devices'

14
src/components/DeviceMonitNew/index.js

@ -4,7 +4,7 @@ import { PureComponent } from 'react'
import { connect } from 'react-redux'
import { ipcRenderer } from 'electron'
import type { Account } from '@ledgerhq/wallet-common/lib/types'
import type { Account, CryptoCurrency } from '@ledgerhq/live-common/lib/types'
import type { Device, Devices } from 'types/common'
import { sendEvent } from 'renderer/events'
@ -19,7 +19,7 @@ type DeviceStatus = 'unconnected' | 'connected'
type AppStatus = 'success' | 'fail' | 'progress'
type Props = {
coinType: number,
currency: ?CryptoCurrency,
devices: Devices,
deviceSelected: Device | null,
account?: Account,
@ -78,7 +78,7 @@ class DeviceMonit extends PureComponent<Props, State> {
}
checkAppOpened = () => {
const { deviceSelected, account, coinType } = this.props
const { deviceSelected, account, currency } = this.props
if (deviceSelected === null) {
return
@ -93,9 +93,9 @@ class DeviceMonit extends PureComponent<Props, State> {
}
}
if (coinType) {
if (currency) {
options = {
coinType,
currencyId: currency.id,
}
}
@ -134,13 +134,13 @@ class DeviceMonit extends PureComponent<Props, State> {
}
render() {
const { coinType, account, devices, deviceSelected, render } = this.props
const { currency, account, devices, deviceSelected, render } = this.props
const { appStatus, deviceStatus } = this.state
if (render) {
return render({
appStatus,
coinType: account ? account.coinType : coinType,
currency: account ? account.currency : currency,
devices,
deviceSelected: deviceStatus === 'connected' ? deviceSelected : null,
deviceStatus,

2
src/components/IsUnlocked.js

@ -6,7 +6,7 @@ import { connect } from 'react-redux'
import { compose } from 'redux'
import styled from 'styled-components'
import { translate } from 'react-i18next'
import type { Account } from '@ledgerhq/wallet-common/lib/types'
import type { Account } from '@ledgerhq/live-common/lib/types'
import type { Settings, T } from 'types/common'
import IconLockScreen from 'icons/LockScreen'

6
src/components/OperationsList/Operation.js

@ -5,9 +5,9 @@ import { connect } from 'react-redux'
import styled from 'styled-components'
import moment from 'moment'
import noop from 'lodash/noop'
import { getIconByCoinType } from '@ledgerhq/currencies/react'
import { getCryptoCurrencyIcon } from '@ledgerhq/live-common/lib/react'
import type { Account, Operation as OperationType } from '@ledgerhq/wallet-common/lib/types'
import type { Account, Operation as OperationType } from '@ledgerhq/live-common/lib/types'
import type { T } from 'types/common'
@ -130,7 +130,7 @@ class Operation extends PureComponent<Props> {
} = this.props
const { unit, currency } = account
const time = moment(op.date)
const Icon = getIconByCoinType(account.currency.coinType)
const Icon = getCryptoCurrencyIcon(account.currency)
const isNegative = op.amount < 0
const type = !isNegative ? 'from' : 'to'

4
src/components/OperationsList/index.js

@ -9,9 +9,9 @@ import { translate } from 'react-i18next'
import {
groupAccountOperationsByDay,
groupAccountsOperationsByDay,
} from '@ledgerhq/wallet-common/lib/helpers/account'
} from '@ledgerhq/live-common/lib/helpers/account'
import type { Account } from '@ledgerhq/wallet-common/lib/types'
import type { Account } from '@ledgerhq/live-common/lib/types'
import noop from 'lodash/noop'
import keyBy from 'lodash/keyBy'

2
src/components/OperationsList/stories.js

@ -1,7 +1,7 @@
// @flow
import React from 'react'
import { genAccount } from '@ledgerhq/wallet-common/lib/mock/account'
import { genAccount } from '@ledgerhq/live-common/lib/mock/account'
import { storiesOf } from '@storybook/react'
import { boolean } from '@storybook/addon-knobs'

2
src/components/QRCodeExporter.js

@ -19,7 +19,7 @@ function makeChunks(state: State): Array<string> {
'account',
account.id,
account.name,
account.coinType,
account.currency.id,
]),
]
return data.map((arr, i) => JSON.stringify([data.length, i, ...arr]))

2
src/components/ReceiveBox.js

@ -4,7 +4,7 @@ import React, { PureComponent } from 'react'
import { connect } from 'react-redux'
import styled from 'styled-components'
import { ipcRenderer } from 'electron'
import type { Account } from '@ledgerhq/wallet-common/lib/types'
import type { Account } from '@ledgerhq/live-common/lib/types'
import type { Device } from 'types/common'

19
src/components/RequestAmount/index.js

@ -5,12 +5,11 @@ import { compose } from 'redux'
import { translate } from 'react-i18next'
import styled from 'styled-components'
import { connect } from 'react-redux'
import type { Account, CalculateCounterValue } from '@ledgerhq/wallet-common/lib/types'
import type { FiatUnit } from '@ledgerhq/currencies'
import type { Currency, Account, CalculateCounterValue } from '@ledgerhq/live-common/lib/types'
import type { T } from 'types/common'
import { getCounterValueFiatUnit } from 'reducers/settings'
import { counterValueCurrencySelector } from 'reducers/settings'
import { calculateCounterValueSelector, reverseCounterValueSelector } from 'reducers/counterValues'
import InputCurrency from 'components/base/InputCurrency'
@ -36,7 +35,7 @@ const InputCenter = styled(Box).attrs({
`
const mapStateToProps = state => ({
rightUnit: getCounterValueFiatUnit(state),
rightCurrency: counterValueCurrencySelector(state),
getCounterValue: calculateCounterValueSelector(state),
getReverseCounterValue: reverseCounterValueSelector(state),
})
@ -59,7 +58,7 @@ type Props = {
// used to determine the right input unit
// retrieved via selector (take the chosen countervalue unit)
rightUnit: FiatUnit,
rightCurrency: Currency,
// used to calculate the opposite field value (right & left)
getCounterValue: CalculateCounterValue,
@ -80,19 +79,19 @@ export class RequestAmount extends PureComponent<Props> {
}
handleChangeAmount = (changedField: string) => (val: number) => {
const { rightUnit, getReverseCounterValue, account, max, onChange } = this.props
const { rightCurrency, getReverseCounterValue, account, max, onChange } = this.props
if (changedField === 'left') {
onChange(val > max ? max : val)
} else if (changedField === 'right') {
const leftVal = getReverseCounterValue(account.currency, rightUnit)(val)
const leftVal = getReverseCounterValue(account.currency, rightCurrency)(val)
onChange(leftVal > max ? max : leftVal)
}
}
renderInputs(containerProps: Object) {
const { value, account, rightUnit, getCounterValue } = this.props
const right = getCounterValue(account.currency, rightUnit)(value)
const { value, account, rightCurrency, getCounterValue } = this.props
const right = getCounterValue(account.currency, rightCurrency)(value)
const rightUnit = rightCurrency.units[0]
return (
<Box horizontal grow shrink>
<InputCurrency

6
src/components/SelectAccount/index.js

@ -3,11 +3,11 @@
import React from 'react'
import { connect } from 'react-redux'
import { translate } from 'react-i18next'
import { getIconByCoinType } from '@ledgerhq/currencies/react'
import { getCryptoCurrencyIcon } from '@ledgerhq/live-common/lib/react'
import noop from 'lodash/noop'
import type { Account } from '@ledgerhq/wallet-common/lib/types'
import type { Account } from '@ledgerhq/live-common/lib/types'
import type { T } from 'types/common'
import { getVisibleAccounts } from 'reducers/accounts'
@ -22,7 +22,7 @@ const mapStateToProps = state => ({
})
const renderItem = a => {
const Icon = getIconByCoinType(a.coinType)
const Icon = getCryptoCurrencyIcon(a)
const { color } = a.currency
return (
<Box grow horizontal alignItems="center" flow={2}>

26
src/components/SelectAccount/stories.js

@ -2,35 +2,13 @@
import React, { Component } from 'react'
import { storiesOf } from '@storybook/react'
import Chance from 'chance'
import { getCurrencyByCoinType, getDefaultUnitByCoinType } from '@ledgerhq/currencies'
import { genAccount } from '@ledgerhq/live-common/lib/mock/account'
import { SelectAccount } from 'components/SelectAccount'
const chance = new Chance()
const stories = storiesOf('Components', module)
export const accounts = [...Array(20)].map(() => ({
id: chance.string(),
address: chance.string({
pool: 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789',
length: 30,
}),
addresses: [],
balance: chance.integer({ min: 10000000000, max: 2000000000000 }),
balanceByDay: {},
coinType: 1,
currency: getCurrencyByCoinType(1),
index: chance.integer({ min: 0, max: 20 }),
name: chance.name(),
path: '',
rootPath: '',
operations: [],
unit: getDefaultUnitByCoinType(1),
settings: {
minConfirmations: 2,
},
}))
export const accounts = [...Array(20)].map((_, i) => genAccount(i))
class Wrapper extends Component<any, any> {
state = {

28
src/components/SelectCurrency/index.js

@ -2,27 +2,24 @@
import React from 'react'
import { translate } from 'react-i18next'
import { getIconByCoinType } from '@ledgerhq/currencies/react'
import { listCurrencies } from '@ledgerhq/currencies'
import { listCryptoCurrencies } from '@ledgerhq/live-common/lib/helpers/currencies'
import noop from 'lodash/noop'
import type { Currency } from '@ledgerhq/currencies'
import type { CryptoCurrency } from '@ledgerhq/live-common/lib/types'
import type { T } from 'types/common'
import CryptoCurrencyIcon from 'components/CryptoCurrencyIcon'
import Select from 'components/base/Select'
import Box from 'components/base/Box'
const renderItem = a => {
const { color, name, coinType } = a
const Icon = getIconByCoinType(coinType)
const renderItem = (currency: CryptoCurrency) => {
const { color, name } = currency
return (
<Box grow horizontal alignItems="center" flow={2}>
{Icon && (
<Box style={{ width: 16, height: 16, color }}>
<Icon size={16} />
<CryptoCurrencyIcon currency={currency} size={16} />
</Box>
)}
<Box grow ff="Open Sans|SemiBold" color="dark" fontSize={4}>
{name}
</Box>
@ -30,23 +27,24 @@ const renderItem = a => {
)
}
const currencies = listCurrencies()
const currencies = listCryptoCurrencies().sort((a, b) => a.name.localeCompare(b.name))
type Props = {
onChange: Function,
value?: Currency,
value?: CryptoCurrency,
placeholder: string,
t: T,
}
const SelectCurrency = ({ onChange, value, t, ...props }: Props) => (
const SelectCurrency = ({ onChange, value, t, placeholder, ...props }: Props) => (
<Select
{...props}
value={value}
renderSelected={renderItem}
renderItem={renderItem}
keyProp="coinType"
items={currencies.sort((a, b) => (a.name < b.name ? -1 : 1))}
placeholder={t('common:selectCurrency')}
keyProp="id"
items={currencies}
placeholder={placeholder || t('common:selectCurrency')}
fontSize={4}
onChange={onChange}
/>

18
src/components/SettingsPage/sections/Currencies.js

@ -2,9 +2,9 @@
import React, { PureComponent } from 'react'
import { listCurrencies } from '@ledgerhq/currencies'
import { listCryptoCurrencies } from '@ledgerhq/live-common/lib/helpers/currencies'
import type { Currency } from '@ledgerhq/currencies'
import type { CryptoCurrency } from '@ledgerhq/live-common/lib/types'
import type { Settings, CurrencySettings, T } from 'types/common'
import SelectCurrency from 'components/SelectCurrency'
@ -43,21 +43,21 @@ type Props = {
}
type State = {
currency: Currency,
currency: CryptoCurrency,
}
class TabCurrencies extends PureComponent<Props, State> {
state = {
currency: listCurrencies()[0],
currency: listCryptoCurrencies()[0],
}
getCurrencySettings() {
const { settings } = this.props
const { currency } = this.state
return settings.currenciesSettings[currency.coinType]
return settings.currenciesSettings[currency.id]
}
handleChangeCurrency = (currency: Currency) => this.setState({ currency })
handleChangeCurrency = (currency: CryptoCurrency) => this.setState({ currency })
handleChangeConfirmationsToSpend = (nb: number) =>
this.updateCurrencySetting('confirmationsToSpend', nb)
@ -72,7 +72,7 @@ class TabCurrencies extends PureComponent<Props, State> {
if (!currencySettings) {
newCurrenciesSettings = {
...settings.currenciesSettings,
[currency.coinType]: {
[currency.id]: {
...CURRENCY_DEFAULTS_SETTINGS,
[key]: val,
},
@ -80,7 +80,7 @@ class TabCurrencies extends PureComponent<Props, State> {
} else {
newCurrenciesSettings = {
...settings.currenciesSettings,
[currency.coinType]: {
[currency.id]: {
...currencySettings,
[key]: val,
},
@ -95,7 +95,7 @@ class TabCurrencies extends PureComponent<Props, State> {
const { confirmationsToSpend, confirmationsNb } =
this.getCurrencySettings() || CURRENCY_DEFAULTS_SETTINGS
return (
<Section key={currency.coinType}>
<Section key={currency.id}>
<Header
icon={<IconCurrencies size={16} />}
title={t('settings:tabs.currencies')}

7
src/components/SettingsPage/sections/Display.js

@ -2,7 +2,7 @@
import React, { PureComponent } from 'react'
import moment from 'moment'
import { listFiats } from '@ledgerhq/currencies'
import { listFiatCurrencies } from '@ledgerhq/live-common/lib/helpers/currencies'
import type { Settings, T } from 'types/common'
@ -19,7 +19,10 @@ import {
SettingsSectionRow as Row,
} from '../SettingsSection'
const fiats = listFiats().map(fiat => ({
const fiats = listFiatCurrencies()
.map(f => f.units[0])
// For now we take first unit, in the future we'll need to figure out something else
.map(fiat => ({
key: fiat.code,
fiat,
name: `${fiat.name} - ${fiat.code}${fiat.symbol ? ` (${fiat.symbol})` : ''}`,

6
src/components/SideBar/index.js

@ -5,8 +5,8 @@ import { compose } from 'redux'
import { translate } from 'react-i18next'
import styled from 'styled-components'
import { connect } from 'react-redux'
import { getIconByCoinType } from '@ledgerhq/currencies/react'
import type { Account } from '@ledgerhq/wallet-common/lib/types'
import { getCryptoCurrencyIcon } from '@ledgerhq/live-common/lib/react'
import type { Account } from '@ledgerhq/live-common/lib/types'
import { MODAL_SEND, MODAL_RECEIVE, MODAL_ADD_ACCOUNT } from 'config/constants'
@ -104,7 +104,7 @@ class SideBar extends PureComponent<Props> {
</CapsSubtitle>
<GrowScroll pb={4} px={4} flow={2}>
{accounts.map(account => {
const Icon = getIconByCoinType(account.currency.coinType)
const Icon = getCryptoCurrencyIcon(account.currency)
return (
<Item
big

2
src/components/base/Chart/Tooltip.js

@ -2,7 +2,7 @@
import React from 'react'
import type { Unit } from '@ledgerhq/currencies'
import type { Unit } from '@ledgerhq/live-common/lib/types'
import { colors as themeColors } from 'styles/theme'
import { TooltipContainer } from 'components/base/Tooltip'

2
src/components/base/Chart/index.js

@ -37,7 +37,7 @@ import React, { PureComponent } from 'react'
import * as d3 from 'd3'
import noop from 'lodash/noop'
import type { Unit } from '@ledgerhq/currencies'
import type { Unit } from '@ledgerhq/live-common/lib/types'
import refreshNodes from './refreshNodes'
import refreshDraw from './refreshDraw'

2
src/components/base/Chart/refreshDraw.js

@ -2,7 +2,7 @@
import * as d3 from 'd3'
import moment from 'moment'
import { formatShort } from '@ledgerhq/currencies'
import { formatShort } from '@ledgerhq/live-common/lib/helpers/currencies'
import { colors as themeColors } from 'styles/theme'

4
src/components/base/Chart/stories.js

@ -1,7 +1,7 @@
// @flow
import React, { Component, Fragment } from 'react'
import { getDefaultUnitByCoinType } from '@ledgerhq/currencies'
import { getCryptoCurrencyById } from '@ledgerhq/live-common/lib/helpers/currencies'
import Chance from 'chance'
import moment from 'moment'
import { storiesOf } from '@storybook/react'
@ -13,7 +13,7 @@ import Chart from 'components/base/Chart'
const stories = storiesOf('Components/base', module)
const data = generateRandomData(365)
const unit = getDefaultUnitByCoinType(0)
const unit = getCryptoCurrencyById('bitcoin').units[0]
type State = {
start: number,

7
src/components/base/FlipTicker/stories.js

@ -3,7 +3,10 @@
import React, { Component } from 'react'
import { storiesOf } from '@storybook/react'
import { formatCurrencyUnit, getFiatUnit } from '@ledgerhq/currencies'
import {
formatCurrencyUnit,
getFiatCurrencyByTicker,
} from '@ledgerhq/live-common/lib/helpers/currencies'
import Chance from 'chance'
import Box from 'components/base/Box'
@ -12,7 +15,7 @@ import FlipTicker from 'components/base/FlipTicker'
const stories = storiesOf('Components/base', module)
const unit = getFiatUnit('USD')
const unit = getFiatCurrencyByTicker('USD').units[0]
const chance = new Chance()
function getValue() {

4
src/components/base/FormattedVal/__tests__/FormattedVal.test.js

@ -1,10 +1,10 @@
import React from 'react'
import { getDefaultUnitByCoinType } from '@ledgerhq/currencies'
import { getCryptoCurrencyById } from '@ledgerhq/live-common/lib/helpers/currencies'
import render from '__mocks__/render'
import FormattedVal from '..'
const bitcoinUnit = getDefaultUnitByCoinType(0)
const bitcoinUnit = getCryptoCurrencyById('bitcoin').units[0]
describe('components', () => {
describe('FormattedVal', () => {

16
src/components/base/FormattedVal/index.js

@ -7,9 +7,12 @@ import { connect } from 'react-redux'
import isUndefined from 'lodash/isUndefined'
import type { Settings } from 'types/common'
import type { Unit } from '@ledgerhq/currencies'
import type { Unit } from '@ledgerhq/live-common/lib/types'
import { formatCurrencyUnit, getFiatUnit } from '@ledgerhq/currencies'
import {
formatCurrencyUnit,
findCurrencyByTicker,
} from '@ledgerhq/live-common/lib/helpers/currencies'
import { getMarketColor } from 'styles/helpers'
@ -81,8 +84,13 @@ export function FormattedVal(props: Props) {
text = `${alwaysShowSign ? (isNegative ? '- ' : '+ ') : ''}${isNegative ? val * -1 : val} %`
} else {
if (fiat) {
unit = getFiatUnit(fiat)
} else if (!unit) {
console.warn('FormattedVal: passing fiat prop is deprecated')
const cur = findCurrencyByTicker(fiat)
if (cur) {
;[unit] = cur.units
}
}
if (!unit) {
return ''
}

4
src/components/base/InputCurrency/index.js

@ -2,7 +2,7 @@
import React, { PureComponent } from 'react'
import styled from 'styled-components'
import { formatCurrencyUnit } from '@ledgerhq/currencies'
import { formatCurrencyUnit } from '@ledgerhq/live-common/lib/helpers/currencies'
import noop from 'lodash/noop'
import isNaN from 'lodash/isNaN'
@ -11,7 +11,7 @@ import Box from 'components/base/Box'
import Input from 'components/base/Input'
import Select from 'components/base/Select'
import type { Unit } from '@ledgerhq/currencies'
import type { Unit } from '@ledgerhq/live-common/lib/types'
function parseValue(value) {
return value.toString().replace(/,/g, '.')

5
src/components/base/InputCurrency/stories.js

@ -5,13 +5,12 @@ import { storiesOf } from '@storybook/react'
import { action } from '@storybook/addon-actions'
import { boolean } from '@storybook/addon-knobs'
import { getCurrencyByCoinType } from '@ledgerhq/currencies'
import { getCryptoCurrencyById } from '@ledgerhq/live-common/lib/helpers/currencies'
import InputCurrency from 'components/base/InputCurrency'
const stories = storiesOf('Components', module)
const { units } = getCurrencyByCoinType(1)
const { units } = getCryptoCurrencyById('bitcoin')
class Wrapper extends Component<any, any> {
state = {

2
src/components/base/InputPassword/index.js

@ -50,7 +50,7 @@ type Props = {
onChange: Function,
t: T,
value: string,
withStrength: boolean,
withStrength?: boolean,
}
class InputPassword extends PureComponent<Props, State> {

4
src/components/base/Modal/ConfirmModal.js

@ -16,8 +16,8 @@ type Props = {
title: string,
subTitle: string,
desc: string,
confirmText: string,
cancelText: string,
confirmText?: string,
cancelText?: string,
onReject: Function,
onConfirm: Function,
t: T,

26
src/components/modals/AddAccount/01-step-currency.js

@ -2,40 +2,26 @@
import React from 'react'
import { listCurrencies } from '@ledgerhq/currencies'
import type { Currency } from '@ledgerhq/currencies/lib/types'
import type { CryptoCurrency } from '@ledgerhq/live-common/lib/types'
import type { T } from 'types/common'
import get from 'lodash/get'
import Box from 'components/base/Box'
import Label from 'components/base/Label'
import Select from 'components/base/Select'
const currencies = listCurrencies().map(currency => ({
key: currency.coinType,
name: currency.name,
data: currency,
}))
import SelectCurrency from 'components/SelectCurrency'
type Props = {
onChangeCurrency: Function,
currency: Currency | null,
currency?: ?CryptoCurrency,
t: T,
}
export default (props: Props) => (
<Box flow={1}>
<Label>{props.t('common:currency')}</Label>
<Select
<SelectCurrency
placeholder={props.t('common:chooseWalletPlaceholder')}
onChange={item => props.onChangeCurrency(item.data)}
renderSelected={item => item.name}
items={currencies}
value={
props.currency ? currencies.find(c => c.key === get(props, 'currency.coinType')) : null
}
onChange={props.onChangeCurrency}
value={props.currency}
/>
</Box>
)

10
src/components/modals/AddAccount/03-step-import.js

@ -2,10 +2,8 @@
import React, { Fragment } from 'react'
import styled from 'styled-components'
import { getDefaultUnitByCoinType } from '@ledgerhq/currencies'
import type { Currency } from '@ledgerhq/currencies/lib/types'
import type { Account } from '@ledgerhq/wallet-common/lib/types'
import type { CryptoCurrency, Account } from '@ledgerhq/live-common/lib/types'
import Box from 'components/base/Box'
@ -29,7 +27,7 @@ const AccountItem = styled(AccountCard)`
type Props = {
accountsImport: Object,
archivedAccounts: Account[],
currency: Currency | null,
currency?: ?CryptoCurrency,
importProgress: boolean,
onSelectAccount?: Function,
selectedAccounts?: Array<number>,
@ -37,7 +35,7 @@ type Props = {
function StepImport(props: Props) {
const hasAccountsImports = Object.keys(props.accountsImport).length > 0
const unit = props.currency !== null && getDefaultUnitByCoinType(props.currency.coinType)
const unit = props.currency && props.currency.units[0]
return (
<Box>
{props.importProgress ? (
@ -56,7 +54,7 @@ function StepImport(props: Props) {
onClick={props.onSelectAccount && props.onSelectAccount(a.id)}
account={{
...a,
coinType: props.currency && props.currency.coinType,
currencyId: props.currency && props.currency.id,
name: `Account ${a.accountIndex}`,
currency: props.currency,
unit,

18
src/components/modals/AddAccount/index.js

@ -5,10 +5,8 @@ import { connect } from 'react-redux'
import { compose } from 'redux'
import { translate } from 'react-i18next'
import { ipcRenderer } from 'electron'
import { getDefaultUnitByCoinType } from '@ledgerhq/currencies'
import type { Account } from '@ledgerhq/wallet-common/lib/types'
import type { Currency } from '@ledgerhq/currencies'
import type { Account, CryptoCurrency } from '@ledgerhq/live-common/lib/types'
import type { Device, T } from 'types/common'
@ -63,11 +61,11 @@ type Props = {
type State = {
accountsImport: Object,
currency: Currency | null,
deviceSelected: Device | null,
currency: ?CryptoCurrency,
deviceSelected: ?Device,
fetchingCounterValues: boolean,
selectedAccounts: Array<number>,
appStatus: null | string,
appStatus: ?string,
stepIndex: number,
}
@ -107,13 +105,13 @@ class AddAccountModal extends PureComponent<Props, State> {
const { accounts } = this.props
const { deviceSelected, currency } = this.state
if (deviceSelected === null || currency === null) {
if (!deviceSelected || !currency) {
return
}
sendEvent('usb', 'wallet.getAccounts', {
pathDevice: deviceSelected.path,
coinType: currency.coinType,
currencyId: currency.id,
currentAccounts: accounts.map(acc => acc.id),
})
}
@ -201,7 +199,7 @@ class AddAccountModal extends PureComponent<Props, State> {
name: `Account ${accountIndex + 1}`,
archived: true,
currency,
unit: getDefaultUnitByCoinType(currency.coinType),
unit: currency.units[0],
})
}
}
@ -223,7 +221,7 @@ class AddAccountModal extends PureComponent<Props, State> {
: [a, ...prev.selectedAccounts],
}))
handleChangeCurrency = (currency: Currency) => this.setState({ currency })
handleChangeCurrency = (currency: CryptoCurrency) => this.setState({ currency })
handleChangeStatus = (deviceStatus, appStatus) => this.setState({ appStatus })

2
src/components/modals/OperationDetails.js

@ -7,7 +7,7 @@ import { translate } from 'react-i18next'
import styled from 'styled-components'
import moment from 'moment'
import type { Account, Operation } from '@ledgerhq/wallet-common/lib/types'
import type { Account, Operation } from '@ledgerhq/live-common/lib/types'
import type { T } from 'types/common'
import { MODAL_OPERATION_DETAILS } from 'config/constants'

2
src/components/modals/Receive/01-step-account.js

@ -2,7 +2,7 @@
import React from 'react'
import type { Account } from '@ledgerhq/wallet-common/lib/types'
import type { Account } from '@ledgerhq/live-common/lib/types'
import type { T } from 'types/common'
import Box from 'components/base/Box'

2
src/components/modals/Receive/03-step-confirm-address.js

@ -3,7 +3,7 @@
import React, { Fragment } from 'react'
import styled from 'styled-components'
import type { Account } from '@ledgerhq/wallet-common/lib/types'
import type { Account } from '@ledgerhq/live-common/lib/types'
import type { Device, T } from 'types/common'
import Box from 'components/base/Box'

2
src/components/modals/Receive/04-step-receive-funds.js

@ -2,7 +2,7 @@
import React from 'react'
import type { Account } from '@ledgerhq/wallet-common/lib/types'
import type { Account } from '@ledgerhq/live-common/lib/types'
import type { T } from 'types/common'
import Box from 'components/base/Box'

2
src/components/modals/Receive/index.js

@ -3,7 +3,7 @@
import React, { Fragment, PureComponent } from 'react'
import { translate } from 'react-i18next'
import type { Account } from '@ledgerhq/wallet-common/lib/types'
import type { Account } from '@ledgerhq/live-common/lib/types'
import type { T, Device } from 'types/common'
import { MODAL_RECEIVE } from 'config/constants'

2
src/components/modals/Send/01-step-amount.js

@ -1,7 +1,7 @@
// @flow
import React, { Fragment } from 'react'
import type { Account } from '@ledgerhq/wallet-common/lib/types'
import type { Account } from '@ledgerhq/live-common/lib/types'
import type { T } from 'types/common'

2
src/components/modals/Send/03-step-verification.js

@ -9,7 +9,7 @@ import { multiline } from 'styles/helpers'
import DeviceCheckAddress from 'components/DeviceCheckAddress'
import DeviceConfirm from 'components/DeviceConfirm'
import type { Account } from '@ledgerhq/wallet-common/lib/types'
import type { Account } from '@ledgerhq/live-common/lib/types'
import type { Device, T } from 'types/common'
const Container = styled(Box).attrs({

2
src/components/modals/Send/Footer.js

@ -1,7 +1,7 @@
// @flow
import React from 'react'
import type { Account } from '@ledgerhq/wallet-common/lib/types'
import type { Account } from '@ledgerhq/live-common/lib/types'
import type { T } from 'types/common'

2
src/components/modals/Send/index.js

@ -5,7 +5,7 @@ import { translate } from 'react-i18next'
import { connect } from 'react-redux'
import { compose } from 'redux'
import type { Account } from '@ledgerhq/wallet-common/lib/types'
import type { Account } from '@ledgerhq/live-common/lib/types'
import type { T, Device } from 'types/common'
import { getVisibleAccounts } from 'reducers/accounts'

2
src/components/modals/SettingsAccount.js

@ -4,7 +4,7 @@ import React, { PureComponent } from 'react'
import { connect } from 'react-redux'
import get from 'lodash/get'
import { push } from 'react-router-redux'
import type { Account } from '@ledgerhq/wallet-common/lib/types'
import type { Account } from '@ledgerhq/live-common/lib/types'
import { MODAL_SETTINGS_ACCOUNT } from 'config/constants'

17
src/components/modals/StepConnectDevice.js

@ -2,8 +2,7 @@
import React from 'react'
import type { Account } from '@ledgerhq/wallet-common/lib/types'
import type { Currency } from '@ledgerhq/currencies/lib/types'
import type { Account, CryptoCurrency } from '@ledgerhq/live-common/lib/types'
import type { Device } from 'types/common'
import DeviceConnect from 'components/DeviceConnect'
@ -12,7 +11,7 @@ import DeviceMonit from 'components/DeviceMonitNew'
type Props = {
accountName?: string,
account?: ?Account,
currency?: ?Currency,
currency?: ?CryptoCurrency,
deviceSelected: ?Device,
onChangeDevice: Function,
onStatusChange: Function,
@ -21,13 +20,13 @@ type Props = {
const StepConnectDevice = (props: Props) => (
<DeviceMonit
account={props.account}
coinType={props.currency && props.currency.coinType}
currency={props.currency}
deviceSelected={props.deviceSelected}
onStatusChange={props.onStatusChange}
render={({ coinType, appStatus, devices, deviceSelected }) => (
render={({ currency, appStatus, devices, deviceSelected }) => (
<DeviceConnect
accountName={props.accountName}
coinType={coinType}
currency={currency}
appOpened={appStatus === 'success' ? 'success' : appStatus === 'fail' ? 'fail' : null}
devices={devices}
deviceSelected={deviceSelected}
@ -37,10 +36,4 @@ const StepConnectDevice = (props: Props) => (
/>
)
StepConnectDevice.defaultProps = {
accountName: undefined,
account: undefined,
currency: undefined,
}
export default StepConnectDevice

137
src/helpers/__tests__/balance.test.js

@ -1,137 +0,0 @@
import { getBalanceHistoryForAccount, getBalanceHistoryForAccounts } from 'helpers/balance'
const counterValues = {
BTC: {
USD: {
'2018-01-01': 1,
'2018-01-02': 2,
'2018-01-03': 3,
'2018-01-04': 4,
'2018-01-05': 5,
},
},
}
describe('helpers > balance', () => {
describe('getBalanceHistoryForAccount', () => {
test('should handle a simple case', () => {
const account = {
coinType: 0,
balanceByDay: {
'2018-01-01': 1,
'2018-01-02': 2,
},
}
const interval = {
start: '2018-01-01',
end: '2018-01-02',
}
const balances = getBalanceHistoryForAccount({
counterValue: 'USD',
account,
counterValues,
interval,
})
expect(balances).toEqual([
{ date: '2018-01-01', balance: 1 },
{ date: '2018-01-02', balance: 4 },
])
})
test('should handle empty days', () => {
const account = {
coinType: 0,
balanceByDay: {
'2018-01-01': 1,
'2018-01-03': 2,
},
}
const interval = {
start: '2018-01-01',
end: '2018-01-03',
}
const balances = getBalanceHistoryForAccount({
counterValue: 'USD',
account,
counterValues,
interval,
})
expect(balances).toEqual([
{ date: '2018-01-01', balance: 1 },
{ date: '2018-01-02', balance: 2 },
{ date: '2018-01-03', balance: 6 },
])
})
test('should work if interval dont contain operations', () => {
const account = {
coinType: 0,
balanceByDay: {
'2018-01-01': 1,
},
}
const interval = {
start: '2018-01-02',
end: '2018-01-03',
}
const balances = getBalanceHistoryForAccount({
counterValue: 'USD',
account,
counterValues,
interval,
})
expect(balances).toEqual([
{ date: '2018-01-02', balance: 2 },
{ date: '2018-01-03', balance: 3 },
])
})
})
describe('getBalanceHistoryForAccounts', () => {
test('should merge multiple accounts balance', () => {
const account1 = {
coinType: 0,
balanceByDay: {
'2018-01-01': 1,
'2018-01-02': 2,
},
}
const account2 = {
coinType: 0,
balanceByDay: {
'2018-01-02': 5,
'2018-01-04': 6,
},
}
const interval = {
start: '2018-01-01',
end: '2018-01-04',
}
const balances = getBalanceHistoryForAccounts({
counterValue: 'USD',
accounts: [account1, account2],
counterValues,
interval,
})
expect(balances).toEqual([
{ date: '2018-01-01', balance: 1 },
{ date: '2018-01-02', balance: 14 },
{ date: '2018-01-03', balance: 21 },
{ date: '2018-01-04', balance: 32 },
])
})
})
})

5
src/helpers/balance.js

@ -2,8 +2,7 @@
import moment from 'moment'
import get from 'lodash/get'
import { getDefaultUnitByCoinType } from '@ledgerhq/currencies'
import type { Account } from '@ledgerhq/wallet-common/lib/types'
import type { Account } from '@ledgerhq/live-common/lib/types'
import find from 'lodash/find'
import first from 'lodash/first'
@ -70,7 +69,7 @@ export function getBalanceHistoryForAccount({
interval: DateInterval,
}): Array<BalanceHistoryDay> {
const todayDate = moment().format('YYYY-MM-DD')
const unit = getDefaultUnitByCoinType(account.coinType)
const { unit } = account
const counterVals = get(counterValues, `${unit.code}.${counterValue}`)
let lastBalance = getBalanceAtIntervalStart(account, interval)
return mapInterval(interval, date => {

19
src/helpers/btc.js

@ -1,9 +1,10 @@
// @flow
import { coinTypeForId } from 'internals/usb/wallet/accounts'
import ledger from 'ledger-test-library'
import bitcoin from 'bitcoinjs-lib'
import axios from 'axios'
import type { OperationRaw } from '@ledgerhq/wallet-common/lib/types'
import type { OperationRaw } from '@ledgerhq/live-common/lib/types'
import groupBy from 'lodash/groupBy'
import noop from 'lodash/noop'
@ -11,16 +12,16 @@ import uniqBy from 'lodash/uniqBy'
const GAP_LIMIT_ADDRESSES = 20
export const networks = [
{
export const networks = {
bitcoin: {
...bitcoin.networks.bitcoin,
family: 1,
},
{
bitcoin_testnet: {
...bitcoin.networks.testnet,
family: 1,
},
]
}
export function computeOperation(addresses: Array<string>, accountId: string) {
return (t: Object) => {
@ -78,7 +79,7 @@ export async function getAccount({
hdnode,
segwit,
network,
coinType,
currencyId,
accountId,
asyncDelay = 250,
onProgress = noop,
@ -89,7 +90,7 @@ export async function getAccount({
currentIndex?: number,
hdnode: Object,
segwit: boolean,
coinType: number,
currencyId: string,
accountId: string,
network: Object,
asyncDelay?: number,
@ -156,7 +157,7 @@ export async function getAccount({
let txs = []
const operationsOpts = { coin_type: coinType }
const operationsOpts = { coin_type: coinTypeForId(currencyId) }
try {
txs = await ledger.getTransactions(listAddresses, operationsOpts)
@ -204,7 +205,7 @@ export async function getAccount({
const account = {
...nextAddress,
coinType,
currencyId,
addresses: operations.length > 0 ? allAddresses : [],
balance,
balanceByDay: getBalanceByDay(operations),

1
src/helpers/db.js

@ -47,6 +47,7 @@ export default {
}
},
// TODO flowtype this. we should be able to express all the possible entries and their expected type (with a union type)
get: (key: DBKey, defaults: any): any => {
const db = store(key)
const data = db.get('data', defaults)

29
src/internals/usb/wallet/accounts.js

@ -9,8 +9,6 @@ import Btc from '@ledgerhq/hw-app-btc'
import { getAccount, getHDNode, networks } from 'helpers/btc'
import { serializeAccounts } from 'reducers/accounts'
type CoinType = number
async function sleep(delay, callback) {
if (delay !== 0) {
await new Promise(resolve => setTimeout(resolve, delay))
@ -56,16 +54,24 @@ function encodeBase58Check(vchIn) {
return bs58check.encode(Buffer.from(vchIn))
}
export function coinTypeForId(id: string) {
if (id === 'bitcoin_testnet') return 1
if (id === 'bitcoin') return 0
throw new Error('coinTypeForId is a hack and will disappear with libcore')
}
export function getPath({
coinType,
currencyId,
account,
segwit = true,
}: {
coinType: CoinType,
currencyId: string,
account?: any,
segwit: boolean,
}) {
return `${segwit ? 49 : 44}'/${coinType}'${account !== undefined ? `/${account}'` : ''}`
return `${segwit ? 49 : 44}'/${coinTypeForId(currencyId)}'${
account !== undefined ? `/${account}'` : ''
}`
}
export function verifyAddress({
@ -86,20 +92,20 @@ export default async ({
transport,
currentAccounts,
onProgress,
coinType = 1,
currencyId = 'bitcoin_testnet',
segwit = true,
nextAccountDelay = 1e3,
}: {
transport: Object,
currentAccounts: Array<*>,
onProgress: Function,
coinType?: CoinType,
currencyId?: string,
segwit?: boolean,
nextAccountDelay?: number,
}) => {
const btc = new Btc(transport)
const network = networks[coinType]
const network = networks[currencyId]
const [p2pkh, p2sh, fam] = [network.pubKeyHash, network.scriptHash, network.family].map(v =>
v.toString(16).padStart(4, 0),
@ -110,7 +116,7 @@ export default async ({
const getPublicKey = path => btc.getWalletPublicKey(path)
let result = bitcoin.crypto.sha256(
await getPublicKey(getPath({ segwit, coinType })).then(
await getPublicKey(getPath({ segwit, currencyId })).then(
({ publicKey }) => new Uint8Array(parseHexString(getCompressPublicKey(publicKey))),
),
)
@ -139,7 +145,7 @@ export default async ({
}
const getAllAccounts = async (currentAccount = 0, accounts = []) => {
const path = getPath({ segwit, coinType, account: currentAccount })
const path = getPath({ segwit, currencyId, account: currentAccount })
const xpub58 = await getXpub58ByPath({ path, account: currentAccount, network })
if (currentAccounts.includes(xpub58)) {
@ -149,7 +155,7 @@ export default async ({
const hdnode = getHDNode({ xpub58, network })
const account = await getAccount({
asyncDelay: 0,
coinType,
currencyId,
accountId: xpub58,
hdnode,
network,
@ -164,7 +170,6 @@ export default async ({
accounts.push({
id: xpub58,
coinType,
...account,
})

24
src/internals/usb/wallet/index.js

@ -5,12 +5,11 @@ import Btc from '@ledgerhq/hw-app-btc'
import getAllAccounts, { getPath, verifyAddress } from './accounts'
async function getAllAccountsByCoinType({ pathDevice, coinType, currentAccounts, onProgress }) {
async function getAllAccountsByCurrencyId({ pathDevice, currencyId, currentAccounts, onProgress }) {
const transport = await CommNodeHid.open(pathDevice)
// 1: BTC Testnet
if (coinType === 1) {
return getAllAccounts({ coinType, transport, currentAccounts, onProgress })
if (currencyId === 'bitcoin_testnet') {
return getAllAccounts({ currencyId, transport, currentAccounts, onProgress })
}
throw new Error('Invalid coinType')
@ -19,11 +18,11 @@ async function getAllAccountsByCoinType({ pathDevice, coinType, currentAccounts,
export default (sendEvent: Function) => ({
getAccounts: async ({
pathDevice,
coinType,
currencyId,
currentAccounts,
}: {
pathDevice: string,
coinType: number,
currencyId: string,
currentAccounts: Array<string>,
}) => {
sendEvent(
@ -35,9 +34,9 @@ export default (sendEvent: Function) => ({
)
try {
const data = await getAllAccountsByCoinType({
const data = await getAllAccountsByCurrencyId({
pathDevice,
coinType,
currencyId,
currentAccounts,
onProgress: progress => sendEvent('wallet.getAccounts.progress', progress, { kill: false }),
})
@ -59,13 +58,13 @@ export default (sendEvent: Function) => ({
}
},
checkIfAppOpened: async ({
coinType,
currencyId,
devicePath,
accountPath,
accountAddress,
segwit = true,
}: {
coinType?: number,
currencyId?: string,
devicePath: string,
accountPath: string,
accountAddress: string,
@ -82,9 +81,8 @@ export default (sendEvent: Function) => ({
throw new Error('Address is different')
}
}
if (coinType) {
await btc.getWalletPublicKey(getPath({ coinType, segwit }), false, segwit)
if (currencyId) {
await btc.getWalletPublicKey(getPath({ currencyId, segwit }), false, segwit)
sendEvent('wallet.checkIfAppOpened.success', { devicePath })
}
} catch (err) {

2
src/main/counterValuesSync.js

@ -1,6 +1,6 @@
// @flow
import { fetchCurrentRates } from '@ledgerhq/wallet-common/lib/api/countervalue'
import { fetchCurrentRates } from '@ledgerhq/live-common/lib/api/countervalue'
type SendFunction = (type: string, data: *) => void

30
src/reducers/accounts.js

@ -1,12 +1,13 @@
// @flow
import { createSelector } from 'reselect'
import { handleActions } from 'redux-actions'
import { createAccountModel } from '@ledgerhq/wallet-common/lib/models/account'
import { createAccountModel } from '@ledgerhq/live-common/lib/models/account'
import every from 'lodash/every'
import get from 'lodash/get'
import reduce from 'lodash/reduce'
import type { Account } from '@ledgerhq/wallet-common/lib/types'
import type { Account } from '@ledgerhq/live-common/lib/types'
import type { State } from 'reducers'
@ -58,7 +59,32 @@ const handlers: Object = {
// Selectors
export function accountsSelector(state: { accounts: AccountsState }): Account[] {
return state.accounts
}
export const archivedAccountsSelector = createSelector(accountsSelector, accounts =>
accounts.filter(acc => acc.archived),
)
export const visibleAccountsSelector = createSelector(accountsSelector, accounts =>
accounts.filter(acc => !acc.archived),
)
export const currenciesSelector = createSelector(visibleAccountsSelector, accounts =>
[...new Set(accounts.map(a => a.currency))].sort((a, b) => a.name.localeCompare(b.name)),
)
export const accountSelector = createSelector(
accountsSelector,
(_, { accountId }: { accountId: string }) => accountId,
(accounts, accountId) => accounts.find(a => a.id === accountId),
)
// TODO remove deprecated selectors
export function getTotalBalance(state: { accounts: AccountsState }) {
// TODO we will have it using utility functions
return reduce(
state.accounts,
(result, account) => {

4
src/reducers/counterValues.js

@ -7,9 +7,9 @@ import {
makeCalculateCounterValue,
makeReverseCounterValue,
formatCounterValueDay,
} from '@ledgerhq/wallet-common/lib/helpers/countervalue'
} from '@ledgerhq/live-common/lib/helpers/countervalue'
import type { CalculateCounterValue } from '@ledgerhq/wallet-common/lib/types'
import type { CalculateCounterValue } from '@ledgerhq/live-common/lib/types'
import type { State } from 'reducers'
export type CounterValuesState = {}

48
src/reducers/settings.js

@ -1,15 +1,28 @@
// @flow
import { handleActions } from 'redux-actions'
import { getFiatUnit } from '@ledgerhq/currencies'
import type { Currency } from '@ledgerhq/currencies'
import get from 'lodash/get'
import { findCurrencyByTicker } from '@ledgerhq/live-common/lib/helpers/currencies'
import type { CryptoCurrency, Currency } from '@ledgerhq/live-common/lib/types'
import type { Settings, CurrencySettings } from 'types/common'
import type { State } from 'reducers'
export type SettingsState = Object
export type SettingsState = {
hasCompletedOnboarding: boolean,
username: string,
counterValue: string,
language: string,
orderAccounts: string,
password: {
isEnabled: boolean,
value: string,
},
marketIndicator: string,
currenciesSettings: {
[currencyId: string]: CurrencySettings,
},
region: string,
}
const defaultState: SettingsState = {
hasCompletedOnboarding: false,
@ -53,22 +66,25 @@ const handlers: Object = {
}),
}
export const hasPassword = (state: Object) =>
get(state.settings, 'password.isEnabled', defaultState.password.isEnabled)
// TODO refactor selectors to *Selector naming convention
export const hasPassword = (state: State): boolean => state.settings.password.isEnabled
export const getCounterValueCode = (state: Object) =>
get(state.settings, 'counterValue', defaultState.counterValue)
export const getCounterValueCode = (state: State) => state.settings.counterValue
export const getCounterValueFiatUnit = (state: Object) => getFiatUnit(getCounterValueCode(state))
export const counterValueCurrencySelector = (state: State): ?Currency =>
findCurrencyByTicker(getCounterValueCode(state))
export const getLanguage = (state: Object) => get(state.settings, 'language', defaultState.language)
export const getLanguage = (state: State) => state.settings.language
export const getOrderAccounts = (state: Object) =>
get(state.settings, 'orderAccounts', defaultState.orderAccounts)
export const getOrderAccounts = (state: State) => state.settings.orderAccounts
export const currencySettingsSelector = (state: State, currency: Currency): CurrencySettings => {
const currencySettings = state.settings.currenciesSettings[currency.coinType]
return currencySettings || CURRENCY_DEFAULTS_SETTINGS
export const currencySettingsSelector = (
state: State,
currency: CryptoCurrency,
): CurrencySettings => {
const currencySettings = state.settings.currenciesSettings[currency.id]
return { ...CURRENCY_DEFAULTS_SETTINGS, ...currencySettings }
}
export const marketIndicatorSelector = (state: State) => state.settings.marketIndicator

11
src/renderer/events.js

@ -4,9 +4,8 @@ import { ipcRenderer } from 'electron'
import objectPath from 'object-path'
import debug from 'debug'
import uniqBy from 'lodash/uniqBy'
import { getFiatUnit } from '@ledgerhq/currencies'
import type { Account } from '@ledgerhq/wallet-common/lib/types'
import type { Currency, Unit } from '@ledgerhq/currencies'
import { getFiatCurrencyByTicker } from '@ledgerhq/live-common/lib/helpers/currencies'
import type { Currency, Account } from '@ledgerhq/live-common/lib/types'
import { CHECK_UPDATE_DELAY, SYNC_ACCOUNT_DELAY, SYNC_COUNTER_VALUES_DELAY } from 'config/constants'
@ -89,10 +88,10 @@ export function startSyncAccounts(accounts: Account[]) {
syncAccountsInProgress = true
sendEvent('accounts', 'sync.all', {
accounts: accounts.map(account => {
const { id, coinType, rootPath, addresses, index, operations } = account
const { id, currency, rootPath, addresses, index, operations } = account
return {
id,
coinType,
currencyId: currency.id,
allAddresses: addresses,
currentIndex: index,
rootPath,
@ -111,7 +110,7 @@ export function stopSyncAccounts() {
export function startSyncCounterValues(counterValueCode: string, accounts: Account[]) {
d.sync('Sync counterValues - start')
const currencies: Currency[] = uniqBy(accounts.map(a => a.currency), 'code')
const counterValue: Unit = getFiatUnit(counterValueCode)
const counterValue = getFiatCurrencyByTicker(counterValueCode)
sendEvent('msg', 'counterValues.sync', { currencies, counterValue })
}

2
src/renderer/init.js

@ -34,7 +34,7 @@ const rootNode = document.getElementById('app')
store.dispatch(fetchSettings())
store.dispatch(initCounterValues())
const state = store.getState() || {}
const state = store.getState()
const language = getLanguage(state)
const locked = isLocked(state)

16
src/stories/currencies.stories.js

@ -2,21 +2,21 @@
import React, { Fragment } from 'react'
import { storiesOf } from '@storybook/react'
import { listCurrencies } from '@ledgerhq/currencies'
import { getIconByCoinType } from '@ledgerhq/currencies/react'
import { listCryptoCurrencies } from '@ledgerhq/live-common/lib/helpers/currencies'
import { getCryptoCurrencyIcon } from '@ledgerhq/live-common/lib/react'
import type { Currency } from '@ledgerhq/currencies'
import type { CryptoCurrency } from '@ledgerhq/live-common/lib/types'
const stories = storiesOf('Common', module)
const currencies: Array<Currency> = listCurrencies()
const currencies: Array<CryptoCurrency> = listCryptoCurrencies()
stories.add('Currencies', () => (
<div>
<table border="1">
<thead>
<tr>
<td>{'coin type'}</td>
<td>{'id'}</td>
<td>{'name'}</td>
<td>{'color'}</td>
<td>{'icon'}</td>
@ -25,10 +25,10 @@ stories.add('Currencies', () => (
</thead>
<tbody>
{currencies.map(cur => {
const Icon = getIconByCoinType(cur.coinType)
const Icon = getCryptoCurrencyIcon(cur)
return (
<tr key={cur.coinType}>
<td>{cur.coinType}</td>
<tr key={cur.id}>
<td>{cur.id}</td>
<td>{cur.name}</td>
<td>
{cur.color ? (

2
src/types/common.js

@ -25,7 +25,7 @@ export type CurrencySettings = {
}
export type CurrenciesSettings = {
[coinType: number]: CurrencySettings,
[id: string]: CurrencySettings,
}
export type Settings = {

18
yarn.lock

@ -956,14 +956,6 @@
lodash "^4.2.0"
to-fast-properties "^2.0.0"
"@ledgerhq/currencies@^4.10.1":
version "4.10.1"
resolved "https://registry.yarnpkg.com/@ledgerhq/currencies/-/currencies-4.10.1.tgz#462081005e3e37e0737bad9aba189eef1663e96a"
dependencies:
lodash "^4.17.5"
numeral "^2.0.6"
querystring "^0.2.0"
"@ledgerhq/hw-app-btc@^4.7.3":
version "4.7.3"
resolved "https://registry.yarnpkg.com/@ledgerhq/hw-app-btc/-/hw-app-btc-4.7.3.tgz#5a7d365f893f5a72bbb6b639d1738edced712c5f"
@ -990,14 +982,14 @@
dependencies:
events "^2.0.0"
"@ledgerhq/wallet-common@^1.2.0":
version "1.2.0"
resolved "https://registry.yarnpkg.com/@ledgerhq/wallet-common/-/wallet-common-1.2.0.tgz#5e648829b6dff0fe33f31da2ee4a974df405642e"
"@ledgerhq/live-common@^2.0.0-rc4":
version "2.0.0-rc4"
resolved "https://registry.yarnpkg.com/@ledgerhq/live-common/-/live-common-2.0.0-rc4.tgz#5f1028ff3e52fc6bf7e42c5ea64d71be9b843f82"
dependencies:
"@ledgerhq/currencies" "^4.10.1"
axios "^0.18.0"
invariant "^2.2.2"
lodash "^4.17.4"
numeral "^2.0.6"
prando "^3.0.1"
react "^16.0.0"
@ -5018,7 +5010,7 @@ electron-webpack@^2.0.1:
webpack-merge "^4.1.2"
yargs "^11.1.0"
electron@1.8.4:
electron@1.8.4, electron@^1.8.2:
version "1.8.4"
resolved "https://registry.yarnpkg.com/electron/-/electron-1.8.4.tgz#cca8d0e6889f238f55b414ad224f03e03b226a38"
dependencies:

Loading…
Cancel
Save