Fix: default 0 zeroConfLimit for new coins
This commit is contained in:
parent
fafee1a727
commit
65a55a669d
7 changed files with 63 additions and 138 deletions
|
|
@ -3,13 +3,27 @@ var db = require('../lib/db')
|
||||||
const settingsLoader = require('../lib/new-settings-loader')
|
const settingsLoader = require('../lib/new-settings-loader')
|
||||||
const configManager = require('../lib/new-config-manager')
|
const configManager = require('../lib/new-config-manager')
|
||||||
|
|
||||||
|
const stripl = _.curry((q, str) => _.startsWith(q, str) ? str.slice(q.length) : str)
|
||||||
|
const filter = namespace => _.pickBy((value, key) => _.startsWith(`${namespace}_`)(key))
|
||||||
|
const strip = key => _.mapKeys(stripl(`${key}_`))
|
||||||
|
|
||||||
|
const fromNamespace = _.curry((key, config) => _.compose(strip(key), filter(key))(config))
|
||||||
|
|
||||||
|
const split = _.curry(_.split)
|
||||||
|
const composed = _.compose(_.head, split('_'))
|
||||||
|
|
||||||
|
const getCryptoCodes = (config) => {
|
||||||
|
const walletKeys = _.keys(fromNamespace('wallets', config))
|
||||||
|
return _.uniq(_.map(composed, walletKeys))
|
||||||
|
}
|
||||||
|
|
||||||
exports.up = function (next) {
|
exports.up = function (next) {
|
||||||
db.tx(async t => {
|
db.tx(async t => {
|
||||||
let min = Infinity
|
let min = Infinity
|
||||||
const sp = settingsLoader.loadLatest()
|
const sp = settingsLoader.loadLatest()
|
||||||
const mp = t.any('SELECT device_id FROM devices')
|
const mp = t.any('SELECT device_id FROM devices')
|
||||||
const [{ config }, machines] = await Promise.all([sp, mp])
|
const [{ config }, machines] = await Promise.all([sp, mp])
|
||||||
const cryptoCurrencies = config.locale_cryptoCurrencies
|
const cryptoCodes = getCryptoCodes(config)
|
||||||
|
|
||||||
_.forEach(o => {
|
_.forEach(o => {
|
||||||
const machineId = o.device_id
|
const machineId = o.device_id
|
||||||
|
|
@ -29,10 +43,10 @@ exports.up = function (next) {
|
||||||
if (!zeroConfLimit) {
|
if (!zeroConfLimit) {
|
||||||
config[key] = Number(min)
|
config[key] = Number(min)
|
||||||
}
|
}
|
||||||
}, cryptoCurrencies)
|
}, cryptoCodes)
|
||||||
|
|
||||||
const regexp = /^cashOut_[0-9a-z]+_zeroConfLimit$/
|
const regexp = /^cashOut_[0-9a-z]+_zeroConfLimit$/
|
||||||
const keysToErase = Object.keys(config).filter(key => key.match(regexp))
|
const keysToErase = _.keys(config).filter(key => key.match(regexp))
|
||||||
|
|
||||||
_.forEach(key => {
|
_.forEach(key => {
|
||||||
config[key] = null
|
config[key] = null
|
||||||
|
|
|
||||||
|
|
@ -149,6 +149,7 @@ const Locales = ({ name: SCREEN_KEY }) => {
|
||||||
if (!coin) return setValue(curr)
|
if (!coin) return setValue(curr)
|
||||||
|
|
||||||
const namespaced = fromNamespace(coin)(wallets)
|
const namespaced = fromNamespace(coin)(wallets)
|
||||||
|
console.log(namespaced)
|
||||||
if (!WalletSchema.isValidSync(namespaced)) {
|
if (!WalletSchema.isValidSync(namespaced)) {
|
||||||
setOnChangeFunction(() => () => setValue(curr))
|
setOnChangeFunction(() => () => setValue(curr))
|
||||||
setWizard(coin)
|
setWizard(coin)
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ import { toNamespace } from 'src/utils/config'
|
||||||
import WizardSplash from './WizardSplash'
|
import WizardSplash from './WizardSplash'
|
||||||
import WizardStep from './WizardStep'
|
import WizardStep from './WizardStep'
|
||||||
|
|
||||||
const LAST_STEP = 5
|
const LAST_STEP = 4
|
||||||
const MODAL_WIDTH = 554
|
const MODAL_WIDTH = 554
|
||||||
|
|
||||||
const contains = crypto => R.compose(R.contains(crypto), R.prop('cryptos'))
|
const contains = crypto => R.compose(R.contains(crypto), R.prop('cryptos'))
|
||||||
|
|
@ -65,6 +65,7 @@ const Wizard = ({
|
||||||
: accountsToSave
|
: accountsToSave
|
||||||
|
|
||||||
if (isLastStep) {
|
if (isLastStep) {
|
||||||
|
newConfig.zeroConfLimit = 0
|
||||||
return save(toNamespace(coin.code, newConfig), newAccounts)
|
return save(toNamespace(coin.code, newConfig), newAccounts)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -85,8 +86,6 @@ const Wizard = ({
|
||||||
return { type: 'exchange', ...exchanges }
|
return { type: 'exchange', ...exchanges }
|
||||||
case 4:
|
case 4:
|
||||||
return { type: 'zeroConf', name: 'zero conf', ...zeroConfs }
|
return { type: 'zeroConf', name: 'zero conf', ...zeroConfs }
|
||||||
case 5:
|
|
||||||
return { type: 'zeroConfLimit' }
|
|
||||||
default:
|
default:
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,13 +2,11 @@ import { makeStyles } from '@material-ui/core'
|
||||||
import classnames from 'classnames'
|
import classnames from 'classnames'
|
||||||
import * as R from 'ramda'
|
import * as R from 'ramda'
|
||||||
import React, { useReducer, useEffect } from 'react'
|
import React, { useReducer, useEffect } from 'react'
|
||||||
import * as Yup from 'yup'
|
|
||||||
|
|
||||||
import ErrorMessage from 'src/components/ErrorMessage'
|
import ErrorMessage from 'src/components/ErrorMessage'
|
||||||
import Stepper from 'src/components/Stepper'
|
import Stepper from 'src/components/Stepper'
|
||||||
import { Button } from 'src/components/buttons'
|
import { Button } from 'src/components/buttons'
|
||||||
import { RadioGroup, Autocomplete } from 'src/components/inputs'
|
import { RadioGroup, Autocomplete } from 'src/components/inputs'
|
||||||
import { NumberInput } from 'src/components/inputs/formik'
|
|
||||||
import { H4, Info2 } from 'src/components/typography'
|
import { H4, Info2 } from 'src/components/typography'
|
||||||
import FormRenderer from 'src/pages/Services/FormRenderer'
|
import FormRenderer from 'src/pages/Services/FormRenderer'
|
||||||
import schema from 'src/pages/Services/schemas'
|
import schema from 'src/pages/Services/schemas'
|
||||||
|
|
@ -84,13 +82,6 @@ const WizardStep = ({
|
||||||
onContinue(config, account)
|
onContinue(config, account)
|
||||||
}
|
}
|
||||||
|
|
||||||
const zeroConfLimitSchema = Yup.object().shape({
|
|
||||||
zeroConfLimit: Yup.number()
|
|
||||||
.integer()
|
|
||||||
.required()
|
|
||||||
.min(0)
|
|
||||||
.max(999999999)
|
|
||||||
})
|
|
||||||
const label = lastStep ? 'Finish' : 'Next'
|
const label = lastStep ? 'Finish' : 'Next'
|
||||||
const displayName = name ?? type
|
const displayName = name ?? type
|
||||||
const subtitleClass = {
|
const subtitleClass = {
|
||||||
|
|
@ -100,83 +91,54 @@ const WizardStep = ({
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Info2 className={classes.title}>{startCase(type)}</Info2>
|
<Info2 className={classes.title}>{startCase(type)}</Info2>
|
||||||
<Stepper steps={5} currentStep={step} />
|
<Stepper steps={4} currentStep={step} />
|
||||||
{step <= 4 && (
|
<H4 className={classnames(subtitleClass)}>
|
||||||
<>
|
Select a {displayName} or set up a new one
|
||||||
<H4 className={classnames(subtitleClass)}>
|
</H4>
|
||||||
Select a {displayName} or set up a new one
|
<RadioGroup
|
||||||
</H4>
|
options={filled}
|
||||||
|
value={selected}
|
||||||
|
className={classes.radioGroup}
|
||||||
|
onChange={(evt, it) => {
|
||||||
|
dispatch({ type: 'select', selected: it })
|
||||||
|
}}
|
||||||
|
labelClassName={classes.radioLabel}
|
||||||
|
radioClassName={classes.radio}
|
||||||
|
/>
|
||||||
|
<div className={classes.setupNew}>
|
||||||
|
{!R.isEmpty(unfilled) && !R.isNil(unfilled) && (
|
||||||
<RadioGroup
|
<RadioGroup
|
||||||
options={filled}
|
value={isNew}
|
||||||
value={selected}
|
|
||||||
className={classes.radioGroup}
|
|
||||||
onChange={(evt, it) => {
|
onChange={(evt, it) => {
|
||||||
dispatch({ type: 'select', selected: it })
|
dispatch({ type: 'new' })
|
||||||
}}
|
}}
|
||||||
labelClassName={classes.radioLabel}
|
labelClassName={classes.radioLabel}
|
||||||
radioClassName={classes.radio}
|
radioClassName={classes.radio}
|
||||||
|
options={[{ display: 'Set up new', code: true }]}
|
||||||
/>
|
/>
|
||||||
<div className={classes.setupNew}>
|
)}
|
||||||
{!R.isEmpty(unfilled) && !R.isNil(unfilled) && (
|
{isNew && (
|
||||||
<RadioGroup
|
<Autocomplete
|
||||||
value={isNew}
|
fullWidth
|
||||||
onChange={(evt, it) => {
|
label={`Select ${displayName}`}
|
||||||
dispatch({ type: 'new' })
|
className={classes.picker}
|
||||||
}}
|
getOptionSelected={R.eqProps('code')}
|
||||||
labelClassName={classes.radioLabel}
|
labelProp={'display'}
|
||||||
radioClassName={classes.radio}
|
options={unfilled}
|
||||||
options={[{ display: 'Set up new', code: true }]}
|
onChange={(evt, it) => {
|
||||||
/>
|
dispatch({ type: 'form', form: it })
|
||||||
)}
|
}}
|
||||||
{isNew && (
|
|
||||||
<Autocomplete
|
|
||||||
fullWidth
|
|
||||||
label={`Select ${displayName}`}
|
|
||||||
className={classes.picker}
|
|
||||||
getOptionSelected={R.eqProps('code')}
|
|
||||||
labelProp={'display'}
|
|
||||||
options={unfilled}
|
|
||||||
onChange={(evt, it) => {
|
|
||||||
dispatch({ type: 'form', form: it })
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
{form && (
|
|
||||||
<FormRenderer
|
|
||||||
save={it =>
|
|
||||||
innerContinue({ [type]: form.code }, { [form.code]: it })
|
|
||||||
}
|
|
||||||
elements={schema[form.code].elements}
|
|
||||||
validationSchema={schema[form.code].validationSchema}
|
|
||||||
value={getValue(form.code)}
|
|
||||||
buttonLabel={label}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
{step === 5 && (
|
|
||||||
<>
|
|
||||||
<H4 className={classnames(subtitleClass)}>Edit 0-conf Limit</H4>
|
|
||||||
<FormRenderer
|
|
||||||
save={it =>
|
|
||||||
innerContinue(
|
|
||||||
{ [type]: Number(it.zeroConfLimit) },
|
|
||||||
{ [form.code]: it }
|
|
||||||
)
|
|
||||||
}
|
|
||||||
elements={[
|
|
||||||
{
|
|
||||||
code: 'zeroConfLimit',
|
|
||||||
display: `Choose a ${locale.fiatCurrency} limit`,
|
|
||||||
component: NumberInput
|
|
||||||
}
|
|
||||||
]}
|
|
||||||
validationSchema={zeroConfLimitSchema}
|
|
||||||
buttonLabel={label}
|
|
||||||
value={null}
|
|
||||||
/>
|
/>
|
||||||
</>
|
)}
|
||||||
|
</div>
|
||||||
|
{form && (
|
||||||
|
<FormRenderer
|
||||||
|
save={it => innerContinue({ [type]: form.code }, { [form.code]: it })}
|
||||||
|
elements={schema[form.code].elements}
|
||||||
|
validationSchema={schema[form.code].validationSchema}
|
||||||
|
value={getValue(form.code)}
|
||||||
|
buttonLabel={label}
|
||||||
|
/>
|
||||||
)}
|
)}
|
||||||
{!form && (
|
{!form && (
|
||||||
<div className={classes.submit}>
|
<div className={classes.submit}>
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,8 @@ const AllSet = ({ data: currentData, doContinue }) => {
|
||||||
const accountsConfig = data?.accountsConfig
|
const accountsConfig = data?.accountsConfig
|
||||||
const cryptoCurrencies = data?.cryptoCurrencies ?? []
|
const cryptoCurrencies = data?.cryptoCurrencies ?? []
|
||||||
|
|
||||||
|
currentData.zeroConfLimit = 0
|
||||||
|
|
||||||
const save = () => {
|
const save = () => {
|
||||||
if (!WalletSchema.isValidSync(currentData)) return setError(true)
|
if (!WalletSchema.isValidSync(currentData)) return setError(true)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,6 @@ import ChooseCoin from './ChooseCoin'
|
||||||
import ChooseExchange from './ChooseExchange'
|
import ChooseExchange from './ChooseExchange'
|
||||||
import ChooseTicker from './ChooseTicker'
|
import ChooseTicker from './ChooseTicker'
|
||||||
import ChooseWallet from './ChooseWallet'
|
import ChooseWallet from './ChooseWallet'
|
||||||
import ZeroConfLimit from './ZeroConfLimit'
|
|
||||||
|
|
||||||
const useStyles = makeStyles(styles)
|
const useStyles = makeStyles(styles)
|
||||||
|
|
||||||
|
|
@ -37,10 +36,6 @@ const steps = [
|
||||||
label: 'Blockcypher',
|
label: 'Blockcypher',
|
||||||
component: Blockcypher
|
component: Blockcypher
|
||||||
},
|
},
|
||||||
{
|
|
||||||
label: 'Set 0-conf Limit',
|
|
||||||
component: ZeroConfLimit
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
label: 'All set',
|
label: 'All set',
|
||||||
component: AllSet
|
component: AllSet
|
||||||
|
|
|
||||||
|
|
@ -1,48 +0,0 @@
|
||||||
import { makeStyles } from '@material-ui/core'
|
|
||||||
import React from 'react'
|
|
||||||
import * as Yup from 'yup'
|
|
||||||
|
|
||||||
import { NumberInput } from 'src/components/inputs/formik'
|
|
||||||
import { H4 } from 'src/components/typography'
|
|
||||||
import FormRenderer from 'src/pages/Services/FormRenderer'
|
|
||||||
|
|
||||||
import styles from './Shared.styles'
|
|
||||||
|
|
||||||
const useStyles = makeStyles(styles)
|
|
||||||
|
|
||||||
const zeroConfLimitSchema = Yup.object().shape({
|
|
||||||
zeroConfLimit: Yup.number()
|
|
||||||
.integer()
|
|
||||||
.required()
|
|
||||||
.min(0)
|
|
||||||
.max(999999999)
|
|
||||||
})
|
|
||||||
|
|
||||||
const ZeroConfLimit = ({ data: currentData, addData }) => {
|
|
||||||
const classes = useStyles()
|
|
||||||
|
|
||||||
const submit = value => {
|
|
||||||
addData({ zeroConfLimit: value })
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className={classes.mdForm}>
|
|
||||||
<H4>Set the 0-conf limit</H4>
|
|
||||||
<FormRenderer
|
|
||||||
elements={[
|
|
||||||
{
|
|
||||||
code: 'zeroConfLimit',
|
|
||||||
display: `Choose a limit`,
|
|
||||||
component: NumberInput
|
|
||||||
}
|
|
||||||
]}
|
|
||||||
validationSchema={zeroConfLimitSchema}
|
|
||||||
buttonLabel={'Continue'}
|
|
||||||
value={null}
|
|
||||||
save={it => submit(Number(it.zeroConfLimit))}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default ZeroConfLimit
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue