Browse Source

Merge pull request #221 from meriadec/unify-types

Unify types between mobile & desktop wallets
master
Loëck Vézien 7 years ago
committed by GitHub
parent
commit
19acddb8da
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 6
      src/components/AccountPage/index.js
  2. 4
      src/components/BalanceSummary/index.js
  3. 4
      src/components/CalculateBalance.js
  4. 32
      src/components/DashboardPage/index.js
  5. 4
      src/components/IsUnlocked.js
  6. 2
      src/components/OperationsList/ConfirmationCheck.js
  7. 46
      src/components/OperationsList/index.js
  8. 21
      src/components/OperationsList/stories.js
  9. 4
      src/components/SelectAccount/index.js
  10. 2
      src/components/SelectAccount/stories.js
  11. 4
      src/components/SideBar/index.js
  12. 2
      src/components/base/Bar/stories.js
  13. 2
      src/components/base/Box/stories.js
  14. 2
      src/components/base/Button/stories.js
  15. 2
      src/components/base/CheckBox/stories.js
  16. 5
      src/components/base/FormattedVal/index.js
  17. 2
      src/components/base/GrowScroll/stories.js
  18. 2
      src/components/base/Input/stories.js
  19. 2
      src/components/base/InputCurrency/stories.js
  20. 2
      src/components/base/Modal/stories.js
  21. 2
      src/components/base/NewChart/stories.js
  22. 2
      src/components/base/Pills/stories.js
  23. 2
      src/components/base/QRCode/stories.js
  24. 2
      src/components/base/Radio/stories.js
  25. 2
      src/components/base/Select/stories.js
  26. 2
      src/components/base/Tabs/stories.js
  27. 4
      src/components/base/Text/stories.js
  28. 2
      src/components/base/Tooltip/stories.js
  29. 6
      src/components/modals/AddAccount/ImportAccounts.js
  30. 4
      src/components/modals/AddAccount/RestoreAccounts.js
  31. 14
      src/components/modals/AddAccount/index.js
  32. 8
      src/components/modals/SettingsAccount.js
  33. 2
      src/helpers/__tests__/balance.test.js
  34. 6
      src/helpers/balance.js
  35. 47
      src/helpers/btc.js
  36. 4
      src/internals/accounts/sync.js
  37. 8
      src/internals/usb/wallet/accounts.js
  38. 33
      src/reducers/accounts.js
  39. 16
      src/renderer/events.js
  40. 2
      src/renderer/i18n/instanciate.js
  41. 2
      src/renderer/i18n/storybook.js
  42. 4
      src/stories/currencies.stories.js
  43. 13
      src/types/common.js
  44. 0
      static/i18n/en/operationsList.yml
  45. 0
      static/i18n/fr/operationsList.yml

6
src/components/AccountPage/index.js

@ -28,7 +28,7 @@ import Box from 'components/base/Box'
import Button from 'components/base/Button'
import FormattedVal from 'components/base/FormattedVal'
import PillsDaysCount from 'components/PillsDaysCount'
import TransactionsList from 'components/TransactionsList'
import OperationsList from 'components/OperationsList'
import AccountHeader from './AccountHeader'
@ -156,9 +156,9 @@ class AccountPage extends PureComponent<Props, State> {
)}
/>
</Box>
<TransactionsList
<OperationsList
title={t('account:lastOperations')}
transactions={account.transactions}
operations={account.operations}
minConfirmations={account.settings.minConfirmations}
/>
</Box>

4
src/components/BalanceSummary/index.js

