diff --git a/lib/commission-math.js b/lib/commission-math.js index 3827cb59..fe77b922 100644 --- a/lib/commission-math.js +++ b/lib/commission-math.js @@ -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) diff --git a/lib/new-config-manager.js b/lib/new-config-manager.js index 1c7fe5be..629ce674 100644 --- a/lib/new-config-manager.js +++ b/lib/new-config-manager.js @@ -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 } diff --git a/lib/plugins.js b/lib/plugins.js index 8ef30170..ce133e8c 100644 --- a/lib/plugins.js +++ b/lib/plugins.js @@ -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(':') diff --git a/migrations/1623975493095-add-crypto-units-to-config.js b/migrations/1623975493095-add-crypto-units-to-config.js new file mode 100644 index 00000000..512e14df --- /dev/null +++ b/migrations/1623975493095-add-crypto-units-to-config.js @@ -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() +} diff --git a/new-lamassu-admin/src/pages/Wallet/AdvancedWallet.js b/new-lamassu-admin/src/pages/Wallet/AdvancedWallet.js new file mode 100644 index 00000000..e326c720 --- /dev/null +++ b/new-lamassu-admin/src/pages/Wallet/AdvancedWallet.js @@ -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 ( + + ) +} + +export default AdvancedWallet diff --git a/new-lamassu-admin/src/pages/Wallet/Wallet.js b/new-lamassu-admin/src/pages/Wallet/Wallet.js index 1844dd07..f9a3514f 100644 --- a/new-lamassu-admin/src/pages/Wallet/Wallet.js +++ b/new-lamassu-admin/src/pages/Wallet/Wallet.js @@ -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 ( <> - - !WalletSchema.isValidSync(it)} - enableEdit - shouldOverrideEdit={shouldOverrideEdit} - editOverride={setWizard} - editWidth={174} - save={save} - validationSchema={WalletSchema} - elements={getElements(cryptoCurrencies, accountsConfig, onChange)} + - {wizard && ( - setWizard(false)} - save={save} - error={error?.message} - cryptoCurrencies={cryptoCurrencies} - userAccounts={data?.config?.accounts} - accounts={accounts} - accountsConfig={accountsConfig} - /> - )} - {editingSchema && ( - setEditingSchema(null)} - open={true}> - + !WalletSchema.isValidSync(it)} + enableEdit + shouldOverrideEdit={shouldOverrideEdit} + editOverride={setWizard} + editWidth={174} + save={save} + validationSchema={WalletSchema} + elements={getElements(cryptoCurrencies, accountsConfig, onChange)} /> - + {wizard && ( + setWizard(false)} + save={save} + error={error?.message} + cryptoCurrencies={cryptoCurrencies} + userAccounts={data?.config?.accounts} + accounts={accounts} + accountsConfig={accountsConfig} + /> + )} + {editingSchema && ( + setEditingSchema(null)} + open={true}> + + + )} + )} + {advancedSettings && } ) } diff --git a/new-lamassu-admin/src/pages/Wallet/Wizard.js b/new-lamassu-admin/src/pages/Wallet/Wizard.js index 4123f3fd..ea8a7c1a 100644 --- a/new-lamassu-admin/src/pages/Wallet/Wizard.js +++ b/new-lamassu-admin/src/pages/Wallet/Wizard.js @@ -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) } diff --git a/new-lamassu-admin/src/pages/Wallet/helper.js b/new-lamassu-admin/src/pages/Wallet/helper.js index 92adf854..82a355d9 100644 --- a/new-lamassu-admin/src/pages/Wallet/helper.js +++ b/new-lamassu-admin/src/pages/Wallet/helper.js @@ -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 +} diff --git a/new-lamassu-admin/src/pages/Wizard/components/Wallet/AllSet.js b/new-lamassu-admin/src/pages/Wizard/components/Wallet/AllSet.js index a9c3cd8f..50f8e4d8 100644 --- a/new-lamassu-admin/src/pages/Wizard/components/Wallet/AllSet.js +++ b/new-lamassu-admin/src/pages/Wizard/components/Wallet/AllSet.js @@ -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))