Browse Source

rework Currencies settings to fix confirmations & rm unused settings

master
Gaëtan Renaudeau 7 years ago
parent
commit
366ee9e8b7
  1. 4
      src/actions/settings.js
  2. 3
      src/components/IsUnlocked.js
  3. 3
      src/components/SettingsPage/index.js
  4. 70
      src/components/SettingsPage/sections/Currencies.js
  5. 3
      src/components/SettingsPage/sections/Display.js
  6. 5
      src/components/SettingsPage/sections/Profile.js
  7. 52
      src/helpers/SettingsDefaults.js
  8. 2
      src/helpers/countervalues.js
  9. 55
      src/reducers/settings.js
  10. 24
      src/types/common.js

4
src/actions/settings.js

@ -1,10 +1,10 @@
// @flow // @flow
import type { Dispatch } from 'redux' import type { Dispatch } from 'redux'
import type { Settings } from 'types/common' import type { SettingsState as Settings } from 'reducers/settings'
import type { Currency } from '@ledgerhq/live-common/lib/types' import type { Currency } from '@ledgerhq/live-common/lib/types'
export type SaveSettings = Settings => { type: string, payload: Settings } export type SaveSettings = Settings => { type: string, payload: $Shape<Settings> }
export const saveSettings: SaveSettings = payload => ({ export const saveSettings: SaveSettings = payload => ({
type: 'DB:SAVE_SETTINGS', type: 'DB:SAVE_SETTINGS',
payload, payload,

3
src/components/IsUnlocked.js

@ -7,7 +7,8 @@ import { compose } from 'redux'
import styled from 'styled-components' import styled from 'styled-components'
import { translate } from 'react-i18next' import { translate } from 'react-i18next'
import type { Settings, T } from 'types/common' import type { SettingsState as Settings } from 'reducers/settings'
import type { T } from 'types/common'
import IconLockScreen from 'icons/LockScreen' import IconLockScreen from 'icons/LockScreen'
import { ErrorMessageInput } from 'components/base/Input' import { ErrorMessageInput } from 'components/base/Input'

3
src/components/SettingsPage/index.js

@ -6,8 +6,9 @@ import { connect } from 'react-redux'
import { translate } from 'react-i18next' import { translate } from 'react-i18next'
import { Switch, Route } from 'react-router' import { Switch, Route } from 'react-router'
import type { SettingsState as Settings } from 'reducers/settings'
import type { RouterHistory, Match, Location } from 'react-router' import type { RouterHistory, Match, Location } from 'react-router'
import type { Settings, T } from 'types/common' import type { T } from 'types/common'
import type { SaveSettings } from 'actions/settings' import type { SaveSettings } from 'actions/settings'
import { saveSettings } from 'actions/settings' import { saveSettings } from 'actions/settings'

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

@ -11,10 +11,12 @@ import { connect } from 'react-redux'
import { createStructuredSelector } from 'reselect' import { createStructuredSelector } from 'reselect'
import type { CryptoCurrency, Currency } from '@ledgerhq/live-common/lib/types' import type { CryptoCurrency, Currency } from '@ledgerhq/live-common/lib/types'
import type { Settings, CurrencySettings, T } from 'types/common' import type { T } from 'types/common'
import { counterValueCurrencySelector } from 'reducers/settings' import { counterValueCurrencySelector, currencySettingsLocaleSelector } from 'reducers/settings'
import type { SettingsState } from 'reducers/settings'
import { currenciesSelector } from 'reducers/accounts' import { currenciesSelector } from 'reducers/accounts'
import { currencySettingsDefaults } from 'helpers/SettingsDefaults'
import SelectCurrency from 'components/SelectCurrency' import SelectCurrency from 'components/SelectCurrency'
import StepperNumber from 'components/base/StepperNumber' import StepperNumber from 'components/base/StepperNumber'
@ -29,30 +31,11 @@ import {
SettingsSectionRow as Row, SettingsSectionRow as Row,
} from '../SettingsSection' } from '../SettingsSection'
// .
// /!\ Please note that this will likely not be like that in the future.
// I guess that all currencies should have those settings inside them
// instead of using same default for all.
//
const CURRENCY_DEFAULTS_SETTINGS: CurrencySettings = {
confirmationsToSpend: 10,
minConfirmationsToSpend: 10,
maxConfirmationsToSpend: 50,
confirmationsNb: 10,
minConfirmationsNb: 10,
maxConfirmationsNb: 50,
transactionFees: 10,
exchange: '',
}
type Props = { type Props = {
counterValueCurrency: Currency, counterValueCurrency: Currency,
currencies: CryptoCurrency[], currencies: CryptoCurrency[],
settings: Settings, settings: SettingsState,
saveSettings: Function, saveSettings: ($Shape<SettingsState>) => void,
t: T, t: T,
} }
@ -70,12 +53,6 @@ class TabCurrencies extends PureComponent<Props, State> {
currency: this.props.currencies[0], currency: this.props.currencies[0],
} }
getCurrencySettings() {
const { settings } = this.props
const { currency } = this.state
return settings.currenciesSettings[currency.id]
}
handleChangeCurrency = (currency: CryptoCurrency) => this.setState({ currency }) handleChangeCurrency = (currency: CryptoCurrency) => this.setState({ currency })
handleChangeConfirmationsToSpend = (nb: number) => handleChangeConfirmationsToSpend = (nb: number) =>
@ -90,13 +67,12 @@ class TabCurrencies extends PureComponent<Props, State> {
// FIXME this really should be a dedicated action // FIXME this really should be a dedicated action
const { settings, saveSettings } = this.props const { settings, saveSettings } = this.props
const { currency } = this.state const { currency } = this.state
const currencySettings = this.getCurrencySettings() const currencySettings = settings.currenciesSettings[currency.id]
let newCurrenciesSettings = [] let newCurrenciesSettings = []
if (!currencySettings) { if (!currencySettings) {
newCurrenciesSettings = { newCurrenciesSettings = {
...settings.currenciesSettings, ...settings.currenciesSettings,
[currency.id]: { [currency.id]: {
...CURRENCY_DEFAULTS_SETTINGS,
[key]: val, [key]: val,
}, },
} }
@ -115,9 +91,9 @@ class TabCurrencies extends PureComponent<Props, State> {
render() { render() {
const { currency } = this.state const { currency } = this.state
if (!currency) return null // this case means there is no accounts if (!currency) return null // this case means there is no accounts
const { t, currencies, counterValueCurrency } = this.props const { t, currencies, counterValueCurrency, settings } = this.props
const { confirmationsToSpend, confirmationsNb, exchange } = const { confirmationsNb, exchange } = currencySettingsLocaleSelector(settings, currency)
this.getCurrencySettings() || CURRENCY_DEFAULTS_SETTINGS const defaults = currencySettingsDefaults(currency)
return ( return (
<Section key={currency.id}> <Section key={currency.id}>
<Header <Header
@ -145,38 +121,20 @@ class TabCurrencies extends PureComponent<Props, State> {
style={{ minWidth: 200 }} style={{ minWidth: 200 }}
/> />
</Row> </Row>
<Row {defaults.confirmationsNb ? (
title={t('settings:currencies.confirmationsToSpend')}
desc={t('settings:currencies.confirmationsToSpendDesc')}
>
<StepperNumber
min={10}
max={40}
step={1}
onChange={this.handleChangeConfirmationsToSpend}
value={confirmationsToSpend}
/>
</Row>
<Row <Row
title={t('settings:currencies.confirmationsNb')} title={t('settings:currencies.confirmationsNb')}
desc={t('settings:currencies.confirmationsNbDesc')} desc={t('settings:currencies.confirmationsNbDesc')}
> >
<StepperNumber <StepperNumber
min={10} min={defaults.confirmationsNb.min}
max={40} max={defaults.confirmationsNb.max}
step={1} step={1}
onChange={this.handleChangeConfirmationsNb} onChange={this.handleChangeConfirmationsNb}
value={confirmationsNb} value={confirmationsNb}
/> />
</Row> </Row>
<Row ) : null}
title={t('settings:currencies.transactionsFees')}
desc={t('settings:currencies.transactionsFeesDesc')}
/>
<Row
title={t('settings:currencies.explorer')}
desc={t('settings:currencies.explorerDesc')}
/>
</Body> </Body>
</Section> </Section>
) )

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

@ -4,7 +4,8 @@ import React, { PureComponent } from 'react'
import moment from 'moment' import moment from 'moment'
import { listFiatCurrencies } from '@ledgerhq/live-common/lib/helpers/currencies' import { listFiatCurrencies } from '@ledgerhq/live-common/lib/helpers/currencies'
import type { Settings, T } from 'types/common' import type { SettingsState as Settings } from 'reducers/settings'
import type { T } from 'types/common'
import Select from 'components/base/Select' import Select from 'components/base/Select'
import RadioGroup from 'components/base/RadioGroup' import RadioGroup from 'components/base/RadioGroup'

5
src/components/SettingsPage/sections/Profile.js

@ -5,7 +5,8 @@ import { connect } from 'react-redux'
import { remote } from 'electron' import { remote } from 'electron'
import bcrypt from 'bcryptjs' import bcrypt from 'bcryptjs'
import type { Settings, T } from 'types/common' import type { SettingsState } from 'reducers/settings'
import type { T } from 'types/common'
import { unlock } from 'reducers/application' import { unlock } from 'reducers/application'
import db, { setEncryptionKey } from 'helpers/db' import db, { setEncryptionKey } from 'helpers/db'
@ -31,7 +32,7 @@ const mapDispatchToProps = {
type Props = { type Props = {
t: T, t: T,
settings: Settings, settings: SettingsState,
unlock: Function, unlock: Function,
saveSettings: Function, saveSettings: Function,
} }

52
src/helpers/SettingsDefaults.js

@ -0,0 +1,52 @@
// @flow
import type { CryptoCurrency } from '@ledgerhq/live-common/lib/types'
type ConfirmationDefaults = {
confirmationsNb: ?{
min: number,
def: number,
max: number,
},
}
// This is approximated to be a 30mn confirmation in number of blocks on blockchains
// to disable the confirmations feature simply set 0.
const confirmationsNbPerCoin = {
bitcoin: 2,
ethereum: 120,
ripple: 0,
bitcoin_cash: 2,
litecoin: 6,
dash: 12,
ethereum_classic: 120,
qtum: 15,
zcash: 12,
bitcoin_gold: 2,
stratis: 12, // FIXME can't grab the block time info anywhere...
dogecoin: 30,
hshare: 12, // FIXME can't grab the block time info anywhere...
komodo: 30,
pivx: 12, // FIXME can't grab the block time info anywhere...
zencash: 12,
vertcoin: 12,
peercoin: 4,
viacoin: 75,
stealthcoin: 12, // FIXME can't grab the block time info anywhere...
digibyte: 30,
bitcoin_testnet: 2,
ethereum_testnet: 120,
}
export const currencySettingsDefaults = (currency: CryptoCurrency): ConfirmationDefaults => {
const confirmationsNbDef = confirmationsNbPerCoin[currency.id]
return {
confirmationsNb: confirmationsNbDef
? {
min: 1,
def: confirmationsNbDef,
max: 100,
}
: null,
}
}

2
src/helpers/countervalues.js

@ -14,7 +14,7 @@ const pairsSelector = createSelector(
currencies.map(currency => ({ currencies.map(currency => ({
from: currency, from: currency,
to: counterValueCurrency, to: counterValueCurrency,
exchange: currencySettingsSelector(state, currency).exchange, exchange: currencySettingsSelector(state, { currency }).exchange,
})), })),
) )

55
src/reducers/settings.js

@ -10,8 +10,9 @@ import languages from 'config/languages'
import { createSelector } from 'reselect' import { createSelector } from 'reselect'
import type { InputSelector as Selector } from 'reselect' import type { InputSelector as Selector } from 'reselect'
import type { CryptoCurrency, Currency, Account } from '@ledgerhq/live-common/lib/types' import type { CryptoCurrency, Currency, Account } from '@ledgerhq/live-common/lib/types'
import { currencySettingsDefaults } from 'helpers/SettingsDefaults'
import type { Settings, CurrencySettings } from 'types/common' import type { CurrencySettings } from 'types/common'
import type { State } from 'reducers' import type { State } from 'reducers'
export type SettingsState = { export type SettingsState = {
@ -24,7 +25,7 @@ export type SettingsState = {
isEnabled: boolean, isEnabled: boolean,
value: string, value: string,
}, },
marketIndicator: string, marketIndicator: 'eastern' | 'western',
currenciesSettings: { currenciesSettings: {
[currencyId: string]: CurrencySettings, [currencyId: string]: CurrencySettings,
}, },
@ -42,21 +43,15 @@ if (!languages.includes(language)) {
region = 'US' region = 'US'
} }
const CURRENCY_DEFAULTS_SETTINGS: CurrencySettings = { const defaultsForCurrency: CryptoCurrency => CurrencySettings = crypto => {
confirmationsToSpend: 10, const defaults = currencySettingsDefaults(crypto)
minConfirmationsToSpend: 10, // FIXME DROP return {
maxConfirmationsToSpend: 50, // FIXME DROP confirmationsNb: defaults.confirmationsNb ? defaults.confirmationsNb.def : 0,
confirmationsNb: 10,
minConfirmationsNb: 10, // FIXME DROP
maxConfirmationsNb: 50, // FIXME DROP
transactionFees: 10,
exchange: '', exchange: '',
}
} }
const state: SettingsState = { const INITIAL_STATE: SettingsState = {
hasCompletedOnboarding: false, hasCompletedOnboarding: false,
counterValue: 'USD', counterValue: 'USD',
language, language,
@ -105,11 +100,17 @@ const handlers: Object = {
} }
return copy return copy
}, },
SAVE_SETTINGS: (state: SettingsState, { payload: settings }: { payload: Settings }) => ({ SAVE_SETTINGS: (
state: SettingsState,
{ payload: settings }: { payload: $Shape<SettingsState> },
) => ({
...state, ...state,
...settings, ...settings,
}), }),
FETCH_SETTINGS: (state: SettingsState, { payload: settings }: { payload: Settings }) => ({ FETCH_SETTINGS: (
state: SettingsState,
{ payload: settings }: { payload: $Shape<SettingsState> },
) => ({
...state, ...state,
...settings, ...settings,
loaded: true, loaded: true,
@ -152,18 +153,26 @@ export const getOrderAccounts = (state: State) => state.settings.orderAccounts
export const areSettingsLoaded = (state: State) => state.settings.loaded export const areSettingsLoaded = (state: State) => state.settings.loaded
export const currencySettingsSelector = ( export const currencySettingsLocaleSelector = (
state: State, settings: SettingsState,
currency: CryptoCurrency, currency: Currency,
): CurrencySettings => { ): CurrencySettings => {
const currencySettings = state.settings.currenciesSettings[currency.id] const currencySettings = settings.currenciesSettings[currency.id]
return { ...CURRENCY_DEFAULTS_SETTINGS, ...currencySettings } return { ...defaultsForCurrency(currency), ...currencySettings }
} }
type CSS = Selector<*, { currency: CryptoCurrency }, CurrencySettings>
export const currencySettingsSelector: CSS = createSelector(
storeSelector,
(_, { currency }) => currency,
currencySettingsLocaleSelector,
)
export const currencySettingsForAccountSelector = ( export const currencySettingsForAccountSelector = (
state: State, state: State,
{ account }: { account: Account }, { account }: { account: Account },
) => currencySettingsSelector(state, account.currency) ) => currencySettingsSelector(state, { currency: account.currency })
type ESFAS = Selector<*, { account: Account }, string> type ESFAS = Selector<*, { account: Account }, string>
export const exchangeSettingsForAccountSelector: ESFAS = createSelector( export const exchangeSettingsForAccountSelector: ESFAS = createSelector(
@ -173,4 +182,4 @@ export const exchangeSettingsForAccountSelector: ESFAS = createSelector(
export const marketIndicatorSelector = (state: State) => state.settings.marketIndicator export const marketIndicatorSelector = (state: State) => state.settings.marketIndicator
export default handleActions(handlers, state) export default handleActions(handlers, INITIAL_STATE)

24
src/types/common.js

@ -11,16 +11,7 @@ export type Device = {
// -------------------- Settings // -------------------- Settings
export type CurrencySettings = { export type CurrencySettings = {
confirmationsToSpend: number,
minConfirmationsToSpend: number,
maxConfirmationsToSpend: number,
confirmationsNb: number, confirmationsNb: number,
minConfirmationsNb: number,
maxConfirmationsNb: number,
transactionFees: number,
exchange: string, exchange: string,
} }
@ -28,21 +19,6 @@ export type CurrenciesSettings = {
[id: string]: CurrencySettings, [id: string]: CurrencySettings,
} }
export type Settings = {
hasCompletedOnboarding: boolean,
language: string,
orderAccounts: string,
counterValue: string,
password: {
isEnabled: boolean,
value: string,
},
marketIndicator: 'eastern' | 'western',
currenciesSettings: CurrenciesSettings,
region: string,
developerMode: boolean,
}
export type T = (?string, ?Object) => string export type T = (?string, ?Object) => string
// -------------------- Manager // -------------------- Manager

Loading…
Cancel
Save