@ -4,7 +4,7 @@ import React, { Fragment } from 'react'
import { getFiatUnit } from '@ledgerhq/currencies'
import type { Accounts } from 'types/common'
import type { Account } from 'types/common'
import Chart from 'components/base/NewChart'
import Box, { Card } from 'components/base/Box'
@ -15,7 +15,7 @@ type Props = {
counterValue: string,
chartColor: string,
chartId: string,
accounts: Accounts,
accounts: Account[],
selectedTime: string,
daysCount: number,
renderHeader: null | Function,

4
src/components/CalculateBalance.js

@ -3,7 +3,7 @@
import { PureComponent } from 'react'
import { connect } from 'react-redux'
import type { Accounts } from 'types/common'
import type { Account } from 'types/common'
import calculateBalance from 'helpers/balance'
@ -12,7 +12,7 @@ const mapStateToProps = state => ({
})
type Props = {
accounts: Accounts,
accounts: Account[],
counterValues: Object,
daysCount: number,
render: Function,

32
src/components/DashboardPage/index.js

@ -10,7 +10,7 @@ import chunk from 'lodash/chunk'
import get from 'lodash/get'
import sortBy from 'lodash/sortBy'
import type { Account, Accounts, T } from 'types/common'
import type { Account, Operation, T } from 'types/common'
import { getVisibleAccounts } from 'reducers/accounts'
import { getCounterValue } from 'reducers/settings'
@ -23,7 +23,7 @@ import BalanceSummary from 'components/BalanceSummary'
import Box from 'components/base/Box'
import PillsDaysCount from 'components/PillsDaysCount'
import Text from 'components/base/Text'
import TransactionsList from 'components/TransactionsList'
import OperationsList from 'components/OperationsList'
import AccountCard from './AccountCard'
import AccountsOrder from './AccountsOrder'
@ -41,28 +41,28 @@ const mapDispatchToProps = {
type Props = {
t: T,
accounts: Accounts,
accounts: Account[],
push: Function,
counterValue: string,
}
type State = {
accountsChunk: Array<Array<Account | null>>,
allTransactions: Array<Object>,
allOperations: Operation[],
selectedTime: string,
daysCount: number,
}
const ACCOUNTS_BY_LINE = 3
const ALL_TRANSACTIONS_LIMIT = 10
const ALL_OPERATIONS_LIMIT = 10
const getAllTransactions = accounts => {
const allTransactions = accounts.reduce((result, account) => {
const transactions = get(account, 'transactions', [])
const getAllOperations = accounts => {
const allOperations = accounts.reduce((result, account) => {
const operations = get(account, 'operations', [])
result = [
...result,
...transactions.map(t => ({
...operations.map(t => ({
...t,
account,
})),
@ -71,9 +71,9 @@ const getAllTransactions = accounts => {
return result
}, [])
return sortBy(allTransactions, t => t.receivedAt)
return sortBy(allOperations, t => t.receivedAt)
.reverse()
.slice(0, ALL_TRANSACTIONS_LIMIT)
.slice(0, ALL_OPERATIONS_LIMIT)
}
const getAccountsChunk = accounts => {
@ -88,7 +88,7 @@ const getAccountsChunk = accounts => {
class DashboardPage extends PureComponent<Props, State> {
state = {
accountsChunk: getAccountsChunk(this.props.accounts),
allTransactions: getAllTransactions(this.props.accounts),
allOperations: getAllOperations(this.props.accounts),
selectedTime: 'week',
daysCount: 7,
}
@ -97,7 +97,7 @@ class DashboardPage extends PureComponent<Props, State> {
if (nextProps.accounts !== this.props.accounts) {
this.setState({
accountsChunk: getAccountsChunk(nextProps.accounts),
allTransactions: getAllTransactions(nextProps.accounts),
allOperations: getAllOperations(nextProps.accounts),
})
}
}
@ -110,7 +110,7 @@ class DashboardPage extends PureComponent<Props, State> {
render() {
const { push, accounts, t, counterValue } = this.props
const { accountsChunk, allTransactions, selectedTime, daysCount } = this.state
const { accountsChunk, allOperations, selectedTime, daysCount } = this.state
const totalAccounts = accounts.length
@ -189,11 +189,11 @@ class DashboardPage extends PureComponent<Props, State> {
))}
</Box>
</Box>
<TransactionsList
<OperationsList
canShowMore
title={t('dashboard:recentActivity')}
withAccounts
transactions={allTransactions}
operations={allOperations}
onAccountClick={account => push(`/account/${account.id}`)}
/>
</Fragment>

4
src/components/IsUnlocked.js

@ -6,7 +6,7 @@ import { compose } from 'redux'
import { translate } from 'react-i18next'
import bcrypt from 'bcryptjs'
import type { Settings, Accounts, T } from 'types/common'
import type { Settings, Account, T } from 'types/common'
import get from 'lodash/get'
@ -31,7 +31,7 @@ type InputValue = {
}
type Props = {
accounts: Accounts,
accounts: Account[],
children: any,
counterValue: string,
fetchAccounts: Function,

2
src/components/TransactionsList/ConfirmationCheck.js → src/components/OperationsList/ConfirmationCheck.js

@ -36,7 +36,7 @@ const ConfirmationCheck = ({
return (
<Tooltip
render={() =>
isConfirmed ? t('transactionsList:confirmed') : t('transactionsList:notConfirmed')
isConfirmed ? t('operationsList:confirmed') : t('operationsList:notConfirmed')
}
>
<Container isConfirmed={isConfirmed}>

46
src/components/TransactionsList/index.js → src/components/OperationsList/index.js

@ -9,7 +9,7 @@ import noop from 'lodash/noop'
import isEqual from 'lodash/isEqual'
import { getIconByCoinType } from '@ledgerhq/currencies/react'
import type { Transaction as TransactionType, T } from 'types/common'
import type { Operation as OperationType, T } from 'types/common'
import IconAngleDown from 'icons/AngleDown'
import Box, { Card } from 'components/base/Box'
@ -55,7 +55,7 @@ HeaderCol.defaultProps = {
children: undefined,
}
const TransactionRaw = styled(Box).attrs({
const OperationRaw = styled(Box).attrs({
horizontal: true,
alignItems: 'center',
})`
@ -97,7 +97,7 @@ const ShowMore = styled(Box).attrs({
}
`
const Transaction = ({
const Operation = ({
t,
onAccountClick,
tx,
@ -106,14 +106,14 @@ const Transaction = ({
}: {
t: T,
onAccountClick?: Function,
tx: TransactionType,
tx: OperationType,
withAccounts?: boolean,
minConfirmations: number,
}) => {
const time = moment(tx.receivedAt)
const Icon = getIconByCoinType(get(tx, 'account.currency.coinType'))
return (
<TransactionRaw>
<OperationRaw>
<Cell size={DATE_COL_SIZE} justifyContent="space-between">
<Box>
<Day>{time.format('DD MMM')}</Day>
@ -149,7 +149,7 @@ const Transaction = ({
}}
>
<Box ff="Open Sans" fontSize={3} color="graphite">
{tx.balance > 0 ? t('transactionsList:from') : t('transactionsList:to')}
{tx.amount > 0 ? t('operationsList:from') : t('operationsList:to')}
</Box>
<Box
color="dark"
@ -167,7 +167,7 @@ const Transaction = ({
</Cell>
<Cell size={AMOUNT_COL_SIZE} justifyContent="flex-end">
<FormattedVal
val={tx.balance}
val={tx.amount}
unit={get(tx, 'account.unit')}
showCode
fontSize={4}
@ -181,11 +181,11 @@ const Transaction = ({
t={t}
/>
</Cell>
</TransactionRaw>
</OperationRaw>
)
}
Transaction.defaultProps = {
Operation.defaultProps = {
onAccountClick: noop,
withAccounts: false,
}
@ -193,14 +193,14 @@ Transaction.defaultProps = {
type Props = {
t: T,
onAccountClick?: Function,
transactions: Array<TransactionType>,
operations: OperationType[],
withAccounts?: boolean,
minConfirmations: number,
title?: string,
canShowMore: boolean,
}
class TransactionsList extends Component<Props> {
class OperationsList extends Component<Props> {
static defaultProps = {
onAccountClick: noop,
withAccounts: false,
@ -221,16 +221,16 @@ class TransactionsList extends Component<Props> {
return true
}
return !isEqual(this._hashCache, this.getHashCache(nextProps.transactions))
return !isEqual(this._hashCache, this.getHashCache(nextProps.operations))
}
getHashCache = (transactions: Array<TransactionType>) => transactions.map(t => t.hash)
getHashCache = (operations: OperationType[]) => operations.map(t => t.hash)
_hashCache = null
render() {
const {
transactions,
operations,
title,
withAccounts,
onAccountClick,
@ -239,26 +239,26 @@ class TransactionsList extends Component<Props> {
t,
} = this.props
this._hashCache = this.getHashCache(transactions)
this._hashCache = this.getHashCache(operations)
return (
<Defer>
<Card flow={1} title={title} p={0}>
<Box horizontal pt={4}>
<HeaderCol size={DATE_COL_SIZE}>{t('transactionsList:date')}</HeaderCol>
<HeaderCol size={DATE_COL_SIZE}>{t('operationsList:date')}</HeaderCol>
{withAccounts && (
<HeaderCol size={ACCOUNT_COL_SIZE}>{t('transactionsList:account')}</HeaderCol>
<HeaderCol size={ACCOUNT_COL_SIZE}>{t('operationsList:account')}</HeaderCol>
)}
<HeaderCol grow>{t('transactionsList:address')}</HeaderCol>
<HeaderCol grow>{t('operationsList:address')}</HeaderCol>
<HeaderCol size={AMOUNT_COL_SIZE} justifyContent="flex-end">
{t('transactionsList:amount')}
{t('operationsList:amount')}
</HeaderCol>
<HeaderCol size={CONFIRMATION_COL_SIZE} px={0} />
</Box>
<Box>
{transactions.map(trans => (
<Transaction
{operations.map(trans => (
<Operation
t={t}
key={`{${trans.hash}-${trans.account ? trans.account.id : ''}`}
withAccounts={withAccounts}
@ -271,7 +271,7 @@ class TransactionsList extends Component<Props> {
{canShowMore && (
<ShowMore>
<span>{t('transactionsList:showMore')}</span>
<span>{t('operationsList:showMore')}</span>
<IconAngleDown width={8} height={8} />
</ShowMore>
)}
@ -281,4 +281,4 @@ class TransactionsList extends Component<Props> {
}
}
export default translate()(TransactionsList)
export default translate()(OperationsList)

21
src/components/TransactionsList/stories.js → src/components/OperationsList/stories.js

@ -1,28 +1,37 @@
// @flow
import React from 'react'
import { getDefaultUnitByCoinType } from '@ledgerhq/currencies'
import { storiesOf } from '@storybook/react'
import { boolean } from '@storybook/addon-knobs'
import TransactionsList from 'components/TransactionsList'
import OperationsList from 'components/OperationsList'
const stories = storiesOf('Components', module)
const transactions = [
const unit = getDefaultUnitByCoinType(0)
const operations = [
{
address: '5c6ea1716520c7d6e038d36a3223faced3c',
hash: '5c6ea1716520c7d6e038d36a3223faced3c4b8f7ffb69d9fb5bd527d562fdb62',
balance: 130000000,
amount: 130000000,
receivedAt: '2018-01-09T16:03:52Z',
account: {
unit,
},
},
{
address: '27416a48caab90fab053b507b8b6b9d4',
hash: '27416a48caab90fab053b507b8b6b9d48fba75421d3bfdbae4b85f64024bc9c4',
balance: 65000000,
amount: -65000000,
receivedAt: '2018-01-09T16:02:40Z',
account: {
unit,
},
},
]
stories.add('TransactionsList', () => (
<TransactionsList transactions={transactions} canShowMore={boolean('canShowMore')} />
stories.add('OperationsList', () => (
<OperationsList operations={operations} canShowMore={boolean('canShowMore')} />
))

4
src/components/SelectAccount/index.js

@ -6,7 +6,7 @@ import { translate } from 'react-i18next'
import noop from 'lodash/noop'
import { getIconByCoinType } from '@ledgerhq/currencies/react'
import type { T, Accounts, Account } from 'types/common'
import type { T, Account } from 'types/common'
import { getVisibleAccounts } from 'reducers/accounts'
@ -42,7 +42,7 @@ const renderItem = a => {
}
type Props = {
accounts: Accounts,
accounts: Account[],
onChange?: () => Account | void,
value?: Account | null,
t: T,

2
src/components/SelectAccount/stories.js

@ -22,7 +22,7 @@ export const accounts = [...Array(20)].map(() => ({
name: chance.name(),
path: '',
rootPath: '',
transactions: [],
operations: [],
unit: getDefaultUnitByCoinType(1),
settings: {
minConfirmations: 2,

4
src/components/SideBar/index.js

@ -9,7 +9,7 @@ import { getIconByCoinType } from '@ledgerhq/currencies/react'
import { MODAL_SEND, MODAL_RECEIVE, MODAL_ADD_ACCOUNT } from 'constants'
import type { Accounts, T } from 'types/common'
import type { Account, T } from 'types/common'
import { openModal } from 'reducers/modals'
import { getVisibleAccounts } from 'reducers/accounts'
@ -52,7 +52,7 @@ const PlusBtn = styled(Tabbable).attrs({
type Props = {
t: T,
accounts: Accounts,
accounts: Account[],
openModal: Function,
}

2
src/components/base/Bar/stories.js

@ -7,6 +7,6 @@ import { storiesOf } from '@storybook/react'
import Bar from 'components/base/Bar'
const stories = storiesOf('Components', module)
const stories = storiesOf('Components/base', module)
stories.add('Bar', () => <Bar size={number('size', 1)} color="grey" />)

2
src/components/base/Box/stories.js

@ -8,7 +8,7 @@ import styled from 'styled-components'
import Box from 'components/base/Box'
const stories = storiesOf('Components/Box', module)
const stories = storiesOf('Components/base/Box', module)
const align = [
undefined,

2
src/components/base/Button/stories.js

@ -6,7 +6,7 @@ import styled from 'styled-components'
import Button from 'components/base/Button'
const stories = storiesOf('Components', module)
const stories = storiesOf('Components/base', module)
const Th = styled.th`
padding: 20px;

2
src/components/base/CheckBox/stories.js

@ -5,7 +5,7 @@ import { action } from '@storybook/addon-actions'
import CheckBox from 'components/base/CheckBox'
const stories = storiesOf('Components', module)
const stories = storiesOf('Components/base', module)
stories.add('CheckBox', () => (
<CheckBox isChecked={boolean('isChecked', false)} onChange={action('onChange')} />

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

@ -2,6 +2,7 @@
import React from 'react'
import styled from 'styled-components'
import isUndefined from 'lodash/isUndefined'
import type { Unit } from '@ledgerhq/currencies'
@ -27,6 +28,10 @@ function FormattedVal(props: Props) {
const { fiat, isPercent, alwaysShowSign, showCode, ...p } = props
let { val, unit } = props
if (isUndefined(val)) {
throw new Error('FormattedVal require a `val` prop. Received `undefined`')
}
const isNegative = val < 0
let text = ''

2
src/components/base/GrowScroll/stories.js

@ -7,7 +7,7 @@ import { boolean } from '@storybook/addon-knobs'
import Box from 'components/base/Box'
import GrowScroll from 'components/base/GrowScroll'
const stories = storiesOf('Components', module)
const stories = storiesOf('Components/base', module)
stories.add('GrowScroll', () => {
const reverseColor = boolean('reverseColor', false)

2
src/components/base/Input/stories.js

@ -5,6 +5,6 @@ import { storiesOf } from '@storybook/react'
import Input from 'components/base/Input'
const stories = storiesOf('Components', module)
const stories = storiesOf('Components/base', module)
stories.add('Input', () => <Input placeholder="Foo bar" />)

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

@ -8,7 +8,7 @@ import { getDefaultUnitByCoinType } from '@ledgerhq/currencies'
import InputCurrency from 'components/base/InputCurrency'
const stories = storiesOf('Components', module)
const stories = storiesOf('Components/base', module)
const unit = getDefaultUnitByCoinType(1)

2
src/components/base/Modal/stories.js

@ -8,7 +8,7 @@ import { Modal, ModalBody, ModalTitle, ModalContent, ModalFooter } from 'compone
import Box from 'components/base/Box'
import Button from 'components/base/Button'
const stories = storiesOf('Components', module)
const stories = storiesOf('Components/base', module)
stories.add('Modal', () => {
const isOpened = boolean('isOpened', true)

2
src/components/base/NewChart/stories.js

@ -10,7 +10,7 @@ import { color } from '@storybook/addon-knobs/react'
import Chart from 'components/base/NewChart'
const stories = storiesOf('Components', module)
const stories = storiesOf('Components/base', module)
const data = generateRandomData(365)
const unit = getDefaultUnitByCoinType(0)

2
src/components/base/Pills/stories.js

@ -5,7 +5,7 @@ import { storiesOf } from '@storybook/react'
import Pills from 'components/base/Pills'
const stories = storiesOf('Components', module)
const stories = storiesOf('Components/base', module)
type State = {
key: string,

2
src/components/base/QRCode/stories.js

@ -7,6 +7,6 @@ import { text, number } from '@storybook/addon-knobs'
import QRCode from 'components/base/QRCode'
const stories = storiesOf('Components', module)
const stories = storiesOf('Components/base', module)
stories.add('QRCode', () => <QRCode data={text('data', 'sample')} size={number('size', 200)} />)

2
src/components/base/Radio/stories.js

@ -5,7 +5,7 @@ import { boolean } from '@storybook/addon-knobs'
import Radio from 'components/base/Radio'
const stories = storiesOf('Components', module)
const stories = storiesOf('Components/base', module)
stories.add('Radio', () => (
<Radio isChecked={boolean('checked', false)} onChange={action('onChange')} />

2
src/components/base/Select/stories.js

@ -7,7 +7,7 @@ import Box from 'components/base/Box'
import Select from 'components/base/Select'
import Text from 'components/base/Text'
const stories = storiesOf('Components/Select', module)
const stories = storiesOf('Components/base/Select', module)
const itemsChessPlayers = [
{ key: 'aleksandr-grichtchouk', name: 'Aleksandr Grichtchouk' },

2
src/components/base/Tabs/stories.js

@ -6,7 +6,7 @@ import { storiesOf } from '@storybook/react'
import Tabs from 'components/base/Tabs'
const stories = storiesOf('Components', module)
const stories = storiesOf('Components/base', module)
stories.add('Tabs', () => (
<Tabs

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

@ -10,7 +10,7 @@ import Text from 'components/base/Text'
import { fontFamilies, fontSizes } from 'styles/theme'
const stories = storiesOf('Common/Text', module)
const stories = storiesOf('Common', module)
const Title = ({ children }: { children: string }) => (
<Text style={{ fontFamily: 'monospace' }} fontSize={5}>
@ -56,7 +56,7 @@ const FontSizes = () => (
</Box>
)
stories.add('all fonts styles', () => (
stories.add('Text styles', () => (
<Box flow={4}>
<FontStyles txt={text('text', 'The quick brown fox jumps over the lazy dog')} />
<FontSizes />

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

@ -5,6 +5,6 @@ import { storiesOf } from '@storybook/react'
import Tooltip from 'components/base/Tooltip'
const stories = storiesOf('Components', module)
const stories = storiesOf('Components/base', module)
stories.add('Tooltip', () => <Tooltip render={() => <div>Oyo!</div>}>Hover me!</Tooltip>)

6
src/components/modals/AddAccount/ImportAccounts.js

@ -3,7 +3,7 @@
import React, { PureComponent } from 'react'
import { translate } from 'react-i18next'
import type { T } from 'types/common'
import type { T, Account } from 'types/common'
import Box from 'components/base/Box'
import Button from 'components/base/Button'
@ -13,7 +13,7 @@ import Input from 'components/base/Input'
type Props = {
t: T,
accounts: Array<Object>,
accounts: Account[],
onImportAccounts: Function,
}
@ -110,7 +110,7 @@ class ImportAccounts extends PureComponent<Props, State> {
val={account.balance}
/>
</Box>
<Box>Transactions: {account.transactions.length}</Box>
<Box>Operations: {account.operations.length}</Box>
</Box>
</Box>
)

4
src/components/modals/AddAccount/RestoreAccounts.js

@ -7,14 +7,14 @@ import Box from 'components/base/Box'
import Button from 'components/base/Button'
import Text from 'components/base/Text'
import type { Accounts } from 'types/common'
import type { Account } from 'types/common'
const Container = styled(Box)`
border: 1px solid ${p => p.theme.colors.alertRed};
`
type Props = {
archivedAccounts: Accounts,
archivedAccounts: Account[],
updateAccount: Function,
}

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

@ -12,7 +12,7 @@ import type { Currency } from '@ledgerhq/currencies'
import { MODAL_ADD_ACCOUNT } from 'constants'
import type { Accounts, Device, T } from 'types/common'
import type { Account, Device, T } from 'types/common'
import { closeModal } from 'reducers/modals'
import { canCreateAccount, getAccounts, getArchivedAccounts } from 'reducers/accounts'
@ -88,7 +88,7 @@ const Steps = {
val={progress.balance || 0}
/>
</Box>
<Box>Transactions: {progress.transactions || 0}</Box>
<Box>Operations: {progress.operations || 0}</Box>
{progress.success && <Box>Finish ! Next account in progress...</Box>}
</Box>
)}
@ -96,8 +96,8 @@ const Steps = {
),
listAccounts: (props: Object) => {
const { accounts, archivedAccounts } = props
const emptyAccounts = accounts.filter(account => account.transactions.length === 0)
const existingAccounts = accounts.filter(account => account.transactions.length > 0)
const emptyAccounts = accounts.filter(account => account.operations.length === 0)
const existingAccounts = accounts.filter(account => account.operations.length > 0)
const canCreateAccount = props.canCreateAccount && emptyAccounts.length === 1
const newAccount = emptyAccounts[0]
return (
@ -117,9 +117,9 @@ const Steps = {
type Step = 'chooseCurrency' | 'connectDevice' | 'inProgress' | 'listAccounts'
type Props = {
accounts: Accounts,
accounts: Account[],
addAccount: Function,
archivedAccounts: Accounts,
archivedAccounts: Account[],
canCreateAccount: boolean,
closeModal: Function,
counterValues: Object,
@ -130,7 +130,7 @@ type Props = {
}
type State = {
accounts: Accounts,
accounts: Account[],
currency: Currency | null,
fetchingCounterValues: boolean,
progress: null | Object,

8
src/components/modals/SettingsAccount.js

@ -50,8 +50,8 @@ const defaultState = {
nameHovered: false,
}
function hasNoTransactions(account: Account) {
return get(account, 'transactions.length', 0) === 0
function hasNoOperations(account: Account) {
return get(account, 'operations.length', 0) === 0
}
class SettingsAccount extends PureComponent<Props, State> {
@ -133,7 +133,7 @@ class SettingsAccount extends PureComponent<Props, State> {
handleArchiveAccount = (account: Account) => () => {
const { push, closeModal, updateAccount, removeAccount } = this.props
const shouldRemove = hasNoTransactions(account)
const shouldRemove = hasNoOperations(account)
if (shouldRemove) {
removeAccount(account)
@ -212,7 +212,7 @@ class SettingsAccount extends PureComponent<Props, State> {
</ModalContent>
<ModalFooter horizontal justify="flex-end" flow={2}>
<Button onClick={this.handleArchiveAccount(account)}>
{hasNoTransactions(account) ? 'Remove account' : 'Archive account'}
{hasNoOperations(account) ? 'Remove account' : 'Archive account'}
</Button>
<Button primary>Go to account</Button>
</ModalFooter>

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

@ -69,7 +69,7 @@ describe('helpers > balance', () => {
])
})
test('should work if interval dont contain transactions', () => {
test('should work if interval dont contain operations', () => {
const account = {
coinType: 0,
balanceByDay: {

6
src/helpers/balance.js

@ -8,7 +8,7 @@ import first from 'lodash/first'
import isUndefined from 'lodash/isUndefined'
import last from 'lodash/last'
import type { Accounts, Account } from 'types/common'
import type { Account } from 'types/common'
type DateInterval = {
start: string,
@ -21,7 +21,7 @@ type BalanceHistoryDay = {
}
type CalculateBalance = {
accounts: Accounts,
accounts: Account[],
counterValue: string,
counterValues: Object,
daysCount: number,
@ -100,7 +100,7 @@ export function getBalanceHistoryForAccounts({
interval,
}: {
counterValue: string,
accounts: Accounts,
accounts: Account[],
counterValues: Object,
interval: DateInterval,
}): Array<BalanceHistoryDay> {

47
src/helpers/btc.js

@ -7,7 +7,7 @@ import groupBy from 'lodash/groupBy'
import noop from 'lodash/noop'
import uniqBy from 'lodash/uniqBy'
import type { Transactions } from 'types/common'
import type { Operation } from 'types/common'
const GAP_LIMIT_ADDRESSES = 20
@ -22,7 +22,7 @@ export const networks = [
},
]
export function computeTransaction(addresses: Array<string>) {
export function computeOperation(addresses: Array<string>) {
return (t: Object) => {
const outputVal = t.outputs
.filter(o => addresses.includes(o.address))
@ -30,10 +30,11 @@ export function computeTransaction(addresses: Array<string>) {
const inputVal = t.inputs
.filter(i => addresses.includes(i.address))
.reduce((acc, cur) => acc + cur.value, 0)
const balance = outputVal - inputVal
const amount = outputVal - inputVal
return {
address: t.balance > 0 ? t.inputs[0].address : t.outputs[0].address,
balance,
id: t.hash,
address: t.amount > 0 ? t.inputs[0].address : t.outputs[0].address,
amount,
confirmations: t.confirmations,
hash: t.hash,
receivedAt: t.received_at,
@ -41,8 +42,8 @@ export function computeTransaction(addresses: Array<string>) {
}
}
export function getBalanceByDay(transactions: Transactions) {
const txsByDate = groupBy(transactions, tx => {
export function getBalanceByDay(operations: Operation[]) {
const txsByDate = groupBy(operations, tx => {
const [date] = new Date(tx.receivedAt).toISOString().split('T')
return date
})
@ -55,7 +56,7 @@ export function getBalanceByDay(transactions: Transactions) {
const txs = txsByDate[k]
balance += txs.reduce((r, v) => {
r += v.balance
r += v.amount
return r
}, 0)
@ -91,7 +92,7 @@ export async function getAccount({
const script = segwit ? parseInt(network.scriptHash, 10) : parseInt(network.pubKeyHash, 10)
let balance = 0
let transactions = []
let operations = []
let lastAddress = null
const pubKeyToSegwitAddress = (pubKey, scriptVersion) => {
@ -149,31 +150,31 @@ export async function getAccount({
let txs = []
const transactionsOpts = { coin_type: coinType }
const operationsOpts = { coin_type: coinType }
try {
txs = await ledger.getTransactions(listAddresses, transactionsOpts)
txs = await ledger.getTransactions(listAddresses, operationsOpts)
txs = txs.filter(t => !allTxsHash.includes(t.hash)).reverse()
} catch (e) {
console.log('getTransactions', e) // eslint-disable-line no-console
console.log('getOperations', e) // eslint-disable-line no-console
}
const hasTransactions = txs.length > 0
const hasOperations = txs.length > 0
if (hasTransactions) {
const newTransactions = txs.map(computeTransaction(allAddresses))
const txHashs = transactions.map(t => t.hash)
if (hasOperations) {
const newOperations = txs.map(computeOperation(allAddresses))
const txHashs = operations.map(t => t.hash)
balance = newTransactions
balance = newOperations
.filter(t => !txHashs.includes(t.hash))
.reduce((result, v) => result + v.balance, balance)
.reduce((result, v) => result + v.amount, balance)
lastAddress = getLastAddress(addresses, txs[0])
transactions = uniqBy([...transactions, ...newTransactions], t => t.hash)
operations = uniqBy([...operations, ...newOperations], t => t.hash)
onProgress({
balance,
transactions: transactions.length,
operations: operations.length,
})
return nextPath(index + (GAP_LIMIT_ADDRESSES - 1))
@ -189,11 +190,11 @@ export async function getAccount({
return {
...nextAddress,
addresses: transactions.length > 0 ? allAddresses : [],
addresses: operations.length > 0 ? allAddresses : [],
balance,
balanceByDay: getBalanceByDay(transactions),
balanceByDay: getBalanceByDay(operations),
rootPath,
transactions,
operations,
}
})

4
src/internals/accounts/sync.js

@ -4,9 +4,9 @@ import { getAccount, getHDNode, networks } from 'helpers/btc'
const network = networks[1]
function syncAccount({ id, transactions, ...currentAccount }) {
function syncAccount({ id, operations, ...currentAccount }) {
const hdnode = getHDNode({ xpub58: id, network })
const allTxsHash = transactions.map(t => t.hash)
const allTxsHash = operations.map(t => t.hash)
return getAccount({ hdnode, network, allTxsHash, segwit: true, ...currentAccount }).then(
account => ({
id,

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

@ -154,11 +154,11 @@ export default async ({
network,
rootPath: path,
segwit,
onProgress: ({ transactions, ...progress }) =>
transactions > 0 && onProgress({ account: currentAccount, transactions, ...progress }),
onProgress: ({ operations, ...progress }) =>
operations > 0 && onProgress({ account: currentAccount, operations, ...progress }),
})
const hasTransactions = account.transactions.length > 0
const hasOperations = account.operations.length > 0
accounts.push({
id: xpub58,
@ -166,7 +166,7 @@ export default async ({
...account,
})
if (hasTransactions) {
if (hasOperations) {
onProgress({
success: true,
})

33
src/reducers/accounts.js

@ -10,18 +10,17 @@ import defaultsDeep from 'lodash/defaultsDeep'
import { getDefaultUnitByCoinType, getCurrencyByCoinType } from '@ledgerhq/currencies'
import type { State } from 'reducers'
import type { Account, Accounts } from 'types/common'
export type AccountsState = Accounts
import type { Account } from 'types/common'
export type AccountsState = Account[]
const state: AccountsState = []
function orderAccountsTransactions(account: Account) {
const { transactions } = account
transactions.sort((a, b) => new Date(b.receivedAt) - new Date(a.receivedAt))
function orderAccountsOperations(account: Account) {
const { operations } = account
operations.sort((a, b) => new Date(b.receivedAt) - new Date(a.receivedAt))
return {
...account,
transactions,
operations,
}
}
@ -36,13 +35,13 @@ function applyDefaults(account) {
const handlers: Object = {
SET_ACCOUNTS: (
state: AccountsState,
{ payload: accounts }: { payload: Accounts },
{ payload: accounts }: { payload: Account[] },
): AccountsState => accounts.map(applyDefaults),
ADD_ACCOUNT: (
state: AccountsState,
{ payload: account }: { payload: Account },
): AccountsState => [...state, orderAccountsTransactions(account)],
): AccountsState => [...state, orderAccountsOperations(account)],
UPDATE_ACCOUNT: (
state: AccountsState,
@ -58,7 +57,7 @@ const handlers: Object = {
...account,
}
return orderAccountsTransactions(updatedAccount)
return orderAccountsOperations(updatedAccount)
}),
REMOVE_ACCOUNT: (state: AccountsState, { payload: account }: { payload: Account }) =>
@ -78,15 +77,15 @@ export function getTotalBalance(state: { accounts: AccountsState }) {
)
}
export function getAccounts(state: { accounts: AccountsState }): Array<Account> {
export function getAccounts(state: { accounts: AccountsState }): Account[] {
return state.accounts
}
export function getArchivedAccounts(state: { accounts: AccountsState }): Array<Account> {
export function getArchivedAccounts(state: { accounts: AccountsState }): Account[] {
return state.accounts.filter(acc => acc.archived === true)
}
export function getVisibleAccounts(state: { accounts: AccountsState }): Array<Account> {
export function getVisibleAccounts(state: { accounts: AccountsState }): Account[] {
return getAccounts(state).filter(account => account.archived !== true)
}
@ -96,7 +95,7 @@ export function getAccountById(state: { accounts: AccountsState }, id: string):
}
export function canCreateAccount(state: State): boolean {
return every(getAccounts(state), a => get(a, 'transactions.length', 0) > 0)
return every(getAccounts(state), a => get(a, 'operations.length', 0) > 0)
}
export function serializeAccounts(accounts: Array<Object>) {
@ -119,7 +118,7 @@ export function serializeAccounts(accounts: Array<Object>) {
return {
...a,
transactions: account.transactions.map(t => ({
operations: account.operations.map(t => ({
...t,
account: a,
})),
@ -127,7 +126,7 @@ export function serializeAccounts(accounts: Array<Object>) {
})
}
export function deserializeAccounts(accounts: Accounts) {
export function deserializeAccounts(accounts: Account[]) {
return accounts.map(account => ({
id: account.id,
address: account.address,
@ -139,7 +138,7 @@ export function deserializeAccounts(accounts: Accounts) {
name: account.name,
path: account.path,
rootPath: account.rootPath,
transactions: account.transactions.map(({ account, ...t }) => t),
operations: account.operations.map(({ account, ...t }) => t),
unit: account.unit,
settings: account.settings,
}))

16
src/renderer/events.js

@ -5,7 +5,7 @@ import objectPath from 'object-path'
import debug from 'debug'
import { getDefaultUnitByCoinType } from '@ledgerhq/currencies'
import type { Accounts } from 'types/common'
import type { Account } from 'types/common'
import { CHECK_UPDATE_DELAY, SYNC_ACCOUNT_DELAY, SYNC_COUNTER_VALUES_DELAY } from 'constants'
@ -52,19 +52,19 @@ export function sendSyncEvent(channel: string, msgType: string, data: any): any
})
}
export function startSyncAccounts(accounts: Accounts) {
export function startSyncAccounts(accounts: Account[]) {
d.sync('Sync accounts - start')
syncAccountsInProgress = true
sendEvent('accounts', 'sync.all', {
accounts: accounts.map(account => {
const { id, coinType, rootPath, addresses, index, transactions } = account
const { id, coinType, rootPath, addresses, index, operations } = account
return {
id,
coinType,
allAddresses: addresses,
currentIndex: index,
rootPath,
transactions,
operations,
}
}),
})
@ -76,7 +76,7 @@ export function stopSyncAccounts() {
clearTimeout(syncAccountsTimeout)
}
export function startSyncCounterValues(counterValue: string, accounts: Accounts) {
export function startSyncCounterValues(counterValue: string, accounts: Account[]) {
d.sync('Sync counterValues - start')
sendEvent('msg', 'counterValues.sync', {
@ -114,9 +114,9 @@ export default ({ store, locked }: { store: Object, locked: boolean }) => {
return
}
const { name, balance, balanceByDay, transactions } = existingAccount
const { name, balance, balanceByDay, operations } = existingAccount
if (account.transactions.length > 0) {
if (account.operations.length > 0) {
d.sync(`Update account - ${name}`)
const updatedAccount = {
...account,
@ -126,7 +126,7 @@ export default ({ store, locked }: { store: Object, locked: boolean }) => {
return result
}, {}),
index: account.index || existingAccount.index,
transactions: [...transactions, ...account.transactions],
operations: [...operations, ...account.operations],
}
store.dispatch(updateAccount(updatedAccount))
}

2
src/renderer/i18n/instanciate.js

@ -14,7 +14,7 @@ const commonConfig = {
'settings',
'sidebar',
'time',
'transactionsList',
'operationsList',
'update',
],
fallbackLng: 'en',

2
src/renderer/i18n/storybook.js

@ -13,7 +13,7 @@ const resources = {
settings: require('../../../static/i18n/en/settings.yml'),
sidebar: require('../../../static/i18n/en/sidebar.yml'),
time: require('../../../static/i18n/en/time.yml'),
transactionsList: require('../../../static/i18n/en/transactionsList.yml'),
operationsList: require('../../../static/i18n/en/operationsList.yml'),
update: require('../../../static/i18n/en/update.yml'),
}

4
src/stories/currencies.stories.js

@ -7,11 +7,11 @@ import { getIconByCoinType } from '@ledgerhq/currencies/react'
import type { Currency } from '@ledgerhq/currencies'
const stories = storiesOf('Common/Currencies', module)
const stories = storiesOf('Common', module)
const currencies: Array<Currency> = listCurrencies()
stories.add('currencies list', () => (
stories.add('Currencies', () => (
<div>
<table border="1">
<thead>

13
src/types/common.js

@ -10,19 +10,18 @@ export type Device = {
export type Devices = Array<Device>
// -------------------- Transactions
// -------------------- Operations
export type Transaction = {
export type Operation = {
id: string,
account?: Account,
address: string,
balance: number,
amount: number,
hash: string,
receivedAt: string,
confirmations: number,
}
export type Transactions = Array<Transaction>
// -------------------- Accounts
export type AccountSettings = {
@ -42,13 +41,11 @@ export type Account = {
name: string,
path: string,
rootPath: string,
transactions: Transactions,
operations: Operation[],
unit: Unit,
settings: AccountSettings,
}
export type Accounts = Array<Account>
// -------------------- Settings
export type SettingsProfile = {

0
static/i18n/en/transactionsList.yml → static/i18n/en/operationsList.yml

0
static/i18n/fr/transactionsList.yml → static/i18n/fr/operationsList.yml

Loading…
Cancel
Save