chore: use monorepo organization
This commit is contained in:
parent
deaf7d6ecc
commit
a687827f7e
1099 changed files with 8184 additions and 11535 deletions
86
packages/admin-ui/src/pages/Services/FormRenderer.jsx
Normal file
86
packages/admin-ui/src/pages/Services/FormRenderer.jsx
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
import classnames from 'classnames'
|
||||
import { Formik, Form, FastField } from 'formik'
|
||||
import * as R from 'ramda'
|
||||
import React, { useState } from 'react'
|
||||
import ErrorMessage from 'src/components/ErrorMessage'
|
||||
|
||||
import { Button } from 'src/components/buttons'
|
||||
import { SecretInput } from 'src/components/inputs/formik'
|
||||
|
||||
const FormRenderer = ({
|
||||
validationSchema,
|
||||
elements,
|
||||
value,
|
||||
save,
|
||||
buttonLabel = 'Save changes',
|
||||
buttonClass,
|
||||
xs = 12
|
||||
}) => {
|
||||
const initialValues = R.compose(
|
||||
R.mergeAll,
|
||||
R.map(({ code }) => ({ [code]: (value && value[code]) ?? '' }))
|
||||
)(elements)
|
||||
|
||||
const values = R.merge(initialValues, value)
|
||||
|
||||
const [saveError, setSaveError] = useState([])
|
||||
|
||||
const saveNonEmptySecret = it => {
|
||||
const emptySecretFields = R.compose(
|
||||
R.map(R.prop('code')),
|
||||
R.filter(
|
||||
elem =>
|
||||
R.prop('component', elem) === SecretInput &&
|
||||
R.isEmpty(it[R.prop('code', elem)])
|
||||
)
|
||||
)(elements)
|
||||
return save(R.omit(emptySecretFields, it)).catch(s => {
|
||||
setSaveError({ save: 'Failed to save changes' })
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<Formik
|
||||
validateOnBlur={false}
|
||||
validateOnChange={false}
|
||||
enableReinitialize
|
||||
initialValues={values}
|
||||
validationSchema={validationSchema}
|
||||
onSubmit={saveNonEmptySecret}>
|
||||
{({ errors }) => (
|
||||
<Form className="flex flex-col flex-1">
|
||||
<div className="flex flex-col gap-3 mb-6 mt-3">
|
||||
{elements.map(
|
||||
({ component, code, display, settings, inputProps }) => (
|
||||
<div key={code}>
|
||||
<FastField
|
||||
component={component}
|
||||
{...inputProps}
|
||||
name={code}
|
||||
label={display}
|
||||
settings={settings}
|
||||
fullWidth={true}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
)}
|
||||
</div>
|
||||
<div className="flex flex-row mt-auto mb-8">
|
||||
{!R.isEmpty(R.mergeRight(errors, saveError)) && (
|
||||
<ErrorMessage>
|
||||
{R.head(R.values(R.mergeRight(errors, saveError)))}
|
||||
</ErrorMessage>
|
||||
)}
|
||||
<Button
|
||||
className={classnames('mt-auto ml-auto', buttonClass)}
|
||||
type="submit">
|
||||
{buttonLabel}
|
||||
</Button>
|
||||
</div>
|
||||
</Form>
|
||||
)}
|
||||
</Formik>
|
||||
)
|
||||
}
|
||||
|
||||
export default FormRenderer
|
||||
141
packages/admin-ui/src/pages/Services/Services.jsx
Normal file
141
packages/admin-ui/src/pages/Services/Services.jsx
Normal file
|
|
@ -0,0 +1,141 @@
|
|||
import { useQuery, useMutation, gql } from '@apollo/client'
|
||||
import * as R from 'ramda'
|
||||
import React, { useState } from 'react'
|
||||
import Modal from 'src/components/Modal'
|
||||
import CheckboxInput from 'src/components/inputs/formik/Checkbox'
|
||||
import TitleSection from 'src/components/layout/TitleSection'
|
||||
import SingleRowTable from 'src/components/single-row-table/SingleRowTable'
|
||||
|
||||
import { SecretInput } from 'src/components/inputs/formik'
|
||||
import { formatLong } from 'src/utils/string'
|
||||
|
||||
import FormRenderer from './FormRenderer'
|
||||
import _schemas from './schemas'
|
||||
|
||||
const GET_INFO = gql`
|
||||
query getData {
|
||||
accounts
|
||||
config
|
||||
}
|
||||
`
|
||||
|
||||
const GET_MARKETS = gql`
|
||||
query getMarkets {
|
||||
getMarkets
|
||||
}
|
||||
`
|
||||
|
||||
const SAVE_ACCOUNT = gql`
|
||||
mutation Save($accounts: JSONObject) {
|
||||
saveAccounts(accounts: $accounts)
|
||||
}
|
||||
`
|
||||
|
||||
const Services = () => {
|
||||
const [editingSchema, setEditingSchema] = useState(null)
|
||||
|
||||
const { data, loading: configLoading } = useQuery(GET_INFO)
|
||||
const { data: marketsData, loading: marketsLoading } = useQuery(GET_MARKETS)
|
||||
const [saveAccount] = useMutation(SAVE_ACCOUNT, {
|
||||
onCompleted: () => setEditingSchema(null),
|
||||
refetchQueries: ['getData']
|
||||
})
|
||||
|
||||
const markets = marketsData?.getMarkets
|
||||
|
||||
const schemas = _schemas(markets)
|
||||
|
||||
const accounts = data?.accounts ?? {}
|
||||
|
||||
const getItems = (code, elements) => {
|
||||
const faceElements = R.filter(R.prop('face'))(elements)
|
||||
const values = accounts[code] || {}
|
||||
return R.map(({ display, code, long }) => ({
|
||||
label: display,
|
||||
value: long ? formatLong(values[code]) : values[code]
|
||||
}))(faceElements)
|
||||
}
|
||||
|
||||
const updateSettings = element => {
|
||||
const settings = element.settings
|
||||
const field = R.lensPath(['config', settings.field])
|
||||
const isEnabled = R.isNil(settings.requirement)
|
||||
? true
|
||||
: R.equals(R.view(field, data), settings.requirement)
|
||||
settings.enabled = isEnabled
|
||||
return element
|
||||
}
|
||||
|
||||
const getElements = ({ code, elements }) => {
|
||||
return R.map(elem => {
|
||||
if (elem.component === CheckboxInput) return updateSettings(elem)
|
||||
if (elem.component !== SecretInput) return elem
|
||||
return {
|
||||
...elem,
|
||||
inputProps: {
|
||||
isPasswordFilled:
|
||||
!R.isNil(accounts[code]) &&
|
||||
!R.isNil(R.path([elem.code], accounts[code]))
|
||||
}
|
||||
}
|
||||
}, elements)
|
||||
}
|
||||
|
||||
const getAccounts = ({ elements, code }) => {
|
||||
const account = accounts[code]
|
||||
const filterBySecretComponent = R.filter(R.propEq('component', SecretInput))
|
||||
const mapToCode = R.map(R.prop(['code']))
|
||||
const passwordFields = R.compose(
|
||||
mapToCode,
|
||||
filterBySecretComponent
|
||||
)(elements)
|
||||
return R.mapObjIndexed(
|
||||
(value, key) => (R.includes(key, passwordFields) ? '' : value),
|
||||
account
|
||||
)
|
||||
}
|
||||
|
||||
const getValidationSchema = ({ code, getValidationSchema }) =>
|
||||
getValidationSchema(accounts[code])
|
||||
|
||||
const loading = marketsLoading || configLoading
|
||||
|
||||
return (
|
||||
!loading && (
|
||||
<div>
|
||||
<TitleSection title="Third-Party services" />
|
||||
<div className="grid grid-cols-3 gap-5">
|
||||
{R.values(schemas).map(schema => (
|
||||
<SingleRowTable
|
||||
key={schema.code}
|
||||
editMessage={'Configure ' + schema.title}
|
||||
title={schema.title}
|
||||
onEdit={() => setEditingSchema(schema)}
|
||||
items={getItems(schema.code, schema.elements)}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
{editingSchema && (
|
||||
<Modal
|
||||
title={`Edit ${editingSchema.name}`}
|
||||
width={525}
|
||||
handleClose={() => setEditingSchema(null)}
|
||||
open={true}>
|
||||
<FormRenderer
|
||||
save={it =>
|
||||
saveAccount({
|
||||
variables: { accounts: { [editingSchema.code]: it } }
|
||||
})
|
||||
}
|
||||
elements={getElements(editingSchema)}
|
||||
validationSchema={getValidationSchema(editingSchema)}
|
||||
value={getAccounts(editingSchema)}
|
||||
/>
|
||||
</Modal>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
export default Services
|
||||
57
packages/admin-ui/src/pages/Services/schemas/binance.js
Normal file
57
packages/admin-ui/src/pages/Services/schemas/binance.js
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
import * as Yup from 'yup'
|
||||
|
||||
import {
|
||||
SecretInput,
|
||||
TextInput,
|
||||
Autocomplete
|
||||
} from 'src/components/inputs/formik'
|
||||
|
||||
import { secretTest, buildCurrencyOptions } from './helper'
|
||||
|
||||
const schema = markets => {
|
||||
return {
|
||||
code: 'binance',
|
||||
name: 'Binance',
|
||||
title: 'Binance (Exchange)',
|
||||
elements: [
|
||||
{
|
||||
code: 'apiKey',
|
||||
display: 'API key',
|
||||
component: TextInput,
|
||||
face: true,
|
||||
long: true
|
||||
},
|
||||
{
|
||||
code: 'privateKey',
|
||||
display: 'Private key',
|
||||
component: SecretInput
|
||||
},
|
||||
{
|
||||
code: 'currencyMarket',
|
||||
display: 'Currency market',
|
||||
component: Autocomplete,
|
||||
inputProps: {
|
||||
options: buildCurrencyOptions(markets),
|
||||
labelProp: 'display',
|
||||
valueProp: 'code'
|
||||
},
|
||||
face: true
|
||||
}
|
||||
],
|
||||
getValidationSchema: account => {
|
||||
return Yup.object().shape({
|
||||
apiKey: Yup.string('The API key must be a string')
|
||||
.max(100, 'The API key is too long')
|
||||
.required('The API key is required'),
|
||||
privateKey: Yup.string('The private key must be a string')
|
||||
.max(100, 'The private key is too long')
|
||||
.test(secretTest(account?.privateKey, 'private key')),
|
||||
currencyMarket: Yup.string(
|
||||
'The currency market must be a string'
|
||||
).required('The currency market is required')
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default schema
|
||||
57
packages/admin-ui/src/pages/Services/schemas/binanceus.js
Normal file
57
packages/admin-ui/src/pages/Services/schemas/binanceus.js
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
import * as Yup from 'yup'
|
||||
|
||||
import {
|
||||
SecretInput,
|
||||
TextInput,
|
||||
Autocomplete
|
||||
} from 'src/components/inputs/formik'
|
||||
|
||||
import { secretTest, buildCurrencyOptions } from './helper'
|
||||
|
||||
const schema = markets => {
|
||||
return {
|
||||
code: 'binanceus',
|
||||
name: 'Binance.us',
|
||||
title: 'Binance.us (Exchange)',
|
||||
elements: [
|
||||
{
|
||||
code: 'apiKey',
|
||||
display: 'API key',
|
||||
component: TextInput,
|
||||
face: true,
|
||||
long: true
|
||||
},
|
||||
{
|
||||
code: 'privateKey',
|
||||
display: 'Private key',
|
||||
component: SecretInput
|
||||
},
|
||||
{
|
||||
code: 'currencyMarket',
|
||||
display: 'Currency market',
|
||||
component: Autocomplete,
|
||||
inputProps: {
|
||||
options: buildCurrencyOptions(markets),
|
||||
labelProp: 'display',
|
||||
valueProp: 'code'
|
||||
},
|
||||
face: true
|
||||
}
|
||||
],
|
||||
getValidationSchema: account => {
|
||||
return Yup.object().shape({
|
||||
apiKey: Yup.string('The API key must be a string')
|
||||
.max(100, 'The API key is too long')
|
||||
.required('The API key is required'),
|
||||
privateKey: Yup.string('The private key must be a string')
|
||||
.max(100, 'The private key is too long')
|
||||
.test(secretTest(account?.privateKey, 'private key')),
|
||||
currencyMarket: Yup.string(
|
||||
'The currency market must be a string'
|
||||
).required('The currency market is required')
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default schema
|
||||
57
packages/admin-ui/src/pages/Services/schemas/bitfinex.js
Normal file
57
packages/admin-ui/src/pages/Services/schemas/bitfinex.js
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
import * as Yup from 'yup'
|
||||
|
||||
import {
|
||||
SecretInput,
|
||||
TextInput,
|
||||
Autocomplete
|
||||
} from 'src/components/inputs/formik'
|
||||
|
||||
import { secretTest, buildCurrencyOptions } from './helper'
|
||||
|
||||
const schema = markets => {
|
||||
return {
|
||||
code: 'bitfinex',
|
||||
name: 'Bitfinex',
|
||||
title: 'Bitfinex (Exchange)',
|
||||
elements: [
|
||||
{
|
||||
code: 'key',
|
||||
display: 'API key',
|
||||
component: TextInput,
|
||||
face: true,
|
||||
long: true
|
||||
},
|
||||
{
|
||||
code: 'secret',
|
||||
display: 'API secret',
|
||||
component: SecretInput
|
||||
},
|
||||
{
|
||||
code: 'currencyMarket',
|
||||
display: 'Currency Market',
|
||||
component: Autocomplete,
|
||||
inputProps: {
|
||||
options: buildCurrencyOptions(markets),
|
||||
labelProp: 'display',
|
||||
valueProp: 'code'
|
||||
},
|
||||
face: true
|
||||
}
|
||||
],
|
||||
getValidationSchema: account => {
|
||||
return Yup.object().shape({
|
||||
key: Yup.string('The API key must be a string')
|
||||
.max(100, 'The API key is too long')
|
||||
.required('The API key is required'),
|
||||
secret: Yup.string('The API secret must be a string')
|
||||
.max(100, 'The API secret is too long')
|
||||
.test(secretTest(account?.secret, 'API secret')),
|
||||
currencyMarket: Yup.string(
|
||||
'The currency market must be a string'
|
||||
).required('The currency market is required')
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default schema
|
||||
149
packages/admin-ui/src/pages/Services/schemas/bitgo.js
Normal file
149
packages/admin-ui/src/pages/Services/schemas/bitgo.js
Normal file
|
|
@ -0,0 +1,149 @@
|
|||
import * as Yup from 'yup'
|
||||
|
||||
import {
|
||||
TextInput,
|
||||
SecretInput,
|
||||
Autocomplete
|
||||
} from 'src/components/inputs/formik'
|
||||
|
||||
import { secretTest } from './helper'
|
||||
|
||||
const isDefined = it => it && it.length
|
||||
|
||||
const buildTestValidation = (id, passphrase) => {
|
||||
return Yup.string()
|
||||
.max(100, 'Too long')
|
||||
.when(id, {
|
||||
is: isDefined,
|
||||
then: schema => schema.test(secretTest(passphrase))
|
||||
})
|
||||
}
|
||||
|
||||
export default {
|
||||
code: 'bitgo',
|
||||
name: 'BitGo',
|
||||
title: 'BitGo (Wallet)',
|
||||
elements: [
|
||||
{
|
||||
code: 'token',
|
||||
display: 'API token',
|
||||
component: TextInput,
|
||||
face: true,
|
||||
long: true
|
||||
},
|
||||
{
|
||||
code: 'environment',
|
||||
display: 'Environment',
|
||||
component: Autocomplete,
|
||||
inputProps: {
|
||||
options: [
|
||||
{ code: 'prod', display: 'prod' },
|
||||
{ code: 'test', display: 'test' }
|
||||
],
|
||||
labelProp: 'display',
|
||||
valueProp: 'code'
|
||||
},
|
||||
face: true
|
||||
},
|
||||
{
|
||||
code: 'BTCWalletId',
|
||||
display: 'BTC wallet ID',
|
||||
component: TextInput
|
||||
},
|
||||
{
|
||||
code: 'BTCWalletPassphrase',
|
||||
display: 'BTC wallet passphrase',
|
||||
component: SecretInput
|
||||
},
|
||||
{
|
||||
code: 'LTCWalletId',
|
||||
display: 'LTC wallet ID',
|
||||
component: TextInput
|
||||
},
|
||||
{
|
||||
code: 'LTCWalletPassphrase',
|
||||
display: 'LTC wallet passphrase',
|
||||
component: SecretInput
|
||||
},
|
||||
{
|
||||
code: 'ZECWalletId',
|
||||
display: 'ZEC wallet ID',
|
||||
component: TextInput
|
||||
},
|
||||
{
|
||||
code: 'ZECWalletPassphrase',
|
||||
display: 'ZEC wallet passphrase',
|
||||
component: SecretInput
|
||||
},
|
||||
{
|
||||
code: 'BCHWalletId',
|
||||
display: 'BCH wallet ID',
|
||||
component: TextInput
|
||||
},
|
||||
{
|
||||
code: 'BCHWalletPassphrase',
|
||||
display: 'BCH wallet passphrase',
|
||||
component: SecretInput
|
||||
},
|
||||
{
|
||||
code: 'DASHWalletId',
|
||||
display: 'DASH wallet ID',
|
||||
component: TextInput
|
||||
},
|
||||
{
|
||||
code: 'DASHWalletPassphrase',
|
||||
display: 'DASH wallet passphrase',
|
||||
component: SecretInput
|
||||
}
|
||||
],
|
||||
getValidationSchema: account => {
|
||||
return Yup.object().shape({
|
||||
token: Yup.string('The token must be a string')
|
||||
.max(100, 'The token is too long')
|
||||
.required('The token is required'),
|
||||
BTCWalletId: Yup.string('The BTC wallet ID must be a string').max(
|
||||
100,
|
||||
'The BTC wallet ID is too long'
|
||||
),
|
||||
BTCWalletPassphrase: buildTestValidation(
|
||||
'BTCWalletId',
|
||||
account?.BTCWalletPassphrase
|
||||
),
|
||||
LTCWalletId: Yup.string('The LTC wallet ID must be a string').max(
|
||||
100,
|
||||
'The LTC wallet ID is too long'
|
||||
),
|
||||
LTCWalletPassphrase: buildTestValidation(
|
||||
'LTCWalletId',
|
||||
account?.LTCWalletPassphrase
|
||||
),
|
||||
ZECWalletId: Yup.string('The ZEC wallet ID must be a string').max(
|
||||
100,
|
||||
'The ZEC wallet ID is too long'
|
||||
),
|
||||
ZECWalletPassphrase: buildTestValidation(
|
||||
'ZECWalletId',
|
||||
account?.ZECWalletPassphrase
|
||||
),
|
||||
BCHWalletId: Yup.string('The BCH wallet ID must be a string').max(
|
||||
100,
|
||||
'The BCH wallet ID is too long'
|
||||
),
|
||||
BCHWalletPassphrase: buildTestValidation(
|
||||
'BCHWalletId',
|
||||
account?.BCHWalletPassphrase
|
||||
),
|
||||
DASHWalletId: Yup.string('The DASH wallet ID must be a string').max(
|
||||
100,
|
||||
'The DASH wallet ID is too long'
|
||||
),
|
||||
DASHWalletPassphrase: buildTestValidation(
|
||||
'DASHWalletId',
|
||||
account?.DASHWalletPassphrase
|
||||
),
|
||||
environment: Yup.string('The environment must be a string')
|
||||
.matches(/(prod|test)/)
|
||||
.required('The environment is required')
|
||||
});
|
||||
}
|
||||
}
|
||||
67
packages/admin-ui/src/pages/Services/schemas/bitstamp.js
Normal file
67
packages/admin-ui/src/pages/Services/schemas/bitstamp.js
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
import * as Yup from 'yup'
|
||||
|
||||
import {
|
||||
SecretInput,
|
||||
TextInput,
|
||||
Autocomplete
|
||||
} from 'src/components/inputs/formik'
|
||||
|
||||
import { secretTest, buildCurrencyOptions } from './helper'
|
||||
|
||||
const schema = markets => {
|
||||
return {
|
||||
code: 'bitstamp',
|
||||
name: 'Bitstamp',
|
||||
title: 'Bitstamp (Exchange)',
|
||||
elements: [
|
||||
{
|
||||
code: 'clientId',
|
||||
display: 'Client ID',
|
||||
component: TextInput,
|
||||
face: true,
|
||||
long: true
|
||||
},
|
||||
{
|
||||
code: 'key',
|
||||
display: 'API key',
|
||||
component: TextInput,
|
||||
face: true,
|
||||
long: true
|
||||
},
|
||||
{
|
||||
code: 'secret',
|
||||
display: 'API secret',
|
||||
component: SecretInput
|
||||
},
|
||||
{
|
||||
code: 'currencyMarket',
|
||||
display: 'Currency market',
|
||||
component: Autocomplete,
|
||||
inputProps: {
|
||||
options: buildCurrencyOptions(markets),
|
||||
labelProp: 'display',
|
||||
valueProp: 'code'
|
||||
},
|
||||
face: true
|
||||
}
|
||||
],
|
||||
getValidationSchema: account => {
|
||||
return Yup.object().shape({
|
||||
clientId: Yup.string('The client ID must be a string')
|
||||
.max(100, 'The client ID is too long')
|
||||
.required('The client ID is required'),
|
||||
key: Yup.string('The API key must be a string')
|
||||
.max(100, 'The API key is too long')
|
||||
.required('The API key is required'),
|
||||
secret: Yup.string('The API secret must be a string')
|
||||
.max(100, 'The API secret is too long')
|
||||
.test(secretTest(account?.secret, 'API secret')),
|
||||
currencyMarket: Yup.string(
|
||||
'The currency market must be a string'
|
||||
).required('The currency market is required')
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default schema
|
||||
50
packages/admin-ui/src/pages/Services/schemas/blockcypher.js
Normal file
50
packages/admin-ui/src/pages/Services/schemas/blockcypher.js
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
import * as Yup from 'yup'
|
||||
|
||||
import { Checkbox, TextInput, NumberInput } from 'src/components/inputs/formik'
|
||||
|
||||
export default {
|
||||
code: 'blockcypher',
|
||||
name: 'Blockcypher',
|
||||
title: 'Blockcypher (Payments)',
|
||||
elements: [
|
||||
{
|
||||
code: 'token',
|
||||
display: 'API token',
|
||||
component: TextInput,
|
||||
face: true,
|
||||
long: true
|
||||
},
|
||||
{
|
||||
code: 'confidenceFactor',
|
||||
display: 'Confidence factor',
|
||||
component: NumberInput,
|
||||
face: true
|
||||
},
|
||||
{
|
||||
code: 'rbf',
|
||||
component: Checkbox,
|
||||
settings: {
|
||||
field: 'wallets_BTC_wallet',
|
||||
enabled: true,
|
||||
disabledMessage:
|
||||
'Lower the confidence of RBF transactions (Available when using bitcoind.)',
|
||||
label: 'Lower the confidence of RBF transactions',
|
||||
requirement: 'bitcoind',
|
||||
rightSideLabel: true
|
||||
},
|
||||
face: true
|
||||
}
|
||||
],
|
||||
getValidationSchema: () => {
|
||||
return Yup.object().shape({
|
||||
token: Yup.string('The token must be a string')
|
||||
.max(100, 'The token is too long')
|
||||
.required('The token is required'),
|
||||
confidenceFactor: Yup.number('The confidence factor must be a number')
|
||||
.integer('The confidence factor must be an integer')
|
||||
.min(0, 'The confidence factor must be between 0 and 100')
|
||||
.max(100, 'The confidence factor must be between 0 and 100')
|
||||
.required('The confidence factor is required')
|
||||
})
|
||||
}
|
||||
}
|
||||
67
packages/admin-ui/src/pages/Services/schemas/cex.js
Normal file
67
packages/admin-ui/src/pages/Services/schemas/cex.js
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
import * as Yup from 'yup'
|
||||
|
||||
import {
|
||||
SecretInput,
|
||||
TextInput,
|
||||
Autocomplete
|
||||
} from 'src/components/inputs/formik'
|
||||
|
||||
import { secretTest, buildCurrencyOptions } from './helper'
|
||||
|
||||
const schema = markets => {
|
||||
return {
|
||||
code: 'cex',
|
||||
name: 'CEX.IO',
|
||||
title: 'CEX.IO (Exchange)',
|
||||
elements: [
|
||||
{
|
||||
code: 'apiKey',
|
||||
display: 'API key',
|
||||
component: TextInput,
|
||||
face: true,
|
||||
long: true
|
||||
},
|
||||
{
|
||||
code: 'uid',
|
||||
display: 'User ID',
|
||||
component: TextInput,
|
||||
face: true,
|
||||
long: true
|
||||
},
|
||||
{
|
||||
code: 'privateKey',
|
||||
display: 'Private key',
|
||||
component: SecretInput
|
||||
},
|
||||
{
|
||||
code: 'currencyMarket',
|
||||
display: 'Currency Market',
|
||||
component: Autocomplete,
|
||||
inputProps: {
|
||||
options: buildCurrencyOptions(markets),
|
||||
labelProp: 'display',
|
||||
valueProp: 'code'
|
||||
},
|
||||
face: true
|
||||
}
|
||||
],
|
||||
getValidationSchema: account => {
|
||||
return Yup.object().shape({
|
||||
apiKey: Yup.string('The API key must be a string')
|
||||
.max(100, 'The API key is too long')
|
||||
.required('The API key is required'),
|
||||
uid: Yup.string('The User ID must be a string')
|
||||
.max(100, 'The User ID is too long')
|
||||
.required('The User ID is required'),
|
||||
privateKey: Yup.string('The private key must be a string')
|
||||
.max(100, 'The private key is too long')
|
||||
.test(secretTest(account?.privateKey, 'private key')),
|
||||
currencyMarket: Yup.string(
|
||||
'The currency market must be a string'
|
||||
).required('The currency market is required')
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default schema
|
||||
63
packages/admin-ui/src/pages/Services/schemas/elliptic.js
Normal file
63
packages/admin-ui/src/pages/Services/schemas/elliptic.js
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
import CheckboxFormik from 'src/components/inputs/formik/Checkbox'
|
||||
import NumberInputFormik from 'src/components/inputs/formik/NumberInput'
|
||||
import SecretInputFormik from 'src/components/inputs/formik/SecretInput'
|
||||
import * as Yup from 'yup'
|
||||
|
||||
import { secretTest, leadingZerosTest } from './helper'
|
||||
|
||||
export default {
|
||||
code: 'elliptic',
|
||||
name: 'Elliptic',
|
||||
title: 'Elliptic (Scoring)',
|
||||
elements: [
|
||||
{
|
||||
code: 'apiKey',
|
||||
display: 'API Key',
|
||||
component: SecretInputFormik
|
||||
},
|
||||
{
|
||||
code: 'apiSecret',
|
||||
display: 'API Secret',
|
||||
component: SecretInputFormik
|
||||
},
|
||||
{
|
||||
code: 'scoreThreshold',
|
||||
display: 'Score threshold',
|
||||
component: NumberInputFormik,
|
||||
face: true,
|
||||
long: false
|
||||
},
|
||||
{
|
||||
code: 'enabled',
|
||||
component: CheckboxFormik,
|
||||
settings: {
|
||||
enabled: true,
|
||||
disabledMessage: 'This plugin is disabled',
|
||||
label: 'Enabled',
|
||||
requirement: null,
|
||||
rightSideLabel: true
|
||||
},
|
||||
face: true
|
||||
}
|
||||
],
|
||||
getValidationSchema: account => {
|
||||
return Yup.object().shape({
|
||||
apiKey: Yup.string('The API key must be a string')
|
||||
.max(100, 'Too long')
|
||||
.test(secretTest(account?.apiKey, 'API key')),
|
||||
apiSecret: Yup.string('The API secret must be a string')
|
||||
.max(100, 'Too long')
|
||||
.test(secretTest(account?.apiKey, 'API key')),
|
||||
scoreThreshold: Yup.number('The score threshold must be a number')
|
||||
.required('A score threshold is required')
|
||||
.min(1, 'The score threshold must be between 1 and 100')
|
||||
.max(100, 'The score threshold must be between 1 and 100')
|
||||
.integer('The score threshold must be an integer')
|
||||
.test(
|
||||
'no-leading-zeros',
|
||||
'The score threshold must not have leading zeros',
|
||||
leadingZerosTest
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
62
packages/admin-ui/src/pages/Services/schemas/galoy.js
Normal file
62
packages/admin-ui/src/pages/Services/schemas/galoy.js
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
import * as Yup from 'yup'
|
||||
|
||||
import {
|
||||
SecretInput,
|
||||
TextInput,
|
||||
Autocomplete
|
||||
} from 'src/components/inputs/formik'
|
||||
|
||||
import { secretTest } from './helper'
|
||||
|
||||
export default {
|
||||
code: 'galoy',
|
||||
name: 'Galoy',
|
||||
title: 'Galoy (Wallet)',
|
||||
elements: [
|
||||
{
|
||||
code: 'apiSecret',
|
||||
display: 'API Secret',
|
||||
component: SecretInput
|
||||
},
|
||||
{
|
||||
code: 'environment',
|
||||
display: 'Environment',
|
||||
component: Autocomplete,
|
||||
inputProps: {
|
||||
options: [
|
||||
{ code: 'main', display: 'prod' },
|
||||
{ code: 'test', display: 'test' }
|
||||
],
|
||||
labelProp: 'display',
|
||||
valueProp: 'code'
|
||||
},
|
||||
face: true
|
||||
},
|
||||
{
|
||||
code: 'endpoint',
|
||||
display: 'Endpoint',
|
||||
component: TextInput
|
||||
},
|
||||
{
|
||||
code: 'walletId',
|
||||
display: 'Wallet ID',
|
||||
component: SecretInput
|
||||
}
|
||||
],
|
||||
getValidationSchema: account => {
|
||||
return Yup.object().shape({
|
||||
apiSecret: Yup.string('The API Secret must be a string')
|
||||
.max(200, 'The API Secret is too long')
|
||||
.test(secretTest(account?.apiSecret)),
|
||||
walletId: Yup.string('The wallet id must be a string')
|
||||
.max(100, 'The wallet id is too long')
|
||||
.test(secretTest(account?.walletId)),
|
||||
environment: Yup.string('The environment must be a string')
|
||||
.matches(/(main|test)/)
|
||||
.required('The environment is required'),
|
||||
endpoint: Yup.string('The endpoint must be a string')
|
||||
.max(100, 'The endpoint is too long')
|
||||
.required('The endpoint is required')
|
||||
});
|
||||
}
|
||||
}
|
||||
64
packages/admin-ui/src/pages/Services/schemas/helper.js
Normal file
64
packages/admin-ui/src/pages/Services/schemas/helper.js
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
import { ALL_CRYPTOS } from '@lamassu/coins/config/consts'
|
||||
import { getEquivalentCode } from '@lamassu/coins/lightUtils'
|
||||
import * as R from 'ramda'
|
||||
|
||||
const WARNING_LEVELS = {
|
||||
CLEAN: 'clean',
|
||||
PARTIAL: 'partial',
|
||||
IMPORTANT: 'important'
|
||||
}
|
||||
|
||||
const secretTest = (secret, message) => ({
|
||||
name: 'secret-test',
|
||||
message: message ? `The ${message} is invalid` : 'Invalid field',
|
||||
test(val) {
|
||||
if (R.isNil(secret) && R.isNil(val)) {
|
||||
return this.createError()
|
||||
}
|
||||
return true
|
||||
}
|
||||
})
|
||||
|
||||
const leadingZerosTest = (value, context) => {
|
||||
if (
|
||||
R.startsWith('0', context.originalValue) &&
|
||||
R.length(context.originalValue) > 1
|
||||
) {
|
||||
return context.createError()
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
const buildCurrencyOptions = markets => {
|
||||
const prunedCoins = R.compose(R.uniq, R.map(getEquivalentCode))(ALL_CRYPTOS)
|
||||
return R.map(it => {
|
||||
const unavailableCryptos = R.difference(prunedCoins, markets[it])
|
||||
const unavailableCryptosFiltered = R.difference(unavailableCryptos, [it]) // As the markets can have stablecoins to trade against other crypto, filter them out, as there can't be pairs such as USDT/USDT
|
||||
|
||||
const unavailableMarketsStr =
|
||||
R.length(unavailableCryptosFiltered) > 1
|
||||
? `${R.join(
|
||||
', ',
|
||||
R.slice(0, -1, unavailableCryptosFiltered)
|
||||
)} and ${R.last(unavailableCryptosFiltered)}`
|
||||
: unavailableCryptosFiltered[0]
|
||||
|
||||
const warningLevel = R.isEmpty(unavailableCryptosFiltered)
|
||||
? WARNING_LEVELS.CLEAN
|
||||
: !R.isEmpty(unavailableCryptosFiltered) &&
|
||||
R.length(unavailableCryptosFiltered) < R.length(prunedCoins)
|
||||
? WARNING_LEVELS.PARTIAL
|
||||
: WARNING_LEVELS.IMPORTANT
|
||||
|
||||
return {
|
||||
code: R.toUpper(it),
|
||||
display: R.toUpper(it),
|
||||
warning: warningLevel,
|
||||
warningMessage: !R.isEmpty(unavailableCryptosFiltered)
|
||||
? `No market pairs available for ${unavailableMarketsStr}`
|
||||
: `All market pairs are available`
|
||||
}
|
||||
}, R.keys(markets))
|
||||
}
|
||||
|
||||
export { secretTest, leadingZerosTest, buildCurrencyOptions }
|
||||
55
packages/admin-ui/src/pages/Services/schemas/index.js
Normal file
55
packages/admin-ui/src/pages/Services/schemas/index.js
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
import _binance from './binance'
|
||||
import _binanceus from './binanceus'
|
||||
import _bitfinex from './bitfinex'
|
||||
import bitgo from './bitgo'
|
||||
import _bitstamp from './bitstamp'
|
||||
import blockcypher from './blockcypher'
|
||||
import _cex from './cex'
|
||||
import elliptic from './elliptic'
|
||||
import galoy from './galoy'
|
||||
import inforu from './inforu'
|
||||
import infura from './infura'
|
||||
import _itbit from './itbit'
|
||||
import _kraken from './kraken'
|
||||
import mailgun from './mailgun'
|
||||
import scorechain from './scorechain'
|
||||
import sumsub from './sumsub'
|
||||
import telnyx from './telnyx'
|
||||
import trongrid from './trongrid'
|
||||
import twilio from './twilio'
|
||||
import vonage from './vonage'
|
||||
|
||||
const schemas = (markets = {}) => {
|
||||
const binance = _binance(markets?.binance)
|
||||
const bitfinex = _bitfinex(markets?.bitfinex)
|
||||
const binanceus = _binanceus(markets?.binanceus)
|
||||
const bitstamp = _bitstamp(markets?.bitstamp)
|
||||
const cex = _cex(markets?.cex)
|
||||
const itbit = _itbit(markets?.itbit)
|
||||
const kraken = _kraken(markets?.kraken)
|
||||
|
||||
return {
|
||||
[bitgo.code]: bitgo,
|
||||
[galoy.code]: galoy,
|
||||
[bitstamp.code]: bitstamp,
|
||||
[blockcypher.code]: blockcypher,
|
||||
[elliptic.code]: elliptic,
|
||||
[inforu.code]: inforu,
|
||||
[infura.code]: infura,
|
||||
[itbit.code]: itbit,
|
||||
[kraken.code]: kraken,
|
||||
[mailgun.code]: mailgun,
|
||||
[telnyx.code]: telnyx,
|
||||
[vonage.code]: vonage,
|
||||
[twilio.code]: twilio,
|
||||
[binanceus.code]: binanceus,
|
||||
[cex.code]: cex,
|
||||
[scorechain.code]: scorechain,
|
||||
[trongrid.code]: trongrid,
|
||||
[binance.code]: binance,
|
||||
[bitfinex.code]: bitfinex,
|
||||
[sumsub.code]: sumsub
|
||||
}
|
||||
}
|
||||
|
||||
export default schemas
|
||||
52
packages/admin-ui/src/pages/Services/schemas/inforu.js
Normal file
52
packages/admin-ui/src/pages/Services/schemas/inforu.js
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
import SecretInputFormik from 'src/components/inputs/formik/SecretInput'
|
||||
import TextInputFormik from 'src/components/inputs/formik/TextInput'
|
||||
import * as Yup from 'yup'
|
||||
|
||||
import { secretTest } from './helper'
|
||||
|
||||
export default {
|
||||
code: 'inforu',
|
||||
name: 'InforU',
|
||||
title: 'InforU (SMS)',
|
||||
elements: [
|
||||
{
|
||||
code: 'username',
|
||||
display: 'InforU username',
|
||||
component: TextInputFormik,
|
||||
face: true
|
||||
},
|
||||
{
|
||||
code: 'apiKey',
|
||||
display: 'API Key',
|
||||
component: SecretInputFormik
|
||||
},
|
||||
{
|
||||
code: 'fromNumber',
|
||||
display: 'InforU sender',
|
||||
component: TextInputFormik,
|
||||
face: true
|
||||
},
|
||||
{
|
||||
code: 'toNumber',
|
||||
display: 'Notifications Number (international format)',
|
||||
component: TextInputFormik,
|
||||
face: true
|
||||
}
|
||||
],
|
||||
getValidationSchema: account => {
|
||||
return Yup.object().shape({
|
||||
username: Yup.string('The InforU username must be a string')
|
||||
.max(100, 'The InforU username is too long')
|
||||
.required('The InforU username is required'),
|
||||
apiKey: Yup.string('The API key must be a string')
|
||||
.max(200, 'The API key is too long')
|
||||
.test(secretTest(account?.apiKey, 'API key')),
|
||||
fromNumber: Yup.string('The InforU sender must be a string')
|
||||
.max(11, 'The InforU sender is too long')
|
||||
.required('The InforU sender is required'),
|
||||
toNumber: Yup.string('The notifications number must be a string')
|
||||
.max(100, 'The notifications number is too long')
|
||||
.required('The notifications number is required')
|
||||
})
|
||||
}
|
||||
}
|
||||
23
packages/admin-ui/src/pages/Services/schemas/infura.js
Normal file
23
packages/admin-ui/src/pages/Services/schemas/infura.js
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
import TextInputFormik from 'src/components/inputs/formik/TextInput'
|
||||
import * as Yup from 'yup'
|
||||
|
||||
export default {
|
||||
code: 'infura',
|
||||
name: 'Infura/Alchemy',
|
||||
title: 'Infura/Alchemy (Wallet)',
|
||||
elements: [
|
||||
{
|
||||
code: 'endpoint',
|
||||
display: 'Endpoint',
|
||||
component: TextInputFormik,
|
||||
face: true
|
||||
}
|
||||
],
|
||||
getValidationSchema: () => {
|
||||
return Yup.object().shape({
|
||||
endpoint: Yup.string('The endpoint must be a string')
|
||||
.max(100, 'The endpoint is too long')
|
||||
.required('The endpoint is required')
|
||||
})
|
||||
}
|
||||
}
|
||||
75
packages/admin-ui/src/pages/Services/schemas/itbit.js
Normal file
75
packages/admin-ui/src/pages/Services/schemas/itbit.js
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
import * as Yup from 'yup'
|
||||
|
||||
import {
|
||||
SecretInput,
|
||||
TextInput,
|
||||
Autocomplete
|
||||
} from 'src/components/inputs/formik'
|
||||
|
||||
import { buildCurrencyOptions, secretTest } from './helper'
|
||||
|
||||
const schema = markets => {
|
||||
return {
|
||||
code: 'itbit',
|
||||
name: 'itBit',
|
||||
title: 'itBit (Exchange)',
|
||||
elements: [
|
||||
{
|
||||
code: 'userId',
|
||||
display: 'User ID',
|
||||
component: TextInput,
|
||||
face: true,
|
||||
long: true
|
||||
},
|
||||
{
|
||||
code: 'walletId',
|
||||
display: 'Wallet ID',
|
||||
component: TextInput,
|
||||
face: true,
|
||||
long: true
|
||||
},
|
||||
{
|
||||
code: 'clientKey',
|
||||
display: 'Client key',
|
||||
component: TextInput
|
||||
},
|
||||
{
|
||||
code: 'clientSecret',
|
||||
display: 'Client secret',
|
||||
component: SecretInput
|
||||
},
|
||||
{
|
||||
code: 'currencyMarket',
|
||||
display: 'Currency market',
|
||||
component: Autocomplete,
|
||||
inputProps: {
|
||||
options: buildCurrencyOptions(markets),
|
||||
labelProp: 'display',
|
||||
valueProp: 'code'
|
||||
},
|
||||
face: true
|
||||
}
|
||||
],
|
||||
getValidationSchema: account => {
|
||||
return Yup.object().shape({
|
||||
userId: Yup.string('The user ID must be a string')
|
||||
.max(100, 'The user ID is too long')
|
||||
.required('The user ID is required'),
|
||||
walletId: Yup.string('The wallet ID must be a string')
|
||||
.max(100, 'The wallet ID is too long')
|
||||
.required('The wallet ID is required'),
|
||||
clientKey: Yup.string('The client key must be a string')
|
||||
.max(100, 'The client key is too long')
|
||||
.required('The client key is required'),
|
||||
clientSecret: Yup.string('The client secret must be a string')
|
||||
.max(100, 'The client secret is too long')
|
||||
.test(secretTest(account?.clientSecret, 'client secret')),
|
||||
currencyMarket: Yup.string(
|
||||
'The currency market must be a string'
|
||||
).required('The currency market is required')
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default schema
|
||||
57
packages/admin-ui/src/pages/Services/schemas/kraken.js
Normal file
57
packages/admin-ui/src/pages/Services/schemas/kraken.js
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
import * as Yup from 'yup'
|
||||
|
||||
import {
|
||||
SecretInput,
|
||||
TextInput,
|
||||
Autocomplete
|
||||
} from 'src/components/inputs/formik'
|
||||
|
||||
import { secretTest, buildCurrencyOptions } from './helper'
|
||||
|
||||
const schema = markets => {
|
||||
return {
|
||||
code: 'kraken',
|
||||
name: 'Kraken',
|
||||
title: 'Kraken (Exchange)',
|
||||
elements: [
|
||||
{
|
||||
code: 'apiKey',
|
||||
display: 'API key',
|
||||
component: TextInput,
|
||||
face: true,
|
||||
long: true
|
||||
},
|
||||
{
|
||||
code: 'privateKey',
|
||||
display: 'Private key',
|
||||
component: SecretInput
|
||||
},
|
||||
{
|
||||
code: 'currencyMarket',
|
||||
display: 'Currency market',
|
||||
component: Autocomplete,
|
||||
inputProps: {
|
||||
options: buildCurrencyOptions(markets),
|
||||
labelProp: 'display',
|
||||
valueProp: 'code'
|
||||
},
|
||||
face: true
|
||||
}
|
||||
],
|
||||
getValidationSchema: account => {
|
||||
return Yup.object().shape({
|
||||
apiKey: Yup.string('The API key must be a string')
|
||||
.max(100, 'The API key is too long')
|
||||
.required('The API key is required'),
|
||||
privateKey: Yup.string('The private key must be a string')
|
||||
.max(100, 'The private key is too long')
|
||||
.test(secretTest(account?.privateKey, 'private key')),
|
||||
currencyMarket: Yup.string(
|
||||
'The currency market must be a string'
|
||||
).required('The currency market is required')
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default schema
|
||||
50
packages/admin-ui/src/pages/Services/schemas/mailgun.js
Normal file
50
packages/admin-ui/src/pages/Services/schemas/mailgun.js
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
import TextInputFormik from 'src/components/inputs/formik/TextInput'
|
||||
import * as Yup from 'yup'
|
||||
|
||||
export default {
|
||||
code: 'mailgun',
|
||||
name: 'Mailgun',
|
||||
title: 'Mailgun (Email)',
|
||||
elements: [
|
||||
{
|
||||
code: 'apiKey',
|
||||
display: 'API key',
|
||||
component: TextInputFormik
|
||||
},
|
||||
{
|
||||
code: 'domain',
|
||||
display: 'Domain',
|
||||
component: TextInputFormik
|
||||
},
|
||||
{
|
||||
code: 'fromEmail',
|
||||
display: 'From email',
|
||||
component: TextInputFormik,
|
||||
face: true
|
||||
},
|
||||
{
|
||||
code: 'toEmail',
|
||||
display: 'To email',
|
||||
component: TextInputFormik,
|
||||
face: true
|
||||
}
|
||||
],
|
||||
getValidationSchema: () => {
|
||||
return Yup.object().shape({
|
||||
apiKey: Yup.string('The API key must be a string')
|
||||
.max(100, 'The API key is too long')
|
||||
.required('The API key is required'),
|
||||
domain: Yup.string('The domain must be a string')
|
||||
.max(100, 'The domain is too long')
|
||||
.required('The domain is required'),
|
||||
fromEmail: Yup.string('The from email must be a string')
|
||||
.max(100, 'The from email is too long')
|
||||
.email('The from email must be a valid email address')
|
||||
.required('The from email is required'),
|
||||
toEmail: Yup.string('The to email must be a string')
|
||||
.max(100, 'The to email is too long')
|
||||
.email('The to email must be a valid email address')
|
||||
.required('The to email is required')
|
||||
})
|
||||
}
|
||||
}
|
||||
55
packages/admin-ui/src/pages/Services/schemas/scorechain.js
Normal file
55
packages/admin-ui/src/pages/Services/schemas/scorechain.js
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
import CheckboxFormik from 'src/components/inputs/formik/Checkbox'
|
||||
import NumberInputFormik from 'src/components/inputs/formik/NumberInput'
|
||||
import SecretInputFormik from 'src/components/inputs/formik/SecretInput'
|
||||
import * as Yup from 'yup'
|
||||
|
||||
import { secretTest, leadingZerosTest } from './helper'
|
||||
|
||||
export default {
|
||||
code: 'scorechain',
|
||||
name: 'Scorechain',
|
||||
title: 'Scorechain (Scoring)',
|
||||
elements: [
|
||||
{
|
||||
code: 'apiKey',
|
||||
display: 'API Key',
|
||||
component: SecretInputFormik
|
||||
},
|
||||
{
|
||||
code: 'scoreThreshold',
|
||||
display: 'Score threshold',
|
||||
component: NumberInputFormik,
|
||||
face: true,
|
||||
long: false
|
||||
},
|
||||
{
|
||||
code: 'enabled',
|
||||
component: CheckboxFormik,
|
||||
settings: {
|
||||
enabled: true,
|
||||
disabledMessage: 'This plugin is disabled',
|
||||
label: 'Enabled',
|
||||
requirement: null,
|
||||
rightSideLabel: true
|
||||
},
|
||||
face: true
|
||||
}
|
||||
],
|
||||
getValidationSchema: account => {
|
||||
return Yup.object().shape({
|
||||
apiKey: Yup.string('The API key must be a string')
|
||||
.max(100, 'Too long')
|
||||
.test(secretTest(account?.apiKey, 'API key')),
|
||||
scoreThreshold: Yup.number('The score threshold must be a number')
|
||||
.required('A score threshold is required')
|
||||
.min(1, 'The score threshold must be between 1 and 100')
|
||||
.max(100, 'The score threshold must be between 1 and 100')
|
||||
.integer('The score threshold must be an integer')
|
||||
.test(
|
||||
'no-leading-zeros',
|
||||
'The score threshold must not have leading zeros',
|
||||
leadingZerosTest
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
64
packages/admin-ui/src/pages/Services/schemas/singlebitgo.js
Normal file
64
packages/admin-ui/src/pages/Services/schemas/singlebitgo.js
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
import * as Yup from 'yup'
|
||||
|
||||
import {
|
||||
TextInput,
|
||||
SecretInput,
|
||||
Autocomplete
|
||||
} from 'src/components/inputs/formik'
|
||||
|
||||
const singleBitgo = code => ({
|
||||
code: 'bitgo',
|
||||
name: 'BitGo',
|
||||
title: 'BitGo (Wallet)',
|
||||
elements: [
|
||||
{
|
||||
code: 'token',
|
||||
display: 'API token',
|
||||
component: TextInput,
|
||||
face: true,
|
||||
long: true
|
||||
},
|
||||
{
|
||||
code: 'environment',
|
||||
display: 'Environment',
|
||||
component: Autocomplete,
|
||||
inputProps: {
|
||||
options: [
|
||||
{ code: 'prod', display: 'prod' },
|
||||
{ code: 'test', display: 'test' }
|
||||
],
|
||||
labelProp: 'display',
|
||||
valueProp: 'code'
|
||||
},
|
||||
face: true
|
||||
},
|
||||
{
|
||||
code: `${code}WalletId`,
|
||||
display: `${code} wallet ID`,
|
||||
component: TextInput
|
||||
},
|
||||
{
|
||||
code: `${code}WalletPassphrase`,
|
||||
display: `${code} wallet passphrase`,
|
||||
component: SecretInput
|
||||
}
|
||||
],
|
||||
validationSchema: Yup.object().shape({
|
||||
token: Yup.string('The token must be a string')
|
||||
.max(100, 'The token is too long')
|
||||
.required('The token is required'),
|
||||
environment: Yup.string('The environment must be a string')
|
||||
.matches(/(prod|test)/)
|
||||
.required('The environment is required'),
|
||||
[`${code}WalletId`]: Yup.string(`The ${code} wallet ID must be a string`)
|
||||
.max(100, `The ${code} wallet ID is too long`)
|
||||
.required(`The ${code} wallet ID is required`),
|
||||
[`${code}WalletPassphrase`]: Yup.string(
|
||||
`The ${code} passphrase must be a string`
|
||||
)
|
||||
.max(100, `The ${code} wallet passphrase is too long`)
|
||||
.required(`The ${code} wallet passphrase is required`)
|
||||
})
|
||||
})
|
||||
|
||||
export default singleBitgo
|
||||
44
packages/admin-ui/src/pages/Services/schemas/sumsub.js
Normal file
44
packages/admin-ui/src/pages/Services/schemas/sumsub.js
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
import * as Yup from 'yup'
|
||||
|
||||
import { SecretInput, TextInput } from 'src/components/inputs/formik'
|
||||
|
||||
import { secretTest } from './helper'
|
||||
|
||||
const schema = {
|
||||
code: 'sumsub',
|
||||
name: 'Sumsub',
|
||||
title: 'Sumsub (Compliance)',
|
||||
elements: [
|
||||
{
|
||||
code: 'apiToken',
|
||||
display: 'API Token',
|
||||
component: SecretInput
|
||||
},
|
||||
{
|
||||
code: 'secretKey',
|
||||
display: 'Secret Key',
|
||||
component: SecretInput
|
||||
},
|
||||
{
|
||||
code: 'applicantLevel',
|
||||
display: 'Applicant Level',
|
||||
component: TextInput,
|
||||
face: true
|
||||
}
|
||||
],
|
||||
getValidationSchema: account => {
|
||||
return Yup.object().shape({
|
||||
apiToken: Yup.string('The API token must be a string')
|
||||
.max(100, 'The API token is too long')
|
||||
.test(secretTest(account?.apiToken, 'API token')),
|
||||
secretKey: Yup.string('The secret key must be a string')
|
||||
.max(100, 'The secret key is too long')
|
||||
.test(secretTest(account?.secretKey, 'secret key')),
|
||||
applicantLevel: Yup.string('The applicant level must be a string')
|
||||
.max(100, 'The applicant level is too long')
|
||||
.required('The applicant level is required')
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export default schema
|
||||
43
packages/admin-ui/src/pages/Services/schemas/telnyx.js
Normal file
43
packages/admin-ui/src/pages/Services/schemas/telnyx.js
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
import SecretInputFormik from 'src/components/inputs/formik/SecretInput'
|
||||
import TextInputFormik from 'src/components/inputs/formik/TextInput'
|
||||
import * as Yup from 'yup'
|
||||
|
||||
import { secretTest } from './helper'
|
||||
|
||||
export default {
|
||||
code: 'telnyx',
|
||||
name: 'Telnyx',
|
||||
title: 'Telnyx (SMS)',
|
||||
elements: [
|
||||
{
|
||||
code: 'apiKey',
|
||||
display: 'API Key',
|
||||
component: SecretInputFormik
|
||||
},
|
||||
{
|
||||
code: 'fromNumber',
|
||||
display: 'Telnyx Number (international format)',
|
||||
component: TextInputFormik,
|
||||
face: true
|
||||
},
|
||||
{
|
||||
code: 'toNumber',
|
||||
display: 'Notifications Number (international format)',
|
||||
component: TextInputFormik,
|
||||
face: true
|
||||
}
|
||||
],
|
||||
getValidationSchema: account => {
|
||||
return Yup.object().shape({
|
||||
apiKey: Yup.string('The API key must be a string')
|
||||
.max(200, 'The API key is too long')
|
||||
.test(secretTest(account?.apiKey, 'API key')),
|
||||
fromNumber: Yup.string('The Telnyx number must be a string')
|
||||
.max(100, 'The Telnyx number is too long')
|
||||
.required('The Telnyx number is required'),
|
||||
toNumber: Yup.string('The notifications number must be a string')
|
||||
.max(100, 'The notifications number is too long')
|
||||
.required('The notifications number is required')
|
||||
})
|
||||
}
|
||||
}
|
||||
24
packages/admin-ui/src/pages/Services/schemas/trongrid.js
Normal file
24
packages/admin-ui/src/pages/Services/schemas/trongrid.js
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
import TextInputFormik from 'src/components/inputs/formik/TextInput'
|
||||
import * as Yup from 'yup'
|
||||
|
||||
export default {
|
||||
code: 'trongrid',
|
||||
name: 'Trongrid',
|
||||
title: 'Trongrid (Wallet)',
|
||||
elements: [
|
||||
{
|
||||
code: 'apiKey',
|
||||
display: 'API Key',
|
||||
component: TextInputFormik,
|
||||
face: true,
|
||||
long: true
|
||||
}
|
||||
],
|
||||
getValidationSchema: account => {
|
||||
return Yup.object().shape({
|
||||
apiKey: Yup.string('The project ID must be a string')
|
||||
.max(100, 'The project ID is too long')
|
||||
.required('The project ID is required')
|
||||
})
|
||||
}
|
||||
}
|
||||
51
packages/admin-ui/src/pages/Services/schemas/twilio.js
Normal file
51
packages/admin-ui/src/pages/Services/schemas/twilio.js
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
import SecretInputFormik from 'src/components/inputs/formik/SecretInput'
|
||||
import TextInputFormik from 'src/components/inputs/formik/TextInput'
|
||||
import * as Yup from 'yup'
|
||||
|
||||
import { secretTest } from './helper'
|
||||
|
||||
export default {
|
||||
code: 'twilio',
|
||||
name: 'Twilio',
|
||||
title: 'Twilio (SMS)',
|
||||
elements: [
|
||||
{
|
||||
code: 'accountSid',
|
||||
display: 'Account SID',
|
||||
component: TextInputFormik
|
||||
},
|
||||
{
|
||||
code: 'authToken',
|
||||
display: 'Auth token',
|
||||
component: SecretInputFormik
|
||||
},
|
||||
{
|
||||
code: 'fromNumber',
|
||||
display: 'Twilio number (international format)',
|
||||
component: TextInputFormik,
|
||||
face: true
|
||||
},
|
||||
{
|
||||
code: 'toNumber',
|
||||
display: 'Notifications number (international format)',
|
||||
component: TextInputFormik,
|
||||
face: true
|
||||
}
|
||||
],
|
||||
getValidationSchema: account => {
|
||||
return Yup.object().shape({
|
||||
accountSid: Yup.string('The account SID must be a string')
|
||||
.max(100, 'The account SID is too long')
|
||||
.required('The account SID is required'),
|
||||
authToken: Yup.string('The auth token must be a string')
|
||||
.max(100, 'The auth token is too long')
|
||||
.test(secretTest(account?.authToken, 'auth token')),
|
||||
fromNumber: Yup.string('The Twilio number must be a string')
|
||||
.max(100, 'The Twilio number is too long')
|
||||
.required('The Twilio number is required'),
|
||||
toNumber: Yup.string('The notifications number must be a string')
|
||||
.max(100, 'The notifications number is too long')
|
||||
.required('The notifications number is required')
|
||||
})
|
||||
}
|
||||
}
|
||||
51
packages/admin-ui/src/pages/Services/schemas/vonage.js
Normal file
51
packages/admin-ui/src/pages/Services/schemas/vonage.js
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
import SecretInputFormik from 'src/components/inputs/formik/SecretInput'
|
||||
import TextInputFormik from 'src/components/inputs/formik/TextInput'
|
||||
import * as Yup from 'yup'
|
||||
|
||||
import { secretTest } from './helper'
|
||||
|
||||
export default {
|
||||
code: 'vonage',
|
||||
name: 'Vonage',
|
||||
title: 'Vonage (SMS)',
|
||||
elements: [
|
||||
{
|
||||
code: 'apiKey',
|
||||
display: 'API Key',
|
||||
component: TextInputFormik
|
||||
},
|
||||
{
|
||||
code: 'apiSecret',
|
||||
display: 'API Secret',
|
||||
component: SecretInputFormik
|
||||
},
|
||||
{
|
||||
code: 'fromNumber',
|
||||
display: 'Vonage Number (international format)',
|
||||
component: TextInputFormik,
|
||||
face: true
|
||||
},
|
||||
{
|
||||
code: 'toNumber',
|
||||
display: 'Notifications Number (international format)',
|
||||
component: TextInputFormik,
|
||||
face: true
|
||||
}
|
||||
],
|
||||
getValidationSchema: account => {
|
||||
return Yup.object().shape({
|
||||
apiKey: Yup.string('The API key must be a string')
|
||||
.max(200, 'The API key is too long')
|
||||
.required('The Vonage number is required'),
|
||||
apiSecret: Yup.string('The API key must be a string')
|
||||
.max(200, 'The API secret is too long')
|
||||
.test(secretTest(account?.apiKey, 'API secret')),
|
||||
fromNumber: Yup.string('The Vonage number must be a string')
|
||||
.max(100, 'The Vonage number is too long')
|
||||
.required('The Vonage number is required'),
|
||||
toNumber: Yup.string('The notifications number must be a string')
|
||||
.max(100, 'The notifications number is too long')
|
||||
.required('The notifications number is required')
|
||||
})
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue