Use existing functions instead of writing our own
This commit is contained in:
		@@ -99,13 +99,13 @@ export class ZeroExInstantProvider extends React.Component<ZeroExInstantProvider
 | 
			
		||||
            asyncData.fetchAvailableAssetDatasAndDispatchToStore(this._store);
 | 
			
		||||
        }
 | 
			
		||||
        // tslint:disable-next-line:no-floating-promises
 | 
			
		||||
        // asyncData.fetchAccountInfoAndDispatchToStore(this._store);
 | 
			
		||||
 | 
			
		||||
        this._accountUpdateHeartbeat = generateAccountHeartbeater(this._store);
 | 
			
		||||
        this._accountUpdateHeartbeat = generateAccountHeartbeater(this._store, true);
 | 
			
		||||
        this._accountUpdateHeartbeat.start(ACCOUNT_UPDATE_INTERVAL_TIME_MS);
 | 
			
		||||
 | 
			
		||||
        this._buyQuoteHeartbeat = generateBuyQuoteHeartbeater(this._store);
 | 
			
		||||
        this._buyQuoteHeartbeat = generateBuyQuoteHeartbeater(this._store, false);
 | 
			
		||||
        this._buyQuoteHeartbeat.start(BUY_QUOTE_UPDATE_INTERVAL_TIME_MS);
 | 
			
		||||
        asyncData.fetchCurrentBuyQuoteAndDispatchToStore(this._store, true);
 | 
			
		||||
 | 
			
		||||
        // warm up the gas price estimator cache just in case we can't
 | 
			
		||||
        // grab the gas price estimate when submitting the transaction
 | 
			
		||||
 
 | 
			
		||||
@@ -11,7 +11,6 @@ import { Action, actions } from '../redux/actions';
 | 
			
		||||
import { State } from '../redux/reducer';
 | 
			
		||||
import { ColorOption } from '../style/theme';
 | 
			
		||||
import { AffiliateInfo, ERC20Asset, OrderProcessState } from '../types';
 | 
			
		||||
import { updateBuyQuoteOrFlashErrorAsync } from '../util/buy_quote_fetcher';
 | 
			
		||||
import { buyQuoteUpdater } from '../util/buy_quote_updater';
 | 
			
		||||
 | 
			
		||||
export interface SelectedERC20AssetAmountInputProps {
 | 
			
		||||
@@ -68,10 +67,9 @@ const mapStateToProps = (state: State, _ownProps: SelectedERC20AssetAmountInputP
 | 
			
		||||
    };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// TODO: change to set pending to true
 | 
			
		||||
const debouncedUpdateBuyQuoteAsync = _.debounce(buyQuoteUpdater.updateBuyQuoteAsync.bind(buyQuoteUpdater), 200, {
 | 
			
		||||
    trailing: true,
 | 
			
		||||
});
 | 
			
		||||
}) as typeof buyQuoteUpdater.updateBuyQuoteAsync;
 | 
			
		||||
 | 
			
		||||
