Merge pull request #766 from josepfo/feat/crypto-units-selector
feat: advanced wallet settings
This commit is contained in:
commit
0881d00594
9 changed files with 222 additions and 47 deletions
|
|
@ -3,11 +3,11 @@ const configManager = require('./new-config-manager')
|
|||
const { utils: coinUtils } = require('lamassu-coins')
|
||||
|
||||
function truncateCrypto (cryptoAtoms, cryptoCode) {
|
||||
const DECIMAL_PLACES = 3
|
||||
const DECIMAL_PLACES = 6
|
||||
if (cryptoAtoms.eq(0)) return cryptoAtoms
|
||||
|
||||
const scale = coinUtils.getCryptoCurrency(cryptoCode).displayScale
|
||||
const scaleFactor = new BN(10).pow(scale)
|
||||
const scale = coinUtils.getCryptoCurrency(cryptoCode).unitScale
|
||||
const scaleFactor = BN(10).pow(scale)
|
||||
|
||||
return new BN(cryptoAtoms).integerValue(BN.ROUND_DOWN).div(scaleFactor)
|
||||
.decimalPlaces(DECIMAL_PLACES).times(scaleFactor)
|
||||
|
|
|
|||
|
|
@ -132,6 +132,10 @@ const getCryptosFromWalletNamespace = config => {
|
|||
|
||||
const getCashInSettings = config => fromNamespace(namespaces.CASH_IN)(config)
|
||||
|
||||
const getCryptoUnits = (crypto, config) => {
|
||||
return getWalletSettings(crypto, config).cryptoUnits
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getWalletSettings,
|
||||
getCashInSettings,
|
||||
|
|
@ -149,5 +153,6 @@ module.exports = {
|
|||
getTriggers,
|
||||
getTriggersAutomation,
|
||||
getCashOut,
|
||||
getCryptosFromWalletNamespace
|
||||
getCryptosFromWalletNamespace,
|
||||
getCryptoUnits
|
||||
}
|
||||
|
|
|
|||
|
|
@ -206,6 +206,7 @@ function plugins (settings, deviceId) {
|
|||
const cashInCommission = new BN(commissions.cashIn)
|
||||
const cashOutCommission = _.isNumber(commissions.cashOut) ? new BN(commissions.cashOut) : null
|
||||
const cryptoRec = coinUtils.getCryptoCurrency(cryptoCode)
|
||||
const cryptoUnits = configManager.getCryptoUnits(cryptoCode, settings.config)
|
||||
|
||||
return {
|
||||
cryptoCode,
|
||||
|
|
@ -214,13 +215,13 @@ function plugins (settings, deviceId) {
|
|||
cashInFee,
|
||||
cashInCommission,
|
||||
cashOutCommission,
|
||||
cryptoNetwork
|
||||
cryptoNetwork,
|
||||
cryptoUnits
|
||||
}
|
||||
}
|
||||
|
||||
function pollQueries (serialNumber, deviceTime, deviceRec, machineVersion, machineModel) {
|
||||
const localeConfig = configManager.getLocale(deviceId, settings.config)
|
||||
|
||||
const fiatCode = localeConfig.fiatCurrency
|
||||
const cryptoCodes = localeConfig.cryptoCurrencies
|
||||
const timezone = localeConfig.timezone.split(':')
|
||||
|
|
|
|||
28
migrations/1623975493095-add-crypto-units-to-config.js
Normal file
28
migrations/1623975493095-add-crypto-units-to-config.js
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
const { saveConfig, loadLatest } = require('../lib/new-settings-loader')
|
||||
const { getCryptosFromWalletNamespace } = require('../lib/new-config-manager.js')
|
||||
const { utils: coinUtils } = require('lamassu-coins')
|
||||
const _ = require('lodash/fp')
|
||||
|
||||
exports.up = function (next) {
|
||||
loadLatest()
|
||||
.then(settings => {
|
||||
const newSettings = {}
|
||||
const activeCryptos = getCryptosFromWalletNamespace(settings.config)
|
||||
if (!activeCryptos.length) return Promise.resolve()
|
||||
_.map(crypto => {
|
||||
const defaultUnit = _.head(_.keys(coinUtils.getCryptoCurrency(crypto).units))
|
||||
newSettings[`wallets_${crypto}_cryptoUnits`] = defaultUnit
|
||||
return newSettings
|
||||
}, activeCryptos)
|
||||
return saveConfig(newSettings)
|
||||
})
|
||||
.then(() => next())
|
||||
.catch(err => {
|
||||
console.log(err.message)
|
||||
return next(err)
|
||||
})
|
||||
}
|
||||
|
||||
exports.down = function (next) {
|
||||
next()
|
||||
}
|
||||
60
new-lamassu-admin/src/pages/Wallet/AdvancedWallet.js
Normal file
60
new-lamassu-admin/src/pages/Wallet/AdvancedWallet.js
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
import { useQuery, useMutation } from '@apollo/react-hooks'
|
||||
import gql from 'graphql-tag'
|
||||
import { utils as coinUtils } from 'lamassu-coins'
|
||||
import * as R from 'ramda'
|
||||
import React from 'react'
|
||||
|
||||
import { NamespacedTable as EditableTable } from 'src/components/editableTable'
|
||||
import { fromNamespace, toNamespace, namespaces } from 'src/utils/config'
|
||||
|
||||
import { AdvancedWalletSchema, getAdvancedWalletElements } from './helper'
|
||||
|
||||
const SAVE_CONFIG = gql`
|
||||
mutation Save($config: JSONObject, $accounts: JSONObject) {
|
||||
saveConfig(config: $config)
|
||||
saveAccounts(accounts: $accounts)
|
||||
}
|
||||
`
|
||||
const GET_INFO = gql`
|
||||
query getData {
|
||||
config
|
||||
accounts
|
||||
cryptoCurrencies {
|
||||
code
|
||||
display
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
const AdvancedWallet = () => {
|
||||
const SCREEN_KEY = namespaces.WALLETS
|
||||
const { data } = useQuery(GET_INFO)
|
||||
|
||||
const [saveConfig, { error }] = useMutation(SAVE_CONFIG, {
|
||||
refetchQueries: () => ['getData']
|
||||
})
|
||||
|
||||
const save = (rawConfig, accounts) => {
|
||||
const config = toNamespace(SCREEN_KEY)(rawConfig)
|
||||
return saveConfig({ variables: { config, accounts } })
|
||||
}
|
||||
|
||||
const config = data?.config && fromNamespace(SCREEN_KEY)(data.config)
|
||||
const cryptoCurrencies = data?.cryptoCurrencies ?? []
|
||||
|
||||
return (
|
||||
<EditableTable
|
||||
name="advancedWallet"
|
||||
namespaces={R.map(R.path(['code']))(cryptoCurrencies)}
|
||||
data={config}
|
||||
error={error?.message}
|
||||
enableEdit
|
||||
editWidth={174}
|
||||
save={save}
|
||||
validationSchema={AdvancedWalletSchema}
|
||||
elements={getAdvancedWalletElements(cryptoCurrencies, coinUtils)}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export default AdvancedWallet
|
||||
|
|
@ -8,8 +8,11 @@ import { NamespacedTable as EditableTable } from 'src/components/editableTable'
|
|||
import TitleSection from 'src/components/layout/TitleSection'
|
||||
import FormRenderer from 'src/pages/Services/FormRenderer'
|
||||
import schemas from 'src/pages/Services/schemas'
|
||||
import { ReactComponent as ReverseSettingsIcon } from 'src/styling/icons/circle buttons/settings/white.svg'
|
||||
import { ReactComponent as SettingsIcon } from 'src/styling/icons/circle buttons/settings/zodiac.svg'
|
||||
import { fromNamespace, toNamespace } from 'src/utils/config'
|
||||
|
||||
import AdvancedWallet from './AdvancedWallet'
|
||||
import Wizard from './Wizard'
|
||||
import { WalletSchema, getElements } from './helper'
|
||||
|
||||
|
|
@ -48,6 +51,7 @@ const Wallet = ({ name: SCREEN_KEY }) => {
|
|||
const [editingSchema, setEditingSchema] = useState(null)
|
||||
const [onChangeFunction, setOnChangeFunction] = useState(null)
|
||||
const [wizard, setWizard] = useState(false)
|
||||
const [advancedSettings, setAdvancedSettings] = useState(false)
|
||||
const { data } = useQuery(GET_INFO)
|
||||
|
||||
const [saveConfig, { error }] = useMutation(SAVE_CONFIG, {
|
||||
|
|
@ -99,47 +103,60 @@ const Wallet = ({ name: SCREEN_KEY }) => {
|
|||
|
||||
return (
|
||||
<>
|
||||
<TitleSection title="Wallet Settings" />
|
||||
<EditableTable
|
||||
name="test"
|
||||
namespaces={R.map(R.path(['code']))(cryptoCurrencies)}
|
||||
data={config}
|
||||
error={error?.message}
|
||||
stripeWhen={it => !WalletSchema.isValidSync(it)}
|
||||
enableEdit
|
||||
shouldOverrideEdit={shouldOverrideEdit}
|
||||
editOverride={setWizard}
|
||||
editWidth={174}
|
||||
save={save}
|
||||
validationSchema={WalletSchema}
|
||||
elements={getElements(cryptoCurrencies, accountsConfig, onChange)}
|
||||
<TitleSection
|
||||
title="Wallet Settings"
|
||||
button={{
|
||||
text: 'Advanced settings',
|
||||
icon: SettingsIcon,
|
||||
inverseIcon: ReverseSettingsIcon,
|
||||
toggle: setAdvancedSettings
|
||||
}}
|
||||
/>
|
||||
{wizard && (
|
||||
<Wizard
|
||||
coin={R.find(R.propEq('code', wizard))(cryptoCurrencies)}
|
||||
onClose={() => setWizard(false)}
|
||||
save={save}
|
||||
error={error?.message}
|
||||
cryptoCurrencies={cryptoCurrencies}
|
||||
userAccounts={data?.config?.accounts}
|
||||
accounts={accounts}
|
||||
accountsConfig={accountsConfig}
|
||||
/>
|
||||
)}
|
||||
{editingSchema && (
|
||||
<Modal
|
||||
title={`Edit ${editingSchema.name}`}
|
||||
width={478}
|
||||
handleClose={() => setEditingSchema(null)}
|
||||
open={true}>
|
||||
<FormRenderer
|
||||
save={wizardSave}
|
||||
elements={editingSchema.elements}
|
||||
validationSchema={editingSchema.validationSchema}
|
||||
value={accounts[editingSchema.code]}
|
||||
{!advancedSettings && (
|
||||
<>
|
||||
<EditableTable
|
||||
name="test"
|
||||
namespaces={R.map(R.path(['code']))(cryptoCurrencies)}
|
||||
data={config}
|
||||
error={error?.message}
|
||||
stripeWhen={it => !WalletSchema.isValidSync(it)}
|
||||
enableEdit
|
||||
shouldOverrideEdit={shouldOverrideEdit}
|
||||
editOverride={setWizard}
|
||||
editWidth={174}
|
||||
save={save}
|
||||
validationSchema={WalletSchema}
|
||||
elements={getElements(cryptoCurrencies, accountsConfig, onChange)}
|
||||
/>
|
||||
</Modal>
|
||||
{wizard && (
|
||||
<Wizard
|
||||
coin={R.find(R.propEq('code', wizard))(cryptoCurrencies)}
|
||||
onClose={() => setWizard(false)}
|
||||
save={save}
|
||||
error={error?.message}
|
||||
cryptoCurrencies={cryptoCurrencies}
|
||||
userAccounts={data?.config?.accounts}
|
||||
accounts={accounts}
|
||||
accountsConfig={accountsConfig}
|
||||
/>
|
||||
)}
|
||||
{editingSchema && (
|
||||
<Modal
|
||||
title={`Edit ${editingSchema.name}`}
|
||||
width={478}
|
||||
handleClose={() => setEditingSchema(null)}
|
||||
open={true}>
|
||||
<FormRenderer
|
||||
save={wizardSave}
|
||||
elements={editingSchema.elements}
|
||||
validationSchema={editingSchema.validationSchema}
|
||||
value={accounts[editingSchema.code]}
|
||||
/>
|
||||
</Modal>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
{advancedSettings && <AdvancedWallet></AdvancedWallet>}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import { utils as coinUtils } from 'lamassu-coins'
|
||||
import * as R from 'ramda'
|
||||
import React, { useState } from 'react'
|
||||
|
||||
|
|
@ -57,7 +58,14 @@ const Wizard = ({ coin, onClose, accountsConfig, accounts, save, error }) => {
|
|||
: accountsToSave
|
||||
|
||||
if (isLastStep) {
|
||||
const configToSave = { ...newConfig, zeroConfLimit: 0 }
|
||||
const defaultCryptoUnit = R.head(
|
||||
R.keys(coinUtils.getCryptoCurrency(coin.code).units)
|
||||
)
|
||||
const configToSave = {
|
||||
...newConfig,
|
||||
zeroConfLimit: 0,
|
||||
cryptoUnits: defaultCryptoUnit
|
||||
}
|
||||
return save(toNamespace(coin.code, configToSave), newAccounts)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -28,6 +28,48 @@ const WalletSchema = Yup.object().shape({
|
|||
.transform(transformNumber)
|
||||
})
|
||||
|
||||
const AdvancedWalletSchema = Yup.object().shape({
|
||||
cryptoUnits: Yup.string().required()
|
||||
})
|
||||
|
||||
const getAdvancedWalletElements = (cryptoCurrencies, coinUtils) => {
|
||||
const viewCryptoCurrency = it =>
|
||||
R.compose(
|
||||
R.prop(['display']),
|
||||
R.find(R.propEq('code', it))
|
||||
)(cryptoCurrencies)
|
||||
|
||||
const getOptions = R.curry((coinUtils, it) => {
|
||||
const options = R.keys(coinUtils.getCryptoCurrency(it.id).units)
|
||||
return R.map(option => {
|
||||
return { code: option, display: option }
|
||||
})(options)
|
||||
})
|
||||
|
||||
return [
|
||||
{
|
||||
name: 'id',
|
||||
header: 'Cryptocurrency',
|
||||
width: 180,
|
||||
view: viewCryptoCurrency,
|
||||
size: 'sm',
|
||||
editable: false
|
||||
},
|
||||
{
|
||||
name: 'cryptoUnits',
|
||||
size: 'sm',
|
||||
stripe: true,
|
||||
width: 190,
|
||||
input: Autocomplete,
|
||||
inputProps: {
|
||||
options: getOptions(coinUtils),
|
||||
valueProp: 'code',
|
||||
labelProp: 'display'
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
const getElements = (cryptoCurrencies, accounts, onChange, wizard = false) => {
|
||||
const widthAdjust = wizard ? 11 : 0
|
||||
const viewCryptoCurrency = it => {
|
||||
|
|
@ -134,4 +176,10 @@ const getElements = (cryptoCurrencies, accounts, onChange, wizard = false) => {
|
|||
]
|
||||
}
|
||||
|
||||
export { WalletSchema, getElements, filterClass }
|
||||
export {
|
||||
WalletSchema,
|
||||
AdvancedWalletSchema,
|
||||
getElements,
|
||||
filterClass,
|
||||
getAdvancedWalletElements
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { useQuery, useMutation } from '@apollo/react-hooks'
|
||||
import { makeStyles } from '@material-ui/core'
|
||||
import gql from 'graphql-tag'
|
||||
import { utils as coinUtils } from 'lamassu-coins'
|
||||
import * as R from 'ramda'
|
||||
import React, { useState } from 'react'
|
||||
|
||||
|
|
@ -53,7 +54,14 @@ const AllSet = ({ data: currentData, doContinue }) => {
|
|||
const cryptoCurrencies = data?.cryptoCurrencies ?? []
|
||||
|
||||
const save = () => {
|
||||
const adjustedData = { zeroConfLimit: 0, ...currentData }
|
||||
const defaultCryptoUnit = R.head(
|
||||
R.keys(coinUtils.getCryptoCurrency(coin).units)
|
||||
)
|
||||
const adjustedData = {
|
||||
zeroConfLimit: 0,
|
||||
...currentData,
|
||||
cryptoUnits: defaultCryptoUnit
|
||||
}
|
||||
if (!WalletSchema.isValidSync(adjustedData)) return setError(true)
|
||||
|
||||
const withCoin = toNamespace(coin, R.omit('coin', adjustedData))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue