diff options
| author | Steve Klebanoff <steve.klebanoff@gmail.com> | 2018-11-28 03:10:20 +0800 | 
|---|---|---|
| committer | Steve Klebanoff <steve.klebanoff@gmail.com> | 2018-11-28 03:10:20 +0800 | 
| commit | 96a46bcb4b78744be08da9b957339802b8ba14fa (patch) | |
| tree | a647bd1cf96e54489e444b9cb7e1bc0ad94362ba | |
| parent | 5fd837cc4fbb8d70d3e72fe05fa5bf33a0331ab8 (diff) | |
| parent | 4653e4c011410b67b0be0335aa1f44dfade86a2e (diff) | |
| download | dexon-sol-tools-96a46bcb4b78744be08da9b957339802b8ba14fa.tar.gz dexon-sol-tools-96a46bcb4b78744be08da9b957339802b8ba14fa.tar.zst dexon-sol-tools-96a46bcb4b78744be08da9b957339802b8ba14fa.zip | |
Merge branch 'development' into feature/instant/dropdown-analytics
| -rw-r--r-- | packages/instant/src/components/buy_button.tsx | 8 | ||||
| -rw-r--r-- | packages/instant/src/components/payment_method_dropdown.tsx | 2 | ||||
| -rw-r--r-- | packages/instant/src/components/zero_ex_instant_overlay.tsx | 9 | ||||
| -rw-r--r-- | packages/instant/src/constants.ts | 2 | ||||
| -rw-r--r-- | packages/instant/src/util/analytics.ts | 55 | 
5 files changed, 73 insertions, 3 deletions
| diff --git a/packages/instant/src/components/buy_button.tsx b/packages/instant/src/components/buy_button.tsx index 8b6121e43..eeb42d6fc 100644 --- a/packages/instant/src/components/buy_button.tsx +++ b/packages/instant/src/components/buy_button.tsx @@ -8,6 +8,7 @@ import { oc } from 'ts-optchain';  import { WEB_3_WRAPPER_TRANSACTION_FAILED_ERROR_MSG_PREFIX } from '../constants';  import { ColorOption } from '../style/theme';  import { AffiliateInfo, ZeroExInstantError } from '../types'; +import { analytics } from '../util/analytics';  import { gasPriceEstimator } from '../util/gas_price_estimator';  import { util } from '../util/util'; @@ -59,6 +60,7 @@ export class BuyButton extends React.Component<BuyButtonProps> {          // if we don't have a balance for the user, let the transaction through, it will be handled by the wallet          const hasSufficientEth = _.isUndefined(accountEthBalanceInWei) || accountEthBalanceInWei.gte(ethNeededForBuy);          if (!hasSufficientEth) { +            analytics.trackBuyNotEnoughEth(buyQuote);              this.props.onValidationFail(buyQuote, ZeroExInstantError.InsufficientETH);              return;          } @@ -66,6 +68,7 @@ export class BuyButton extends React.Component<BuyButtonProps> {          const gasInfo = await gasPriceEstimator.getGasInfoAsync();          const feeRecipient = oc(affiliateInfo).feeRecipient();          try { +            analytics.trackBuyStarted(buyQuote);              txHash = await assetBuyer.executeBuyQuoteAsync(buyQuote, {                  feeRecipient,                  takerAddress: accountAddress, @@ -74,9 +77,11 @@ export class BuyButton extends React.Component<BuyButtonProps> {          } catch (e) {              if (e instanceof Error) {                  if (e.message === AssetBuyerError.SignatureRequestDenied) { +                    analytics.trackBuySignatureDenied(buyQuote);                      this.props.onSignatureDenied(buyQuote);                      return;                  } else if (e.message === AssetBuyerError.TransactionValueTooLow) { +                    analytics.trackBuySimulationFailed(buyQuote);                      this.props.onValidationFail(buyQuote, AssetBuyerError.TransactionValueTooLow);                      return;                  } @@ -87,14 +92,17 @@ export class BuyButton extends React.Component<BuyButtonProps> {          const expectedEndTimeUnix = startTimeUnix + gasInfo.estimatedTimeMs;          this.props.onBuyProcessing(buyQuote, txHash, startTimeUnix, expectedEndTimeUnix);          try { +            analytics.trackBuyTxSubmitted(buyQuote, txHash, startTimeUnix, expectedEndTimeUnix);              await web3Wrapper.awaitTransactionSuccessAsync(txHash);          } catch (e) {              if (e instanceof Error && e.message.startsWith(WEB_3_WRAPPER_TRANSACTION_FAILED_ERROR_MSG_PREFIX)) { +                analytics.trackBuyTxFailed(buyQuote, txHash, startTimeUnix, expectedEndTimeUnix);                  this.props.onBuyFailure(buyQuote, txHash);                  return;              }              throw e;          } +        analytics.trackBuyTxSucceeded(buyQuote, txHash, startTimeUnix, expectedEndTimeUnix);          this.props.onBuySuccess(buyQuote, txHash);      };  } diff --git a/packages/instant/src/components/payment_method_dropdown.tsx b/packages/instant/src/components/payment_method_dropdown.tsx index 7d7fecbc2..872ac0831 100644 --- a/packages/instant/src/components/payment_method_dropdown.tsx +++ b/packages/instant/src/components/payment_method_dropdown.tsx @@ -1,5 +1,5 @@  import { BigNumber } from '@0x/utils'; -import copy from 'copy-to-clipboard'; +import * as copy from 'copy-to-clipboard';  import * as React from 'react';  import { Network } from '../types'; diff --git a/packages/instant/src/components/zero_ex_instant_overlay.tsx b/packages/instant/src/components/zero_ex_instant_overlay.tsx index 2856ea3e3..b3fb57dd6 100644 --- a/packages/instant/src/components/zero_ex_instant_overlay.tsx +++ b/packages/instant/src/components/zero_ex_instant_overlay.tsx @@ -1,6 +1,7 @@  import * as React from 'react';  import { ZeroExInstantContainer } from '../components/zero_ex_instant_container'; +import { MAIN_CONTAINER_DIV_CLASS, OVERLAY_DIV_CLASS } from '../constants';  import { ColorOption } from '../style/theme';  import { Container } from './ui/container'; @@ -18,7 +19,7 @@ export const ZeroExInstantOverlay: React.StatelessComponent<ZeroExInstantOverlay      const { onClose, zIndex, ...rest } = props;      return (          <ZeroExInstantProvider {...rest}> -            <Overlay zIndex={zIndex}> +            <Overlay zIndex={zIndex} className={OVERLAY_DIV_CLASS}>                  <Flex height="100vh">                      <Container position="absolute" top="0px" right="0px" display={{ default: 'initial', sm: 'none' }}>                          <Icon @@ -30,7 +31,11 @@ export const ZeroExInstantOverlay: React.StatelessComponent<ZeroExInstantOverlay                              padding="2em 2em"                          />                      </Container> -                    <Container width={{ default: 'auto', sm: '100%' }} height={{ default: 'auto', sm: '100%' }}> +                    <Container +                        width={{ default: 'auto', sm: '100%' }} +                        height={{ default: 'auto', sm: '100%' }} +                        className={MAIN_CONTAINER_DIV_CLASS} +                    >                          <ZeroExInstantContainer />                      </Container>                  </Flex> diff --git a/packages/instant/src/constants.ts b/packages/instant/src/constants.ts index be6077ca9..163be40b3 100644 --- a/packages/instant/src/constants.ts +++ b/packages/instant/src/constants.ts @@ -7,6 +7,8 @@ export const ETH_DECIMALS = 18;  export const DEFAULT_ZERO_EX_CONTAINER_SELECTOR = '#zeroExInstantContainer';  export const INJECTED_DIV_CLASS = 'zeroExInstantResetRoot';  export const INJECTED_DIV_ID = 'zeroExInstant'; +export const OVERLAY_DIV_CLASS = 'zeroExInstantOverlay'; +export const MAIN_CONTAINER_DIV_CLASS = 'zeroExInstantMainContainer';  export const WEB_3_WRAPPER_TRANSACTION_FAILED_ERROR_MSG_PREFIX = 'Transaction failed';  export const GWEI_IN_WEI = new BigNumber(1000000000);  export const ONE_SECOND_MS = 1000; diff --git a/packages/instant/src/util/analytics.ts b/packages/instant/src/util/analytics.ts index 05988965b..5bc9bb385 100644 --- a/packages/instant/src/util/analytics.ts +++ b/packages/instant/src/util/analytics.ts @@ -1,3 +1,6 @@ +import { BuyQuote } from '@0x/asset-buyer'; +import * as _ from 'lodash'; +  import { AffiliateInfo, Asset, Network, OrderSource, ProviderState } from '../types';  import { EventProperties, heapUtil } from './heap'; @@ -23,6 +26,13 @@ enum EventNames {      PAYMENT_METHOD_DROPDOWN_OPENED = 'Payment Method - Dropdown Opened',      PAYMENT_METHOD_OPENED_ETHERSCAN = 'Payment Method - Opened Etherscan',      PAYMENT_METHOD_COPIED_ADDRESS = 'Payment Method - Copied Address', +    BUY_NOT_ENOUGH_ETH = 'Buy - Not Enough Eth', +    BUY_STARTED = 'Buy - Started', +    BUY_SIGNATURE_DENIED = 'Buy - Signature Denied', +    BUY_SIMULATION_FAILED = 'Buy - Simulation Failed', +    BUY_TX_SUBMITTED = 'Buy - Tx Submitted', +    BUY_TX_SUCCEEDED = 'Buy - Tx Succeeded', +    BUY_TX_FAILED = 'Buy - Tx Failed',      TOKEN_SELECTOR_OPENED = 'Token Selector - Opened',      TOKEN_SELECTOR_CLOSED = 'Token Selector - Closed',      TOKEN_SELECTOR_CHOSE = 'Token Selector - Chose', @@ -46,6 +56,23 @@ function trackingEventFnWithPayload(eventName: EventNames): (eventProperties: Ev      };  } +const buyQuoteEventProperties = (buyQuote: BuyQuote) => { +    const assetBuyAmount = buyQuote.assetBuyAmount.toString(); +    const assetEthAmount = buyQuote.worstCaseQuoteInfo.assetEthAmount.toString(); +    const feeEthAmount = buyQuote.worstCaseQuoteInfo.feeEthAmount.toString(); +    const totalEthAmount = buyQuote.worstCaseQuoteInfo.totalEthAmount.toString(); +    const feePercentage = !_.isUndefined(buyQuote.feePercentage) ? buyQuote.feePercentage.toString() : 0; +    const hasFeeOrders = !_.isEmpty(buyQuote.feeOrders) ? 'true' : 'false'; +    return { +        assetBuyAmount, +        assetEthAmount, +        feeEthAmount, +        totalEthAmount, +        feePercentage, +        hasFeeOrders, +    }; +}; +  export interface AnalyticsUserOptions {      lastKnownEthAddress?: string;      ethBalanceInUnitAmount?: string; @@ -115,6 +142,34 @@ export const analytics = {      trackPaymentMethodDropdownOpened: trackingEventFnWithoutPayload(EventNames.PAYMENT_METHOD_DROPDOWN_OPENED),      trackPaymentMethodOpenedEtherscan: trackingEventFnWithoutPayload(EventNames.PAYMENT_METHOD_OPENED_ETHERSCAN),      trackPaymentMethodCopiedAddress: trackingEventFnWithoutPayload(EventNames.PAYMENT_METHOD_COPIED_ADDRESS), +    trackBuyNotEnoughEth: (buyQuote: BuyQuote) => +        trackingEventFnWithPayload(EventNames.BUY_NOT_ENOUGH_ETH)(buyQuoteEventProperties(buyQuote)), +    trackBuyStarted: (buyQuote: BuyQuote) => +        trackingEventFnWithPayload(EventNames.BUY_STARTED)(buyQuoteEventProperties(buyQuote)), +    trackBuySignatureDenied: (buyQuote: BuyQuote) => +        trackingEventFnWithPayload(EventNames.BUY_SIGNATURE_DENIED)(buyQuoteEventProperties(buyQuote)), +    trackBuySimulationFailed: (buyQuote: BuyQuote) => +        trackingEventFnWithPayload(EventNames.BUY_SIMULATION_FAILED)(buyQuoteEventProperties(buyQuote)), +    trackBuyTxSubmitted: (buyQuote: BuyQuote, txHash: string, startTimeUnix: number, expectedEndTimeUnix: number) => +        trackingEventFnWithPayload(EventNames.BUY_TX_SUBMITTED)({ +            ...buyQuoteEventProperties(buyQuote), +            txHash, +            expectedTxTimeMs: expectedEndTimeUnix - startTimeUnix, +        }), +    trackBuyTxSucceeded: (buyQuote: BuyQuote, txHash: string, startTimeUnix: number, expectedEndTimeUnix: number) => +        trackingEventFnWithPayload(EventNames.BUY_TX_SUCCEEDED)({ +            ...buyQuoteEventProperties(buyQuote), +            txHash, +            expectedTxTimeMs: expectedEndTimeUnix - startTimeUnix, +            actualTxTimeMs: new Date().getTime() - startTimeUnix, +        }), +    trackBuyTxFailed: (buyQuote: BuyQuote, txHash: string, startTimeUnix: number, expectedEndTimeUnix: number) => +        trackingEventFnWithPayload(EventNames.BUY_TX_FAILED)({ +            ...buyQuoteEventProperties(buyQuote), +            txHash, +            expectedTxTimeMs: expectedEndTimeUnix - startTimeUnix, +            actualTxTimeMs: new Date().getTime() - startTimeUnix, +        }),      trackTokenSelectorOpened: trackingEventFnWithoutPayload(EventNames.TOKEN_SELECTOR_OPENED),      trackTokenSelectorClosed: (closedVia: TokenSelectorClosedVia) =>          trackingEventFnWithPayload(EventNames.TOKEN_SELECTOR_CLOSED)({ closedVia }), | 
