Skip to content

Commit

Permalink
[REF] use Moralis sdk for token rates
Browse files Browse the repository at this point in the history
  • Loading branch information
gabrielbazan7 committed Mar 26, 2024
1 parent 713b7de commit b88ae5e
Show file tree
Hide file tree
Showing 6 changed files with 210 additions and 119 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@
"lodash.uniqby": "4.7.0",
"mixpanel-react-native": "2.3.1",
"moment": "2.29.1",
"moralis": "2.14.3",
"moralis": "2.25.2",
"papaparse": "5.3.2",
"path-browserify": "1.0.1",
"react": "18.2.0",
Expand Down
1 change: 1 addition & 0 deletions scripts/allowed-url-prefixes.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ const allowedUrlPrefixes = [
'https://api.zenledger.io/',
'https://api.blockcypher.com/v1/',
'https://api.fullstack.cash/v5/',
'https://deep-index.moralis.io/api/v2.2/',
].concat(developmentOnlyAllowedUrlPrefixes);

const allowedUrlPrefixString = allowedUrlPrefixes.join(',');
Expand Down
21 changes: 15 additions & 6 deletions src/store/buy-crypto/buy-crypto.effects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,12 @@ export const calculateAltFiatToUsd =
};

export const calculateUsdToAltFiat =
(usdAmount: number, altFiatCurrency: string): Effect<number | undefined> =>
(
usdAmount: number,
altFiatCurrency: string,
decimalPrecision: number = 2,
shouldSkipLogging?: boolean,
): Effect<number | undefined> =>
(dispatch, getState) => {
const state = getState();
const allRates = state.RATE.rates;
Expand All @@ -63,12 +68,16 @@ export const calculateUsdToAltFiat =

if (rateBtcAlt && rateBtcUsd?.rate && rateBtcUsd?.rate > 0) {
const rateAltUsd = rateBtcAlt.rate / rateBtcUsd.rate;
const equivalentAmount = +(usdAmount * rateAltUsd).toFixed(2);
dispatch(
LogActions.debug(
`${usdAmount} USD => ${equivalentAmount} ${altFiatCurrency}`,
),
const equivalentAmount = +(usdAmount * rateAltUsd).toFixed(
decimalPrecision,
);
if (!shouldSkipLogging) {
dispatch(
LogActions.debug(
`${usdAmount} USD => ${equivalentAmount} ${altFiatCurrency}`,
),
);
}
return equivalentAmount;
} else {
dispatch(
Expand Down
49 changes: 48 additions & 1 deletion src/store/moralis/moralis.effects.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import Moralis from 'moralis';
import {EvmChain} from '@moralisweb3/common-evm-utils';
import {
EvmChain,
EvmTokenPriceItemInput,
GetMultipleTokenPricesOperationResponseJSON,
GetMultipleTokenPricesOperationRequest,
} from '@moralisweb3/common-evm-utils';
import {LogActions} from '../log';
import {Effect} from '..';
import axios from 'axios';
Expand Down Expand Up @@ -395,6 +400,48 @@ export const getERC20TokenPrice =
}
};

export const getMultipleTokenPrices =
({
addresses,
chain,
}: {
addresses: EvmTokenPriceItemInput[];
chain: string;
}): Effect<Promise<GetMultipleTokenPricesOperationResponseJSON>> =>
async dispatch => {
try {
const query = {
chain: MORALIS_EVM_CHAIN[chain],
include: 'percent_change',
} as GetMultipleTokenPricesOperationRequest;
const body = {tokens: addresses};
const {raw} = await Moralis.EvmApi.token.getMultipleTokenPrices(
query,
body,
);

dispatch(
LogActions.info(
'[moralis/getMultipleTokenPrices]: get ERC20 token price successfully',
),
);
return raw;
} catch (e) {
let errorStr;
if (e instanceof Error) {
errorStr = e.message;
} else {
errorStr = JSON.stringify(e);
}
dispatch(
LogActions.error(
`[moralis/getMultipleTokenPrices]: an error occurred while getting ERC20 token price: ${errorStr}`,
),
);
throw e;
}
};

export const getERC20TokenBalanceByWallet =
({address, chain}: {address: string; chain: string}): Effect<Promise<any>> =>
async dispatch => {
Expand Down
63 changes: 43 additions & 20 deletions src/store/wallet/effects/rates/rates.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,12 @@ import {
getCurrencyAbbreviation,
addTokenChainSuffix,
} from '../../../../utils/helper-methods';
import {getMultipleTokenPrices} from '../../../../store/moralis/moralis.effects';
import {
EvmTokenPriceItemInput,
EvmErc20PriceJSON,
} from '@moralisweb3/common-evm-utils';
import {calculateUsdToAltFiat} from '../../../../store/buy-crypto/buy-crypto.effects';

export const getPriceHistory =
(defaultAltCurrencyIsoCode: string): Effect =>
Expand Down Expand Up @@ -210,6 +216,8 @@ export const getTokenRates =

let tokenRates: {[key in string]: any} = {};
let tokenLastDayRates: {[key in string]: any} = {};
const shouldSkipLogging = true;
const decimalPrecision = 6;

try {
const {
Expand All @@ -229,7 +237,7 @@ export const getTokenRates =
const altCurrencies = altCurrencyList.map(altCurrency =>
altCurrency.isoCode.toLowerCase(),
);
const chunkArray = (array: string[], size: number) => {
const chunkArray = (array: EvmTokenPriceItemInput[], size: number) => {
const chunked_arr = [];
for (let i = 0; i < array.length; i += size) {
chunked_arr.push(array.slice(i, i + size));
Expand All @@ -240,19 +248,29 @@ export const getTokenRates =
for (const chain of SUPPORTED_EVM_COINS) {
const contractAddresses = dispatch(getContractAddresses(chain));
if (contractAddresses?.length > 0) {
const chunks = chunkArray(contractAddresses, 5);
const formattedAddresses = contractAddresses.map(address => ({
tokenAddress: address,
})) as EvmTokenPriceItemInput[]; // format addresses for Moralis
const chunks = chunkArray(formattedAddresses, 25);
for (const chunk of chunks) {
const url = `${BASE_BWS_URL}/v1/service/coinGecko/getRates/${chunk.join(
',',
)}/${altCurrencies.join(',')}/${chain}`;
dispatch(
LogActions.debug(`getTokenRates: get request to: ${url}`),
const data = await dispatch(
getMultipleTokenPrices({addresses: chunk, chain}),
);
const {data} = await axios.get(url);
dispatch(LogActions.debug('getTokenRates: success get request'));
Object.entries(data).map(([key, value]: [string, any]) => {
const formattedTokenAddress = addTokenChainSuffix(key, chain);
data.forEach((tokenInfo: EvmErc20PriceJSON) => {
const {
usdPrice,
tokenAddress,
'24hrPercentChange': percentChange,
} = tokenInfo;
const lastUpdate = Date.now();

if (!usdPrice || !tokenAddress || !percentChange) {
return;
}
const formattedTokenAddress = addTokenChainSuffix(
tokenAddress.toLowerCase(),
chain,
);
// only save token rates if exist in tokens list
if (tokensOptsByAddress[formattedTokenAddress]) {
const tokenName = getCurrencyAbbreviation(
Expand All @@ -263,27 +281,32 @@ export const getTokenRates =
tokenLastDayRates[tokenName] = [];

altCurrencies.forEach(altCurrency => {
const rate =
dispatch(
calculateUsdToAltFiat(
usdPrice,
altCurrency,
decimalPrecision,
shouldSkipLogging,
),
) || 0;
tokenRates[tokenName].push({
code: altCurrency.toUpperCase(),
fetchedOn: value.last_updated_at,
fetchedOn: lastUpdate,
name: tokensOptsByAddress[formattedTokenAddress]?.symbol,
rate: value[altCurrency],
ts: value.last_updated_at,
rate,
ts: lastUpdate,
});

const yesterday = moment
.unix(value.last_updated_at)
.unix(lastUpdate)
.subtract(1, 'days')
.unix();
tokenLastDayRates[tokenName].push({
code: altCurrency.toUpperCase(),
fetchedOn: yesterday,
name: tokensOptsByAddress[formattedTokenAddress]?.symbol,
rate:
value[altCurrency] +
(value[altCurrency] *
value[`${altCurrency}_24h_change`]) /
100,
rate: Number(percentChange) * rate,
ts: yesterday,
});
});
Expand Down
Loading

0 comments on commit b88ae5e

Please sign in to comment.