aboutsummaryrefslogtreecommitdiffstats
path: root/packages/instant/src
diff options
context:
space:
mode:
authorSteve Klebanoff <steve@0xproject.com>2018-11-30 07:44:07 +0800
committerGitHub <noreply@github.com>2018-11-30 07:44:07 +0800
commitfc3641b49938ea9dc5e77e633e798ca19aa812ff (patch)
tree8eb14525cab2ac8485202ff28d6f66e06290169f /packages/instant/src
parentd4c439b27703b6855a6f7da60cf5a249d82b6b81 (diff)
parent5c66f9117fa0bf6a5be29243dbecbfe016b95345 (diff)
downloaddexon-sol-tools-fc3641b49938ea9dc5e77e633e798ca19aa812ff.tar
dexon-sol-tools-fc3641b49938ea9dc5e77e633e798ca19aa812ff.tar.gz
dexon-sol-tools-fc3641b49938ea9dc5e77e633e798ca19aa812ff.tar.bz2
dexon-sol-tools-fc3641b49938ea9dc5e77e633e798ca19aa812ff.tar.lz
dexon-sol-tools-fc3641b49938ea9dc5e77e633e798ca19aa812ff.tar.xz
dexon-sol-tools-fc3641b49938ea9dc5e77e633e798ca19aa812ff.tar.zst
dexon-sol-tools-fc3641b49938ea9dc5e77e633e798ca19aa812ff.zip
Merge pull request #1343 from 0xProject/feature/instant/quote-analytics
[instant] Quote analytics
Diffstat (limited to 'packages/instant/src')
-rw-r--r--packages/instant/src/components/zero_ex_instant_provider.tsx6
-rw-r--r--packages/instant/src/containers/selected_erc20_asset_amount_input.ts4
-rw-r--r--packages/instant/src/redux/async_data.ts10
-rw-r--r--packages/instant/src/types.ts5
-rw-r--r--packages/instant/src/util/analytics.ts25
-rw-r--r--packages/instant/src/util/buy_quote_updater.ts12
-rw-r--r--packages/instant/src/util/heartbeater_factory.ts12
7 files changed, 62 insertions, 12 deletions
diff --git a/packages/instant/src/components/zero_ex_instant_provider.tsx b/packages/instant/src/components/zero_ex_instant_provider.tsx
index e006a5a5f..a4a03bbf4 100644
--- a/packages/instant/src/components/zero_ex_instant_provider.tsx
+++ b/packages/instant/src/components/zero_ex_instant_provider.tsx
@@ -11,7 +11,7 @@ import { asyncData } from '../redux/async_data';
import { DEFAULT_STATE, DefaultState, State } from '../redux/reducer';
import { store, Store } from '../redux/store';
import { fonts } from '../style/fonts';
-import { AccountState, AffiliateInfo, AssetMetaData, Network, OrderSource } from '../types';
+import { AccountState, AffiliateInfo, AssetMetaData, Network, OrderSource, QuoteFetchOrigin } from '../types';
import { analytics, disableAnalytics } from '../util/analytics';
import { assetUtils } from '../util/asset';
import { errorFlasher } from '../util/error_flasher';
@@ -115,7 +115,9 @@ export class ZeroExInstantProvider extends React.Component<ZeroExInstantProvider
this._buyQuoteHeartbeat.start(BUY_QUOTE_UPDATE_INTERVAL_TIME_MS);
// Trigger first buyquote fetch
// tslint:disable-next-line:no-floating-promises
- asyncData.fetchCurrentBuyQuoteAndDispatchToStore(state, dispatch, { updateSilently: false });
+ asyncData.fetchCurrentBuyQuoteAndDispatchToStore(state, dispatch, QuoteFetchOrigin.Manual, {
+ updateSilently: false,
+ });
// warm up the gas price estimator cache just in case we can't
// grab the gas price estimate when submitting the transaction
// tslint:disable-next-line:no-floating-promises
diff --git a/packages/instant/src/containers/selected_erc20_asset_amount_input.ts b/packages/instant/src/containers/selected_erc20_asset_amount_input.ts
index a39bc46a2..cb9df527e 100644
--- a/packages/instant/src/containers/selected_erc20_asset_amount_input.ts
+++ b/packages/instant/src/containers/selected_erc20_asset_amount_input.ts
@@ -10,7 +10,7 @@ import { ERC20AssetAmountInput, ERC20AssetAmountInputProps } from '../components
import { Action, actions } from '../redux/actions';
import { State } from '../redux/reducer';
import { ColorOption } from '../style/theme';
-import { AffiliateInfo, ERC20Asset, Omit, OrderProcessState } from '../types';
+import { AffiliateInfo, ERC20Asset, Omit, OrderProcessState, QuoteFetchOrigin } from '../types';
import { buyQuoteUpdater } from '../util/buy_quote_updater';
export interface SelectedERC20AssetAmountInputProps {
@@ -88,7 +88,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, {
+ debouncedUpdateBuyQuoteAsync(assetBuyer, dispatch, asset, value, QuoteFetchOrigin.Manual, {
setPending: true,
dispatchErrors: true,
affiliateInfo,
diff --git a/packages/instant/src/redux/async_data.ts b/packages/instant/src/redux/async_data.ts
index 6feb760e7..9fdcea3ca 100644
--- a/packages/instant/src/redux/async_data.ts
+++ b/packages/instant/src/redux/async_data.ts
@@ -4,7 +4,7 @@ import * as _ from 'lodash';
import { Dispatch } from 'redux';
import { BIG_NUMBER_ZERO } from '../constants';
-import { AccountState, ERC20Asset, OrderProcessState, ProviderState } from '../types';
+import { AccountState, ERC20Asset, OrderProcessState, ProviderState, QuoteFetchOrigin } from '../types';
import { analytics } from '../util/analytics';
import { assetUtils } from '../util/asset';
import { buyQuoteUpdater } from '../util/buy_quote_updater';
@@ -84,6 +84,7 @@ export const asyncData = {
fetchCurrentBuyQuoteAndDispatchToStore: async (
state: State,
dispatch: Dispatch,
+ fetchOrigin: QuoteFetchOrigin,
options: { updateSilently: boolean },
) => {
const { buyOrderState, providerState, selectedAsset, selectedAssetUnitAmount, affiliateInfo } = state;
@@ -99,7 +100,12 @@ export const asyncData = {
dispatch,
selectedAsset as ERC20Asset,
selectedAssetUnitAmount,
- { setPending: !options.updateSilently, dispatchErrors: !options.updateSilently, affiliateInfo },
+ fetchOrigin,
+ {
+ setPending: !options.updateSilently,
+ dispatchErrors: !options.updateSilently,
+ affiliateInfo,
+ },
);
}
},
diff --git a/packages/instant/src/types.ts b/packages/instant/src/types.ts
index 4ad9c9d4f..2d73ba29e 100644
--- a/packages/instant/src/types.ts
+++ b/packages/instant/src/types.ts
@@ -21,6 +21,11 @@ export enum OrderProcessState {
Failure = 'FAILURE',
}
+export enum QuoteFetchOrigin {
+ Manual = 'Manual',
+ Heartbeat = 'Heartbeat',
+}
+
export interface SimulatedProgress {
startTimeUnix: number;
expectedEndTimeUnix: number;
diff --git a/packages/instant/src/util/analytics.ts b/packages/instant/src/util/analytics.ts
index d44998666..4b8aff4c9 100644
--- a/packages/instant/src/util/analytics.ts
+++ b/packages/instant/src/util/analytics.ts
@@ -1,7 +1,16 @@
import { BuyQuote } from '@0x/asset-buyer';
+import { BigNumber } from '@0x/utils';
import * as _ from 'lodash';
-import { AffiliateInfo, Asset, Network, OrderSource, ProviderState, WalletSuggestion } from '../types';
+import {
+ AffiliateInfo,
+ Asset,
+ Network,
+ OrderSource,
+ ProviderState,
+ QuoteFetchOrigin,
+ WalletSuggestion,
+} from '../types';
import { EventProperties, heapUtil } from './heap';
@@ -42,6 +51,8 @@ enum EventNames {
TOKEN_SELECTOR_CLOSED = 'Token Selector - Closed',
TOKEN_SELECTOR_CHOSE = 'Token Selector - Chose',
TOKEN_SELECTOR_SEARCHED = 'Token Selector - Searched',
+ QUOTE_FETCHED = 'Quote - Fetched',
+ QUOTE_ERROR = 'Quote - Error',
}
const track = (eventName: EventNames, eventProperties: EventProperties = {}): void => {
@@ -190,4 +201,16 @@ export const analytics = {
trackingEventFnWithPayload(EventNames.TOKEN_SELECTOR_CHOSE)(payload),
trackTokenSelectorSearched: (searchText: string) =>
trackingEventFnWithPayload(EventNames.TOKEN_SELECTOR_SEARCHED)({ searchText }),
+ trackQuoteFetched: (buyQuote: BuyQuote, fetchOrigin: QuoteFetchOrigin) =>
+ trackingEventFnWithPayload(EventNames.QUOTE_FETCHED)({
+ ...buyQuoteEventProperties(buyQuote),
+ fetchOrigin,
+ }),
+ trackQuoteError: (errorMessage: string, assetBuyAmount: BigNumber, fetchOrigin: QuoteFetchOrigin) => {
+ trackingEventFnWithPayload(EventNames.QUOTE_ERROR)({
+ errorMessage,
+ assetBuyAmount: assetBuyAmount.toString(),
+ fetchOrigin,
+ });
+ },
};
diff --git a/packages/instant/src/util/buy_quote_updater.ts b/packages/instant/src/util/buy_quote_updater.ts
index 2fd16d781..c1899f8c1 100644
--- a/packages/instant/src/util/buy_quote_updater.ts
+++ b/packages/instant/src/util/buy_quote_updater.ts
@@ -6,7 +6,8 @@ import { Dispatch } from 'redux';
import { oc } from 'ts-optchain';
import { Action, actions } from '../redux/actions';
-import { AffiliateInfo, ERC20Asset } from '../types';
+import { AffiliateInfo, ERC20Asset, QuoteFetchOrigin } from '../types';
+import { analytics } from '../util/analytics';
import { assetUtils } from '../util/asset';
import { errorFlasher } from '../util/error_flasher';
@@ -16,7 +17,12 @@ export const buyQuoteUpdater = {
dispatch: Dispatch<Action>,
asset: ERC20Asset,
assetUnitAmount: BigNumber,
- options: { setPending: boolean; dispatchErrors: boolean; affiliateInfo?: AffiliateInfo },
+ fetchOrigin: QuoteFetchOrigin,
+ options: {
+ setPending: boolean;
+ dispatchErrors: boolean;
+ affiliateInfo?: AffiliateInfo;
+ },
): Promise<void> => {
// get a new buy quote.
const baseUnitValue = Web3Wrapper.toBaseUnitAmount(assetUnitAmount, asset.metaData.decimals);
@@ -31,6 +37,7 @@ export const buyQuoteUpdater = {
} catch (error) {
if (options.dispatchErrors) {
dispatch(actions.setQuoteRequestStateFailure());
+ analytics.trackQuoteError(error.message ? error.message : 'other', baseUnitValue, fetchOrigin);
let errorMessage;
if (error.message === AssetBuyerError.InsufficientAssetLiquidity) {
const assetName = assetUtils.bestNameForAsset(asset, 'of this asset');
@@ -58,5 +65,6 @@ export const buyQuoteUpdater = {
errorFlasher.clearError(dispatch);
// invalidate the last buy quote.
dispatch(actions.updateLatestBuyQuote(newBuyQuote));
+ analytics.trackQuoteFetched(newBuyQuote, fetchOrigin);
},
};
diff --git a/packages/instant/src/util/heartbeater_factory.ts b/packages/instant/src/util/heartbeater_factory.ts
index 2b852fb0d..cf29bf3ea 100644
--- a/packages/instant/src/util/heartbeater_factory.ts
+++ b/packages/instant/src/util/heartbeater_factory.ts
@@ -1,5 +1,6 @@
import { asyncData } from '../redux/async_data';
import { Store } from '../redux/store';
+import { QuoteFetchOrigin } from '../types';
import { Heartbeater } from './heartbeater';
@@ -17,8 +18,13 @@ export const generateAccountHeartbeater = (options: HeartbeatFactoryOptions): He
export const generateBuyQuoteHeartbeater = (options: HeartbeatFactoryOptions): Heartbeater => {
const { store, shouldPerformImmediatelyOnStart } = options;
return new Heartbeater(async () => {
- await asyncData.fetchCurrentBuyQuoteAndDispatchToStore(store.getState(), store.dispatch, {
- updateSilently: true,
- });
+ await asyncData.fetchCurrentBuyQuoteAndDispatchToStore(
+ store.getState(),
+ store.dispatch,
+ QuoteFetchOrigin.Heartbeat,
+ {
+ updateSilently: true,
+ },
+ );
}, shouldPerformImmediatelyOnStart);
};