import { AssetBuyer, AssetBuyerError, BuyQuote } from '@0x/asset-buyer'; import { BigNumber } from '@0x/utils'; import { Web3Wrapper } from '@0x/web3-wrapper'; import * as _ from 'lodash'; import { Dispatch } from 'redux'; import { oc } from 'ts-optchain'; import { Action, actions } from '../redux/actions'; import { AffiliateInfo, ERC20Asset, QuoteFetchedVia } from '../types'; import { analytics } from '../util/analytics'; import { assetUtils } from '../util/asset'; import { errorFlasher } from '../util/error_flasher'; export const buyQuoteUpdater = { updateBuyQuoteAsync: async ( assetBuyer: AssetBuyer, dispatch: Dispatch, asset: ERC20Asset, assetUnitAmount: BigNumber, options: { setPending: boolean; dispatchErrors: boolean; fetchedVia: QuoteFetchedVia; affiliateInfo?: AffiliateInfo; }, ): Promise => { // get a new buy quote. const baseUnitValue = Web3Wrapper.toBaseUnitAmount(assetUnitAmount, asset.metaData.decimals); if (options.setPending) { // mark quote as pending dispatch(actions.setQuoteRequestStatePending()); } const feePercentage = oc(options.affiliateInfo).feePercentage(); let newBuyQuote: BuyQuote | undefined; try { newBuyQuote = await assetBuyer.getBuyQuoteAsync(asset.assetData, baseUnitValue, { feePercentage }); } catch (error) { if (options.dispatchErrors) { dispatch(actions.setQuoteRequestStateFailure()); analytics.trackQuoteError( error.message ? error.message : 'other', asset.metaData.name, asset.assetData, assetUnitAmount, options.fetchedVia, ); let errorMessage; if (error.message === AssetBuyerError.InsufficientAssetLiquidity) { const assetName = assetUtils.bestNameForAsset(asset, 'of this asset'); errorMessage = `Not enough ${assetName} available`; } else if (error.message === AssetBuyerError.InsufficientZrxLiquidity) { errorMessage = 'Not enough ZRX available'; } else if ( error.message === AssetBuyerError.StandardRelayerApiError || error.message.startsWith(AssetBuyerError.AssetUnavailable) ) { const assetName = assetUtils.bestNameForAsset(asset, 'This asset'); errorMessage = `${assetName} is currently unavailable`; } if (!_.isUndefined(errorMessage)) { errorFlasher.flashNewErrorMessage(dispatch, errorMessage); } else { throw error; } } // TODO: report to error reporter on else return; } // We have a successful new buy quote errorFlasher.clearError(dispatch); // invalidate the last buy quote. dispatch(actions.updateLatestBuyQuote(newBuyQuote)); analytics.trackQuoteFetched(newBuyQuote, options.fetchedVia); }, };