Merge pull request #1188 from 0xProject/fix/instant/quote-race-conditions

[instant] Make sure quote updates are consistent with the current state
This commit is contained in:
Brandon Millman
2018-10-26 13:24:04 -07:00
committed by GitHub

View File

@@ -1,6 +1,7 @@
import { AssetBuyer, BuyQuote } from '@0x/asset-buyer'; import { AssetBuyer, BuyQuote } from '@0x/asset-buyer';
import { ObjectMap } from '@0x/types'; import { AssetProxyId, ObjectMap } from '@0x/types';
import { BigNumber } from '@0x/utils'; import { BigNumber } from '@0x/utils';
import { Web3Wrapper } from '@0x/web3-wrapper';
import * as _ from 'lodash'; import * as _ from 'lodash';
import { assetMetaDataMap } from '../data/asset_meta_data_map'; import { assetMetaDataMap } from '../data/asset_meta_data_map';
@@ -57,11 +58,19 @@ export const reducer = (state: State = INITIAL_STATE, action: Action): State =>
selectedAssetAmount: action.data, selectedAssetAmount: action.data,
}; };
case ActionTypes.UPDATE_LATEST_BUY_QUOTE: case ActionTypes.UPDATE_LATEST_BUY_QUOTE:
return { const newBuyQuoteIfExists = action.data;
...state, const shouldUpdate =
latestBuyQuote: action.data, _.isUndefined(newBuyQuoteIfExists) || doesBuyQuoteMatchState(newBuyQuoteIfExists, state);
quoteRequestState: AsyncProcessState.SUCCESS, if (shouldUpdate) {
}; return {
...state,
latestBuyQuote: newBuyQuoteIfExists,
quoteRequestState: AsyncProcessState.SUCCESS,
};
} else {
return state;
}
case ActionTypes.SET_QUOTE_REQUEST_STATE_PENDING: case ActionTypes.SET_QUOTE_REQUEST_STATE_PENDING:
return { return {
...state, ...state,
@@ -122,3 +131,29 @@ export const reducer = (state: State = INITIAL_STATE, action: Action): State =>
return state; return state;
} }
}; };
const doesBuyQuoteMatchState = (buyQuote: BuyQuote, state: State): boolean => {
const selectedAssetIfExists = state.selectedAsset;
const selectedAssetAmountIfExists = state.selectedAssetAmount;
// if no selectedAsset or selectedAssetAmount exists on the current state, return false
if (_.isUndefined(selectedAssetIfExists) || _.isUndefined(selectedAssetAmountIfExists)) {
return false;
}
// if buyQuote's assetData does not match that of the current selected asset, return false
if (selectedAssetIfExists.assetData !== buyQuote.assetData) {
return false;
}
// if ERC20 and buyQuote's assetBuyAmount does not match selectedAssetAmount, return false
// if ERC721, return true
const selectedAssetMetaData = selectedAssetIfExists.metaData;
if (selectedAssetMetaData.assetProxyId === AssetProxyId.ERC20) {
const selectedAssetAmountBaseUnits = Web3Wrapper.toBaseUnitAmount(
selectedAssetAmountIfExists,
selectedAssetMetaData.decimals,
);
const doesAssetAmountMatch = selectedAssetAmountBaseUnits.eq(buyQuote.assetBuyAmount);
return doesAssetAmountMatch;
} else {
return true;
}
};