const mapDispatchToProps = (
 | 
			
		||||
    dispatch: Dispatch<Action>,
 | 
			
		||||
@@ -89,7 +87,7 @@ const mapDispatchToProps = (
 | 
			
		||||
            // even if it's debounced, give them the illusion it's loading
 | 
			
		||||
            dispatch(actions.setQuoteRequestStatePending());
 | 
			
		||||
            // tslint:disable-next-line:no-floating-promises
 | 
			
		||||
            debouncedUpdateBuyQuoteAsync(assetBuyer, dispatch, asset, value, affiliateInfo);
 | 
			
		||||
            debouncedUpdateBuyQuoteAsync(assetBuyer, dispatch, asset, value, true, affiliateInfo);
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
@@ -74,7 +74,7 @@ export const asyncData = {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    fetchCurrentBuyQuoteAndDispatchToStore: async (store: Store) => {
 | 
			
		||||
    fetchCurrentBuyQuoteAndDispatchToStore: async (store: Store, setPending: boolean) => {
 | 
			
		||||
        const { providerState, selectedAsset, selectedAssetAmount, affiliateInfo } = store.getState();
 | 
			
		||||
        const assetBuyer = providerState.assetBuyer;
 | 
			
		||||
        if (
 | 
			
		||||
@@ -87,6 +87,7 @@ export const asyncData = {
 | 
			
		||||
                store.dispatch,
 | 
			
		||||
                selectedAsset as ERC20Asset,
 | 
			
		||||
                selectedAssetAmount,
 | 
			
		||||
                setPending,
 | 
			
		||||
                affiliateInfo,
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -1,75 +0,0 @@
 | 
			
		||||
// TODO: rename file and export object
 | 
			
		||||
// TODO: delete this
 | 
			
		||||
 | 
			
		||||
import { AssetBuyer, AssetBuyerError, BuyQuote } from '@0x/asset-buyer';
 | 
			
		||||
import { AssetProxyId } from '@0x/types';
 | 
			
		||||
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 { State } from '../redux/reducer';
 | 
			
		||||
import { AffiliateInfo, ERC20Asset } from '../types';
 | 
			
		||||
import { assetUtils } from '../util/asset';
 | 
			
		||||
 | 
			
		||||
import { errorFlasher } from './error_flasher';
 | 
			
		||||
 | 
			
		||||
export const updateBuyQuoteOrFlashErrorAsync = async (
 | 
			
		||||
    assetBuyer: AssetBuyer,
 | 
			
		||||
    asset: ERC20Asset,
 | 
			
		||||
    assetAmount: BigNumber,
 | 
			
		||||
    dispatch: Dispatch<Action>,
 | 
			
		||||
    affiliateInfo?: AffiliateInfo,
 | 
			
		||||
) => {
 | 
			
		||||
    // get a new buy quote.
 | 
			
		||||
    const baseUnitValue = Web3Wrapper.toBaseUnitAmount(assetAmount, asset.metaData.decimals);
 | 
			
		||||
 | 
			
		||||
    const feePercentage = oc(affiliateInfo).feePercentage();
 | 
			
		||||
    let newBuyQuote: BuyQuote | undefined;
 | 
			
		||||
    try {
 | 
			
		||||
        newBuyQuote = await assetBuyer.getBuyQuoteAsync(asset.assetData, baseUnitValue, { feePercentage });
 | 
			
		||||
    } catch (error) {
 | 
			
		||||
        dispatch(actions.setQuoteRequestStateFailure());
 | 
			
		||||
        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;
 | 
			
		||||
        }
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    // We have a successful new buy quote
 | 
			
		||||
    errorFlasher.clearError(dispatch);
 | 
			
		||||
    // invalidate the last buy quote.
 | 
			
		||||
    dispatch(actions.updateLatestBuyQuote(newBuyQuote));
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const updateBuyQuoteOrFlashErrorAsyncForState = async (state: State, dispatch: Dispatch<Action>) => {
 | 
			
		||||
    const { selectedAsset, selectedAssetAmount, affiliateInfo } = state;
 | 
			
		||||
    const assetBuyer = state.providerState.assetBuyer;
 | 
			
		||||
 | 
			
		||||
    if (selectedAsset && selectedAssetAmount && selectedAsset.metaData.assetProxyId === AssetProxyId.ERC20) {
 | 
			
		||||
        // TODO: maybe dont do in the case of an error showing
 | 
			
		||||
        updateBuyQuoteOrFlashErrorAsync(
 | 
			
		||||
            assetBuyer,
 | 
			
		||||
            selectedAsset as ERC20Asset, // TODO: better way to do this?
 | 
			
		||||
            selectedAssetAmount,
 | 
			
		||||
            dispatch,
 | 
			
		||||
            affiliateInfo,
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
@@ -1,4 +1,5 @@
 | 
			
		||||
import { AssetBuyer, AssetBuyerError, BuyQuote } from '@0x/asset-buyer';
 | 
			
		||||
import { AssetProxyId } from '@0x/types';
 | 
			
		||||
import { BigNumber } from '@0x/utils';
 | 
			
		||||
import { Web3Wrapper } from '@0x/web3-wrapper';
 | 
			
		||||
import * as _ from 'lodash';
 | 
			
		||||
@@ -6,6 +7,7 @@ import { Dispatch } from 'redux';
 | 
			
		||||
import { oc } from 'ts-optchain';
 | 
			
		||||
 | 
			
		||||
import { Action, actions } from '../redux/actions';
 | 
			
		||||
import { State } from '../redux/reducer';
 | 
			
		||||
import { AffiliateInfo, ERC20Asset } from '../types';
 | 
			
		||||
import { assetUtils } from '../util/asset';
 | 
			
		||||
import { errorFlasher } from '../util/error_flasher';
 | 
			
		||||
@@ -16,12 +18,15 @@ export const buyQuoteUpdater = {
 | 
			
		||||
        dispatch: Dispatch<Action>,
 | 
			
		||||
        asset: ERC20Asset,
 | 
			
		||||
        assetAmount: BigNumber,
 | 
			
		||||
        setPending = true,
 | 
			
		||||
        affiliateInfo?: AffiliateInfo,
 | 
			
		||||
    ): Promise<void> => {
 | 
			
		||||
        // get a new buy quote.
 | 
			
		||||
        const baseUnitValue = Web3Wrapper.toBaseUnitAmount(assetAmount, asset.metaData.decimals);
 | 
			
		||||
        // mark quote as pending
 | 
			
		||||
        dispatch(actions.setQuoteRequestStatePending());
 | 
			
		||||
        if (setPending) {
 | 
			
		||||
            // mark quote as pending
 | 
			
		||||
            dispatch(actions.setQuoteRequestStatePending());
 | 
			
		||||
        }
 | 
			
		||||
        const feePercentage = oc(affiliateInfo).feePercentage();
 | 
			
		||||
        let newBuyQuote: BuyQuote | undefined;
 | 
			
		||||
        try {
 | 
			
		||||
 
 | 
			
		||||
@@ -4,18 +4,24 @@ type HeartbeatableFunction = () => Promise<void>;
 | 
			
		||||
export class Heartbeater {
 | 
			
		||||
    private _intervalId?: number;
 | 
			
		||||
    private _hasPendingRequest: boolean;
 | 
			
		||||
    private _performImmediatelyOnStart: boolean;
 | 
			
		||||
    private _performFunction: HeartbeatableFunction;
 | 
			
		||||
 | 
			
		||||
    public constructor(_performingFunctionAsync: HeartbeatableFunction) {
 | 
			
		||||
        this._performFunction = _performingFunctionAsync;
 | 
			
		||||
    public constructor(performingFunctionAsync: HeartbeatableFunction, performImmediatelyOnStart: boolean) {
 | 
			
		||||
        this._performFunction = performingFunctionAsync;
 | 
			
		||||
        this._hasPendingRequest = false;
 | 
			
		||||
        this._performImmediatelyOnStart = performImmediatelyOnStart;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public start(intervalTimeMs: number): void {
 | 
			
		||||
        if (!_.isUndefined(this._intervalId)) {
 | 
			
		||||
            throw new Error('Heartbeat is running, please stop before restarting');
 | 
			
		||||
        }
 | 
			
		||||
        this._trackAndPerformAsync();
 | 
			
		||||
 | 
			
		||||
        if (this._performImmediatelyOnStart) {
 | 
			
		||||
            this._trackAndPerformAsync();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this._intervalId = window.setInterval(this._trackAndPerformAsync.bind(this), intervalTimeMs);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,17 +1,16 @@
 | 
			
		||||
import { asyncData } from '../redux/async_data';
 | 
			
		||||
import { Store } from '../redux/store';
 | 
			
		||||
 | 
			
		||||
import { updateBuyQuoteOrFlashErrorAsyncForState } from './buy_quote_fetcher';
 | 
			
		||||
import { Heartbeater } from './heartbeater';
 | 
			
		||||
 | 
			
		||||
export const generateAccountHeartbeater = (store: Store): Heartbeater => {
 | 
			
		||||
export const generateAccountHeartbeater = (store: Store, performImmediatelyOnStart: boolean): Heartbeater => {
 | 
			
		||||
    return new Heartbeater(async () => {
 | 
			
		||||
        await asyncData.fetchAccountInfoAndDispatchToStore(store, { setLoading: false });
 | 
			
		||||
    });
 | 
			
		||||
    }, performImmediatelyOnStart);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const generateBuyQuoteHeartbeater = (store: Store): Heartbeater => {
 | 
			
		||||
export const generateBuyQuoteHeartbeater = (store: Store, performImmediatelyOnStart: boolean): Heartbeater => {
 | 
			
		||||
    return new Heartbeater(async () => {
 | 
			
		||||
        await updateBuyQuoteOrFlashErrorAsyncForState(store.getState(), store.dispatch);
 | 
			
		||||
    });
 | 
			
		||||
        await asyncData.fetchCurrentBuyQuoteAndDispatchToStore(store, false);
 | 
			
		||||
    }, performImmediatelyOnStart);
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user