Merge branch 'dev' into releases/v10.1

This commit is contained in:
Rafael Taranto 2025-01-07 14:47:10 +00:00 committed by GitHub
commit 320e76fdae
393 changed files with 11183 additions and 31834 deletions

View file

@ -23,7 +23,8 @@ const ALL = {
bitpay: bitpay,
coinbase: {
CRYPTO: [BTC, ETH, LTC, DASH, ZEC, BCH, USDT, USDT_TRON, TRX, LN],
FIAT: 'ALL_CURRENCIES'
FIAT: 'ALL_CURRENCIES',
DEFAULT_FIAT_MARKET: 'EUR'
},
binance: binance,
bitfinex: bitfinex
@ -33,11 +34,8 @@ function buildMarket (fiatCode, cryptoCode, serviceName) {
if (!_.includes(cryptoCode, ALL[serviceName].CRYPTO)) {
throw new Error('Unsupported crypto: ' + cryptoCode)
}
const fiatSupported = ALL[serviceName].FIAT
if (fiatSupported !== 'ALL_CURRENCIES' && !_.includes(fiatCode, fiatSupported)) {
logger.info('Building a market for an unsupported fiat. Defaulting to EUR market')
return cryptoCode + '/' + 'EUR'
}
if (_.isNil(fiatCode)) throw new Error('Market pair building failed: Missing fiat code')
return cryptoCode + '/' + fiatCode
}
@ -51,4 +49,8 @@ function isConfigValid (config, fields) {
return _.every(it => it || it === 0)(values)
}
module.exports = { buildMarket, ALL, verifyFiatSupport, isConfigValid }
function defaultFiatMarket (serviceName) {
return ALL[serviceName].DEFAULT_FIAT_MARKET
}
module.exports = { buildMarket, ALL, verifyFiatSupport, isConfigValid, defaultFiatMarket }

View file

@ -6,8 +6,9 @@ const { ORDER_TYPES } = require('./consts')
const ORDER_TYPE = ORDER_TYPES.MARKET
const { BTC, BCH, XMR, ETH, LTC, ZEC, LN } = COINS
const CRYPTO = [BTC, ETH, LTC, ZEC, BCH, XMR, LN]
const FIAT = ['USD', 'EUR']
const REQUIRED_CONFIG_FIELDS = ['apiKey', 'privateKey']
const FIAT = ['EUR']
const DEFAULT_FIAT_MARKET = 'EUR'
const REQUIRED_CONFIG_FIELDS = ['apiKey', 'privateKey', 'currencyMarket']
const loadConfig = (account) => {
const mapper = {
@ -17,4 +18,4 @@ const loadConfig = (account) => {
return { ...mapped, timeout: 3000 }
}
module.exports = { loadConfig, REQUIRED_CONFIG_FIELDS, CRYPTO, FIAT, ORDER_TYPE }
module.exports = { loadConfig, DEFAULT_FIAT_MARKET, REQUIRED_CONFIG_FIELDS, CRYPTO, FIAT, ORDER_TYPE }

View file

@ -7,7 +7,8 @@ const ORDER_TYPE = ORDER_TYPES.MARKET
const { BTC, BCH, DASH, ETH, LTC, ZEC, USDT, USDT_TRON, LN } = COINS
const CRYPTO = [BTC, ETH, LTC, DASH, ZEC, BCH, USDT, USDT_TRON, LN]
const FIAT = ['USD']
const REQUIRED_CONFIG_FIELDS = ['apiKey', 'privateKey']
const DEFAULT_FIAT_MARKET = 'USD'
const REQUIRED_CONFIG_FIELDS = ['apiKey', 'privateKey', 'currencyMarket']
const loadConfig = (account) => {
const mapper = {
@ -17,4 +18,4 @@ const loadConfig = (account) => {
return { ...mapped, timeout: 3000 }
}
module.exports = { loadConfig, REQUIRED_CONFIG_FIELDS, CRYPTO, FIAT, ORDER_TYPE }
module.exports = { loadConfig, DEFAULT_FIAT_MARKET, REQUIRED_CONFIG_FIELDS, CRYPTO, FIAT, ORDER_TYPE }

View file

@ -7,6 +7,7 @@ const ORDER_TYPE = ORDER_TYPES.MARKET
const { BTC, ETH, LTC, BCH, USDT, LN } = COINS
const CRYPTO = [BTC, ETH, LTC, BCH, USDT, LN]
const FIAT = ['USD', 'EUR']
const DEFAULT_FIAT_MARKET = 'EUR'
const AMOUNT_PRECISION = 8
const REQUIRED_CONFIG_FIELDS = ['key', 'secret']
@ -18,4 +19,4 @@ const loadConfig = (account) => {
return { ...mapped, timeout: 3000 }
}
module.exports = { loadConfig, REQUIRED_CONFIG_FIELDS, CRYPTO, FIAT, ORDER_TYPE, AMOUNT_PRECISION }
module.exports = { loadConfig, REQUIRED_CONFIG_FIELDS, DEFAULT_FIAT_MARKET, CRYPTO, FIAT, ORDER_TYPE, AMOUNT_PRECISION }

View file

@ -7,8 +7,9 @@ const ORDER_TYPE = ORDER_TYPES.MARKET
const { BTC, ETH, LTC, BCH, USDT, LN } = COINS
const CRYPTO = [BTC, ETH, LTC, BCH, USDT, LN]
const FIAT = ['USD', 'EUR']
const DEFAULT_FIAT_MARKET = 'EUR'
const AMOUNT_PRECISION = 8
const REQUIRED_CONFIG_FIELDS = ['key', 'secret', 'clientId']
const REQUIRED_CONFIG_FIELDS = ['key', 'secret', 'clientId', 'currencyMarket']
const loadConfig = (account) => {
const mapper = {
@ -19,4 +20,4 @@ const loadConfig = (account) => {
return { ...mapped, timeout: 3000 }
}
module.exports = { loadConfig, REQUIRED_CONFIG_FIELDS, CRYPTO, FIAT, ORDER_TYPE, AMOUNT_PRECISION }
module.exports = { loadConfig, DEFAULT_FIAT_MARKET, REQUIRED_CONFIG_FIELDS, CRYPTO, FIAT, ORDER_TYPE, AMOUNT_PRECISION }

View file

@ -1,9 +1,13 @@
const { utils: coinUtils } = require('@lamassu/coins')
const _ = require('lodash/fp')
const ccxt = require('ccxt')
const mem = require('mem')
const { buildMarket, ALL, isConfigValid } = require('../common/ccxt')
const { ORDER_TYPES } = require('./consts')
const logger = require('../../logger')
const { currencies } = require('../../new-admin/config')
const T = require('../../time')
const DEFAULT_PRICE_PRECISION = 2
const DEFAULT_AMOUNT_PRECISION = 8
@ -18,7 +22,8 @@ function trade (side, account, tradeEntry, exchangeName) {
const { USER_REF, loadOptions, loadConfig = _.noop, REQUIRED_CONFIG_FIELDS, ORDER_TYPE, AMOUNT_PRECISION } = exchangeConfig
if (!isConfigValid(account, REQUIRED_CONFIG_FIELDS)) throw Error('Invalid config')
const symbol = buildMarket(fiatCode, cryptoCode, exchangeName)
const selectedFiatMarket = account.currencyMarket
const symbol = buildMarket(selectedFiatMarket, cryptoCode, exchangeName)
const precision = _.defaultTo(DEFAULT_AMOUNT_PRECISION, AMOUNT_PRECISION)
const amount = coinUtils.toUnit(cryptoAtoms, cryptoCode).toFixed(precision)
const accountOptions = _.isFunction(loadOptions) ? loadOptions(account) : {}
@ -50,4 +55,38 @@ function calculatePrice (side, amount, orderBook) {
throw new Error('Insufficient market depth')
}
module.exports = { trade }
function _getMarkets (exchangeName, availableCryptos) {
const prunedCryptos = _.compose(_.uniq, _.map(coinUtils.getEquivalentCode))(availableCryptos)
try {
const exchange = new ccxt[exchangeName]()
const cryptosToQuoteAgainst = ['USDT']
const currencyCodes = _.concat(_.map(it => it.code, currencies), cryptosToQuoteAgainst)
return exchange.fetchMarkets()
.then(_.filter(it => (it.type === 'spot' || it.spot)))
.then(res =>
_.reduce((acc, value) => {
if (_.includes(value.base, prunedCryptos) && _.includes(value.quote, currencyCodes)) {
if (value.quote === value.base) return acc
if (_.isNil(acc[value.quote])) {
return { ...acc, [value.quote]: [value.base] }
}
acc[value.quote].push(value.base)
}
return acc
}, {}, res)
)
} catch (e) {
logger.debug(`No CCXT exchange found for ${exchangeName}`)
}
}
const getMarkets = mem(_getMarkets, {
maxAge: T.week,
cacheKey: (exchangeName, availableCryptos) => exchangeName
})
module.exports = { trade, getMarkets }

View file

@ -7,7 +7,8 @@ const ORDER_TYPE = ORDER_TYPES.MARKET
const { BTC, BCH, DASH, ETH, LTC, USDT, TRX, USDT_TRON, LN } = COINS
const CRYPTO = [BTC, ETH, LTC, DASH, BCH, USDT, TRX, USDT_TRON, LN]
const FIAT = ['USD', 'EUR']
const REQUIRED_CONFIG_FIELDS = ['apiKey', 'privateKey']
const DEFAULT_FIAT_MARKET = 'EUR'
const REQUIRED_CONFIG_FIELDS = ['apiKey', 'privateKey', 'currencyMarket']
const loadConfig = (account) => {
const mapper = {
@ -17,4 +18,4 @@ const loadConfig = (account) => {
return { ...mapped, timeout: 3000 }
}
module.exports = { loadConfig, REQUIRED_CONFIG_FIELDS, CRYPTO, FIAT, ORDER_TYPE }
module.exports = { loadConfig, DEFAULT_FIAT_MARKET, REQUIRED_CONFIG_FIELDS, CRYPTO, FIAT, ORDER_TYPE }

View file

@ -7,8 +7,9 @@ const ORDER_TYPE = ORDER_TYPES.LIMIT
const { BTC, ETH, USDT, LN } = COINS
const CRYPTO = [BTC, ETH, USDT, LN]
const FIAT = ['USD']
const DEFAULT_FIAT_MARKET = 'USD'
const AMOUNT_PRECISION = 4
const REQUIRED_CONFIG_FIELDS = ['clientKey', 'clientSecret', 'userId', 'walletId']
const REQUIRED_CONFIG_FIELDS = ['clientKey', 'clientSecret', 'userId', 'walletId', 'currencyMarket']
const loadConfig = (account) => {
const mapper = {
@ -21,4 +22,4 @@ const loadConfig = (account) => {
}
const loadOptions = ({ walletId }) => ({ walletId })
module.exports = { loadOptions, loadConfig, REQUIRED_CONFIG_FIELDS, CRYPTO, FIAT, ORDER_TYPE, AMOUNT_PRECISION }
module.exports = { loadOptions, loadConfig, DEFAULT_FIAT_MARKET, REQUIRED_CONFIG_FIELDS, CRYPTO, FIAT, ORDER_TYPE, AMOUNT_PRECISION }

View file

@ -7,8 +7,9 @@ const ORDER_TYPE = ORDER_TYPES.MARKET
const { BTC, BCH, DASH, ETH, LTC, ZEC, XMR, USDT, TRX, USDT_TRON, LN } = COINS
const CRYPTO = [BTC, ETH, LTC, DASH, ZEC, BCH, XMR, USDT, TRX, USDT_TRON, LN]
const FIAT = ['USD', 'EUR']
const DEFAULT_FIAT_MARKET = 'EUR'
const AMOUNT_PRECISION = 6
const REQUIRED_CONFIG_FIELDS = ['apiKey', 'privateKey']
const REQUIRED_CONFIG_FIELDS = ['apiKey', 'privateKey', 'currencyMarket']
const USER_REF = 'userref'
const loadConfig = (account) => {
@ -26,4 +27,4 @@ const loadConfig = (account) => {
const loadOptions = () => ({ expiretm: '+60' })
module.exports = { USER_REF, loadOptions, loadConfig, REQUIRED_CONFIG_FIELDS, CRYPTO, FIAT, ORDER_TYPE, AMOUNT_PRECISION }
module.exports = { USER_REF, loadOptions, loadConfig, DEFAULT_FIAT_MARKET, REQUIRED_CONFIG_FIELDS, CRYPTO, FIAT, ORDER_TYPE, AMOUNT_PRECISION }

View file

@ -1,7 +1,7 @@
const ccxt = require('ccxt')
const BN = require('../../bn')
const { buildMarket, verifyFiatSupport } = require('../common/ccxt')
const { buildMarket, verifyFiatSupport, defaultFiatMarket } = require('../common/ccxt')
const { getRate } = require('../../../lib/forex')
const RETRIES = 2
@ -33,7 +33,7 @@ function ticker (fiatCode, cryptoCode, tickerName) {
return getRate(RETRIES, fiatCode)
.then(({ fxRate }) => {
try {
return getCurrencyRates(ticker, 'USD', cryptoCode)
return getCurrencyRates(ticker, defaultFiatMarket(tickerName), cryptoCode)
.then(res => ({
rates: {
ask: res.rates.ask.times(fxRate),