From 01114d01e480a3a45db48d580e06031174806e99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Oliveira?= Date: Wed, 4 Aug 2021 17:56:37 +0100 Subject: [PATCH 1/3] feat: add support for binance.us, cex.io and ftx --- lib/new-admin/config/accounts.js | 8 ++++- lib/new-settings-loader.js | 3 ++ lib/plugins/common/ccxt.js | 6 ++++ lib/plugins/exchange/binanceus.js | 20 +++++++++++ lib/plugins/exchange/cex.js | 21 +++++++++++ lib/plugins/exchange/ftx.js | 19 ++++++++++ .../src/pages/Services/Services.js | 1 + .../src/pages/Services/schemas/binanceus.js | 36 +++++++++++++++++++ .../src/pages/Services/schemas/cex.js | 36 +++++++++++++++++++ .../src/pages/Services/schemas/ftx.js | 36 +++++++++++++++++++ .../src/pages/Services/schemas/index.js | 8 ++++- .../components/Wallet/ChooseExchange.js | 3 +- 12 files changed, 194 insertions(+), 3 deletions(-) create mode 100644 lib/plugins/exchange/binanceus.js create mode 100644 lib/plugins/exchange/cex.js create mode 100644 lib/plugins/exchange/ftx.js create mode 100644 new-lamassu-admin/src/pages/Services/schemas/binanceus.js create mode 100644 new-lamassu-admin/src/pages/Services/schemas/cex.js create mode 100644 new-lamassu-admin/src/pages/Services/schemas/ftx.js diff --git a/lib/new-admin/config/accounts.js b/lib/new-admin/config/accounts.js index 7fbd76dd..d8fded9b 100644 --- a/lib/new-admin/config/accounts.js +++ b/lib/new-admin/config/accounts.js @@ -4,7 +4,7 @@ const _ = require('lodash/fp') const { ALL } = require('../../plugins/common/ccxt') const { BTC, BCH, DASH, ETH, LTC, ZEC, USDT } = COINS -const { bitpay, coinbase, itbit, bitstamp, kraken } = ALL +const { bitpay, coinbase, itbit, bitstamp, kraken, binanceus, cex, ftx } = ALL const TICKER = 'ticker' const WALLET = 'wallet' @@ -16,6 +16,9 @@ const EMAIL = 'email' const ZERO_CONF = 'zeroConf' const ALL_ACCOUNTS = [ + { code: 'binanceus', display: 'Binance.us', class: TICKER, cryptos: binanceus.CRYPTO }, + { code: 'cex', display: 'Cex', class: TICKER, cryptos: cex.CRYPTO }, + { code: 'ftx', display: 'Ftx', class: TICKER, cryptos: ftx.CRYPTO }, { code: 'bitpay', display: 'Bitpay', class: TICKER, cryptos: bitpay.CRYPTO }, { code: 'kraken', display: 'Kraken', class: TICKER, cryptos: kraken.CRYPTO }, { code: 'bitstamp', display: 'Bitstamp', class: TICKER, cryptos: bitstamp.CRYPTO }, @@ -34,6 +37,9 @@ const ALL_ACCOUNTS = [ { code: 'bitstamp', display: 'Bitstamp', class: EXCHANGE, cryptos: bitstamp.CRYPTO }, { code: 'itbit', display: 'itBit', class: EXCHANGE, cryptos: itbit.CRYPTO }, { code: 'kraken', display: 'Kraken', class: EXCHANGE, cryptos: kraken.CRYPTO }, + { code: 'binanceus', display: 'Binance.us', class: EXCHANGE, cryptos: binanceus.CRYPTO }, + { code: 'cex', display: 'Cex', class: EXCHANGE, cryptos: cex.CRYPTO }, + { code: 'ftx', display: 'Ftx', class: EXCHANGE, cryptos: ftx.CRYPTO }, { code: 'mock-wallet', display: 'Mock (Caution!)', class: WALLET, cryptos: ALL_CRYPTOS, dev: true }, { code: 'no-exchange', display: 'No exchange', class: EXCHANGE, cryptos: ALL_CRYPTOS }, { code: 'mock-exchange', display: 'Mock exchange', class: EXCHANGE, cryptos: ALL_CRYPTOS, dev: true }, diff --git a/lib/new-settings-loader.js b/lib/new-settings-loader.js index 1be04445..fd0cc435 100644 --- a/lib/new-settings-loader.js +++ b/lib/new-settings-loader.js @@ -15,6 +15,9 @@ const SECRET_FIELDS = [ 'infura.apiSecret', 'itbit.clientSecret', 'kraken.privateKey', + 'binanceus.privateKey', + 'ftx.privateKey', + 'cex.privateKey', 'twilio.authToken' ] diff --git a/lib/plugins/common/ccxt.js b/lib/plugins/common/ccxt.js index 3ead7673..b0c879e9 100644 --- a/lib/plugins/common/ccxt.js +++ b/lib/plugins/common/ccxt.js @@ -4,10 +4,16 @@ const _ = require('lodash/fp') const kraken = require('../exchange/kraken') const bitstamp = require('../exchange/bitstamp') const itbit = require('../exchange/itbit') +const binanceus = require('../exchange/binanceus') +const cex = require('../exchange/cex') +const ftx = require('../exchange/ftx') const bitpay = require('../ticker/bitpay') const { BTC, BCH, DASH, ETH, LTC, ZEC } = COINS const ALL = { + cex: cex, + ftx: ftx, + binanceus: binanceus, kraken: kraken, bitstamp: bitstamp, itbit: itbit, diff --git a/lib/plugins/exchange/binanceus.js b/lib/plugins/exchange/binanceus.js new file mode 100644 index 00000000..fb98998f --- /dev/null +++ b/lib/plugins/exchange/binanceus.js @@ -0,0 +1,20 @@ +const { COINS } = require('lamassu-coins') +const _ = require('lodash/fp') + +const { ORDER_TYPES } = require('./consts') + +const ORDER_TYPE = ORDER_TYPES.MARKET +const { BTC, BCH, DASH, ETH, LTC, ZEC, USDT } = COINS +const CRYPTO = [BTC, ETH, LTC, DASH, ZEC, BCH, USDT] +const FIAT = ['USD'] +const REQUIRED_CONFIG_FIELDS = ['apiKey', 'privateKey'] + +const loadConfig = (account) => { + const mapper = {} + const mapped = _.mapKeys(key => mapper[key] ? mapper[key] : key)(account) + return { ...mapped, timeout: 3000 } +} + +// Documentation mentions a mandatory field 'time', not sure how ccxt handles this, probably works if we send this via options + +module.exports = { loadConfig, REQUIRED_CONFIG_FIELDS, CRYPTO, FIAT, ORDER_TYPE } diff --git a/lib/plugins/exchange/cex.js b/lib/plugins/exchange/cex.js new file mode 100644 index 00000000..ae3b2885 --- /dev/null +++ b/lib/plugins/exchange/cex.js @@ -0,0 +1,21 @@ +const { COINS } = require('lamassu-coins') +const _ = require('lodash/fp') + +const { ORDER_TYPES } = require('./consts') + +const ORDER_TYPE = ORDER_TYPES.MARKET +const { BTC, BCH, DASH, ETH, LTC, USDT } = COINS +const CRYPTO = [BTC, ETH, LTC, DASH, BCH, USDT] +const FIAT = ['USD', 'EUR'] +const REQUIRED_CONFIG_FIELDS = ['apiKey', 'privateKey'] + +const loadConfig = (account) => { + const mapper = {} + const mapped = _.mapKeys(key => mapper[key] ? mapper[key] : key)(account) + return { ...mapped, timeout: 3000 } +} + +// Documentation mentions a field 'nonce', doesn't specify if it's mandatory +// or not but we should pay attention to this when testing + +module.exports = { loadConfig, REQUIRED_CONFIG_FIELDS, CRYPTO, FIAT, ORDER_TYPE } diff --git a/lib/plugins/exchange/ftx.js b/lib/plugins/exchange/ftx.js new file mode 100644 index 00000000..f9e154e8 --- /dev/null +++ b/lib/plugins/exchange/ftx.js @@ -0,0 +1,19 @@ +const { COINS } = require('lamassu-coins') +const _ = require('lodash/fp') + +const { ORDER_TYPES } = require('./consts') + +const ORDER_TYPE = ORDER_TYPES.MARKET +const { BTC, BCH, ETH, LTC, USDT } = COINS +const CRYPTO = [BTC, ETH, LTC, BCH, USDT] +// ftx supports EUR as well but only for certain cryptos: ETH, BTC +const FIAT = ['USD'] +const REQUIRED_CONFIG_FIELDS = ['apiKey', 'privateKey'] + +const loadConfig = (account) => { + const mapper = {} + const mapped = _.mapKeys(key => mapper[key] ? mapper[key] : key)(account) + return { ...mapped, timeout: 3000 } +} + +module.exports = { loadConfig, REQUIRED_CONFIG_FIELDS, CRYPTO, FIAT, ORDER_TYPE } diff --git a/new-lamassu-admin/src/pages/Services/Services.js b/new-lamassu-admin/src/pages/Services/Services.js index 2bfe619f..3953be9f 100644 --- a/new-lamassu-admin/src/pages/Services/Services.js +++ b/new-lamassu-admin/src/pages/Services/Services.js @@ -114,6 +114,7 @@ const Services = () => { ))} + {console.log(editingSchema)} {editingSchema && ( { + return Yup.object().shape({ + apiKey: Yup.string() + .max(100, 'Too long') + .required(), + privateKey: Yup.string() + .max(100, 'Too long') + .test(secretTest(account?.privateKey)) + }) + } +} diff --git a/new-lamassu-admin/src/pages/Services/schemas/cex.js b/new-lamassu-admin/src/pages/Services/schemas/cex.js new file mode 100644 index 00000000..a2108afd --- /dev/null +++ b/new-lamassu-admin/src/pages/Services/schemas/cex.js @@ -0,0 +1,36 @@ +import * as Yup from 'yup' + +import SecretInputFormik from 'src/components/inputs/formik/SecretInput' +import TextInputFormik from 'src/components/inputs/formik/TextInput' + +import secretTest from './helper' + +export default { + code: 'cex', + name: 'Cex', + title: 'Cex (Exchange)', + elements: [ + { + code: 'apiKey', + display: 'API Key', + component: TextInputFormik, + face: true, + long: true + }, + { + code: 'privateKey', + display: 'Private Key', + component: SecretInputFormik + } + ], + getValidationSchema: account => { + return Yup.object().shape({ + apiKey: Yup.string() + .max(100, 'Too long') + .required(), + privateKey: Yup.string() + .max(100, 'Too long') + .test(secretTest(account?.privateKey)) + }) + } +} diff --git a/new-lamassu-admin/src/pages/Services/schemas/ftx.js b/new-lamassu-admin/src/pages/Services/schemas/ftx.js new file mode 100644 index 00000000..125b5f80 --- /dev/null +++ b/new-lamassu-admin/src/pages/Services/schemas/ftx.js @@ -0,0 +1,36 @@ +import * as Yup from 'yup' + +import SecretInputFormik from 'src/components/inputs/formik/SecretInput' +import TextInputFormik from 'src/components/inputs/formik/TextInput' + +import secretTest from './helper' + +export default { + code: 'ftx', + name: 'Ftx', + title: 'Ftx (Exchange)', + elements: [ + { + code: 'apiKey', + display: 'API Key', + component: TextInputFormik, + face: true, + long: true + }, + { + code: 'privateKey', + display: 'Private Key', + component: SecretInputFormik + } + ], + getValidationSchema: account => { + return Yup.object().shape({ + apiKey: Yup.string() + .max(100, 'Too long') + .required(), + privateKey: Yup.string() + .max(100, 'Too long') + .test(secretTest(account?.privateKey)) + }) + } +} diff --git a/new-lamassu-admin/src/pages/Services/schemas/index.js b/new-lamassu-admin/src/pages/Services/schemas/index.js index ac51c92f..a7878702 100644 --- a/new-lamassu-admin/src/pages/Services/schemas/index.js +++ b/new-lamassu-admin/src/pages/Services/schemas/index.js @@ -1,6 +1,9 @@ +import binanceus from './binanceus' import bitgo from './bitgo' import bitstamp from './bitstamp' import blockcypher from './blockcypher' +import cex from './cex' +import ftx from './ftx' import infura from './infura' import itbit from './itbit' import kraken from './kraken' @@ -15,5 +18,8 @@ export default { [itbit.code]: itbit, [kraken.code]: kraken, [mailgun.code]: mailgun, - [twilio.code]: twilio + [twilio.code]: twilio, + [binanceus.code]: binanceus, + [cex.code]: cex, + [ftx.code]: ftx } diff --git a/new-lamassu-admin/src/pages/Wizard/components/Wallet/ChooseExchange.js b/new-lamassu-admin/src/pages/Wizard/components/Wallet/ChooseExchange.js index 158c2512..10b9b51c 100644 --- a/new-lamassu-admin/src/pages/Wizard/components/Wallet/ChooseExchange.js +++ b/new-lamassu-admin/src/pages/Wizard/components/Wallet/ChooseExchange.js @@ -38,7 +38,8 @@ const SAVE_ACCOUNTS = gql` } ` -const isConfigurable = it => R.contains(it)(['kraken', 'itbit', 'bitstamp']) +const isConfigurable = it => + R.contains(it)(['kraken', 'itbit', 'bitstamp', 'binanceus', 'cex', 'ftx']) const ChooseExchange = ({ data: currentData, addData }) => { const classes = useStyles() From 99177c01bb9293611c898c59a85b2fa0db80f3c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Oliveira?= Date: Wed, 4 Aug 2021 17:59:01 +0100 Subject: [PATCH 2/3] fix: remove console log --- new-lamassu-admin/src/pages/Services/Services.js | 1 - 1 file changed, 1 deletion(-) diff --git a/new-lamassu-admin/src/pages/Services/Services.js b/new-lamassu-admin/src/pages/Services/Services.js index 3953be9f..2bfe619f 100644 --- a/new-lamassu-admin/src/pages/Services/Services.js +++ b/new-lamassu-admin/src/pages/Services/Services.js @@ -114,7 +114,6 @@ const Services = () => { ))} - {console.log(editingSchema)} {editingSchema && ( Date: Mon, 9 Aug 2021 01:01:53 +0100 Subject: [PATCH 3/3] refactor: simplify filter function and remove unnecessary comments --- lib/plugins/exchange/binanceus.js | 2 -- lib/plugins/exchange/cex.js | 3 --- lib/plugins/exchange/ftx.js | 1 - .../src/pages/Wizard/components/Wallet/ChooseExchange.js | 3 +-- 4 files changed, 1 insertion(+), 8 deletions(-) diff --git a/lib/plugins/exchange/binanceus.js b/lib/plugins/exchange/binanceus.js index fb98998f..78df0263 100644 --- a/lib/plugins/exchange/binanceus.js +++ b/lib/plugins/exchange/binanceus.js @@ -15,6 +15,4 @@ const loadConfig = (account) => { return { ...mapped, timeout: 3000 } } -// Documentation mentions a mandatory field 'time', not sure how ccxt handles this, probably works if we send this via options - module.exports = { loadConfig, REQUIRED_CONFIG_FIELDS, CRYPTO, FIAT, ORDER_TYPE } diff --git a/lib/plugins/exchange/cex.js b/lib/plugins/exchange/cex.js index ae3b2885..8405996b 100644 --- a/lib/plugins/exchange/cex.js +++ b/lib/plugins/exchange/cex.js @@ -15,7 +15,4 @@ const loadConfig = (account) => { return { ...mapped, timeout: 3000 } } -// Documentation mentions a field 'nonce', doesn't specify if it's mandatory -// or not but we should pay attention to this when testing - module.exports = { loadConfig, REQUIRED_CONFIG_FIELDS, CRYPTO, FIAT, ORDER_TYPE } diff --git a/lib/plugins/exchange/ftx.js b/lib/plugins/exchange/ftx.js index f9e154e8..a8cf8df3 100644 --- a/lib/plugins/exchange/ftx.js +++ b/lib/plugins/exchange/ftx.js @@ -6,7 +6,6 @@ const { ORDER_TYPES } = require('./consts') const ORDER_TYPE = ORDER_TYPES.MARKET const { BTC, BCH, ETH, LTC, USDT } = COINS const CRYPTO = [BTC, ETH, LTC, BCH, USDT] -// ftx supports EUR as well but only for certain cryptos: ETH, BTC const FIAT = ['USD'] const REQUIRED_CONFIG_FIELDS = ['apiKey', 'privateKey'] diff --git a/new-lamassu-admin/src/pages/Wizard/components/Wallet/ChooseExchange.js b/new-lamassu-admin/src/pages/Wizard/components/Wallet/ChooseExchange.js index 10b9b51c..98760107 100644 --- a/new-lamassu-admin/src/pages/Wizard/components/Wallet/ChooseExchange.js +++ b/new-lamassu-admin/src/pages/Wizard/components/Wallet/ChooseExchange.js @@ -38,8 +38,7 @@ const SAVE_ACCOUNTS = gql` } ` -const isConfigurable = it => - R.contains(it)(['kraken', 'itbit', 'bitstamp', 'binanceus', 'cex', 'ftx']) +const isConfigurable = it => !R.contains(it)(['mock-exchange']) const ChooseExchange = ({ data: currentData, addData }) => { const classes = useStyles()