diff --git a/src/index.ts b/src/index.ts index 8b1d9ff..66a1771 100644 --- a/src/index.ts +++ b/src/index.ts @@ -30,6 +30,7 @@ import { getAliceBobEstimationPayload } from './utils/alice-bob/get-alice-bob-es import { getAliceBobOrderInfo } from './utils/alice-bob/get-alice-bob-order-info'; import { getAliceBobPairInfo } from './utils/alice-bob/get-alice-bob-pair-info'; import { getAliceBobPairsInfo } from './utils/alice-bob/get-alice-bob-pairs-info'; +import { btcExchangeRateProvider, tezExchangeRateProvider } from './utils/coingecko'; import { CodedError } from './utils/errors'; import { coinGeckoTokens } from './utils/gecko-tokens'; import { getExternalApiErrorPayload, isDefined, isNonEmptyString } from './utils/helpers'; @@ -37,7 +38,6 @@ import logger from './utils/logger'; import { getSignedMoonPayUrl } from './utils/moonpay/get-signed-moonpay-url'; import { getSigningNonce } from './utils/signing-nonce'; import SingleQueryDataProvider from './utils/SingleQueryDataProvider'; -import { tezExchangeRateProvider } from './utils/tezos'; import { getExchangeRates } from './utils/tokens'; const PINO_LOGGER = { @@ -175,6 +175,7 @@ app.get('/api/abtest', (_, res) => { }); app.get('/api/exchange-rates/tez', makeProviderDataRequestHandler(tezExchangeRateProvider)); +app.get('/api/exchange-rates/btc', makeProviderDataRequestHandler(btcExchangeRateProvider)); app.get('/api/exchange-rates', async (_req, res) => { const tokensExchangeRates = await getExchangeRates(); diff --git a/src/utils/coingecko.ts b/src/utils/coingecko.ts index b4abf9c..089a2da 100644 --- a/src/utils/coingecko.ts +++ b/src/utils/coingecko.ts @@ -1,4 +1,7 @@ -import { range } from './helpers'; +import { AxiosError } from 'axios'; + +import { isDefined, range } from './helpers'; +import logger from './logger'; import { makeBuildQueryFn } from './makeBuildQueryFn'; import SingleQueryDataProvider from './SingleQueryDataProvider'; @@ -89,3 +92,29 @@ export const getMarketsBySymbols = async (symbols: string[]) => { return chunks.flat(); }; + +const createCoingeckoExchangeRateProvider = (tokenSymbol: string) => + new SingleQueryDataProvider(60000, async () => { + try { + const [market] = await getMarketsBySymbols([tokenSymbol]); + + return market.current_price; + } catch (e) { + if (!(e instanceof AxiosError)) { + logger.error(`Request for ${tokenSymbol} exchange rate failed with unknown error`); + } else if (isDefined(e.response) && isDefined(e.response.data)) { + logger.error( + `Request for ${tokenSymbol} exchange rate failed with status ${e.response.status} and message ${e.response.data}` + ); + } else if (isDefined(e.response) && isDefined(e.response.status)) { + logger.error(`Request for ${tokenSymbol} exchange rate failed with status ${e.response.status}`); + } else { + logger.error(`Request for ${tokenSymbol} exchange rate failed without response`); + } + + throw e; + } + }); + +export const tezExchangeRateProvider = createCoingeckoExchangeRateProvider('xtz'); +export const btcExchangeRateProvider = createCoingeckoExchangeRateProvider('btc'); diff --git a/src/utils/tezos.ts b/src/utils/tezos.ts index 2d098c6..5613fde 100644 --- a/src/utils/tezos.ts +++ b/src/utils/tezos.ts @@ -1,13 +1,8 @@ import { compose, MichelCodecPacker, Signer, TezosToolkit } from '@taquito/taquito'; import { tzip12 } from '@taquito/tzip12'; import { tzip16 } from '@taquito/tzip16'; -import { AxiosError } from 'axios'; import memoizee from 'memoizee'; -import { getMarketsBySymbols } from './coingecko'; -import { isDefined } from './helpers'; -import logger from './logger'; -import SingleQueryDataProvider from './SingleQueryDataProvider'; import { BcdTokenData } from './tzkt'; const RPC_URL = process.env.RPC_URL ?? 'https://mainnet-node.madfish.solutions'; @@ -54,30 +49,6 @@ export const getStorage = memoizee( { promise: true, maxAge: 30000 } ); -const getTezExchangeRate = async () => { - try { - const [xtzMarket] = await getMarketsBySymbols(['xtz']); - - return xtzMarket.current_price; - } catch (e) { - if (!(e instanceof AxiosError)) { - logger.error('Request for TEZ exchange rate failed with unknown error'); - } else if (isDefined(e.response) && isDefined(e.response.data)) { - logger.error( - `Request for TEZ exchange rate failed with status ${e.response.status} and message ${e.response.data}` - ); - } else if (isDefined(e.response) && isDefined(e.response.status)) { - logger.error(`Request for TEZ exchange rate failed with status ${e.response.status}`); - } else { - logger.error('Request for TEZ exchange rate failed without response'); - } - - throw e; - } -}; - -export const tezExchangeRateProvider = new SingleQueryDataProvider(60000, getTezExchangeRate); - export class MetadataParseError extends Error {} export const getTokenMetadata = memoizee( diff --git a/src/utils/tokens.ts b/src/utils/tokens.ts index c468e6d..64d63df 100644 --- a/src/utils/tokens.ts +++ b/src/utils/tokens.ts @@ -1,10 +1,10 @@ import { BigNumber } from 'bignumber.js'; import { redisClient } from '../redis'; +import { tezExchangeRateProvider } from './coingecko'; import { isDefined } from './helpers'; import logger from './logger'; import SingleQueryDataProvider, { SingleQueryDataProviderState } from './SingleQueryDataProvider'; -import { tezExchangeRateProvider } from './tezos'; import { getThreeRouteExchangeRates, getThreeRouteTokens,