From 848193074a10d9799ffbc27918a8b264a2e101bb Mon Sep 17 00:00:00 2001 From: fragosti Date: Fri, 16 Nov 2018 15:21:04 -0800 Subject: feat: close and open instant based on history changes --- packages/instant/src/index.umd.ts | 51 +++++++++++++++++++++++++++++---------- 1 file changed, 38 insertions(+), 13 deletions(-) (limited to 'packages/instant/src') diff --git a/packages/instant/src/index.umd.ts b/packages/instant/src/index.umd.ts index 0274db30c..81b7aebe3 100644 --- a/packages/instant/src/index.umd.ts +++ b/packages/instant/src/index.umd.ts @@ -5,6 +5,7 @@ import * as ReactDOM from 'react-dom'; import { DEFAULT_ZERO_EX_CONTAINER_SELECTOR, INJECTED_DIV_CLASS, INJECTED_DIV_ID } from './constants'; import { ZeroExInstantOverlay, ZeroExInstantOverlayProps } from './index'; import { assert } from './util/assert'; +import { util } from './util/util'; export const render = (props: ZeroExInstantOverlayProps, selector: string = DEFAULT_ZERO_EX_CONTAINER_SELECTOR) => { assert.isValidOrderSource('orderSource', props.orderSource); @@ -36,21 +37,45 @@ export const render = (props: ZeroExInstantOverlayProps, selector: string = DEFA assert.isWeb3Provider('props.provider', props.provider); } assert.isString('selector', selector); - const appendToIfExists = document.querySelector(selector); - assert.assert(!_.isNull(appendToIfExists), `Could not find div with selector: ${selector}`); - const appendTo = appendToIfExists as Element; - const injectedDiv = document.createElement('div'); - injectedDiv.setAttribute('id', INJECTED_DIV_ID); - injectedDiv.setAttribute('class', INJECTED_DIV_CLASS); - appendTo.appendChild(injectedDiv); - const instantOverlayProps = { - ...props, - onClose: () => { - appendTo.removeChild(injectedDiv); + // Render instant and return a callback that allows you to close it. + const renderInstant = () => { + const appendToIfExists = document.querySelector(selector); + assert.assert(!_.isNull(appendToIfExists), `Could not find div with selector: ${selector}`); + const appendTo = appendToIfExists as Element; + const injectedDiv = document.createElement('div'); + injectedDiv.setAttribute('id', INJECTED_DIV_ID); + injectedDiv.setAttribute('class', INJECTED_DIV_CLASS); + appendTo.appendChild(injectedDiv); + const instantOverlayProps = { + ...props, + onClose: () => window.history.back(), + }; + ReactDOM.render(React.createElement(ZeroExInstantOverlay, instantOverlayProps), injectedDiv); + const close = () => appendTo.removeChild(injectedDiv); + return close; + }; + // Before we render, push to history saying that instant is showing for this part of the history. + window.history.pushState({ zeroExInstantShowing: true }, '0x Instant'); + let closeInstant = renderInstant(); + + let prevOnPopState = util.boundNoop; + if (window.onpopstate) { + prevOnPopState = window.onpopstate.bind(window); + } + window.onpopstate = (e: PopStateEvent) => { + // Don't override integrators handler. + prevOnPopState(e); + // e.state represents the new state + if (e.state && e.state.zeroExInstantShowing) { + // The user pressed fowards, so re-render instant. + closeInstant = renderInstant(); + } else { + // User pressed back, so close instant. + closeInstant(); + delete window.onpopstate; if (!_.isUndefined(props.onClose)) { props.onClose(); } - }, + } }; - ReactDOM.render(React.createElement(ZeroExInstantOverlay, instantOverlayProps), injectedDiv); }; -- cgit From f7914af9c564d4521e375fb3dd5825da763df7d6 Mon Sep 17 00:00:00 2001 From: fragosti Date: Fri, 16 Nov 2018 15:23:44 -0800 Subject: feat: rename props to config --- packages/instant/src/index.umd.ts | 50 +++++++++++++++++++++------------------ 1 file changed, 27 insertions(+), 23 deletions(-) (limited to 'packages/instant/src') diff --git a/packages/instant/src/index.umd.ts b/packages/instant/src/index.umd.ts index 81b7aebe3..fda21478f 100644 --- a/packages/instant/src/index.umd.ts +++ b/packages/instant/src/index.umd.ts @@ -7,34 +7,38 @@ import { ZeroExInstantOverlay, ZeroExInstantOverlayProps } from './index'; import { assert } from './util/assert'; import { util } from './util/util'; -export const render = (props: ZeroExInstantOverlayProps, selector: string = DEFAULT_ZERO_EX_CONTAINER_SELECTOR) => { - assert.isValidOrderSource('orderSource', props.orderSource); - if (!_.isUndefined(props.defaultSelectedAssetData)) { - assert.isHexString('defaultSelectedAssetData', props.defaultSelectedAssetData); +export interface ZeroExInstantConfig extends ZeroExInstantOverlayProps { + shouldUseHistoryApi?: boolean; +} + +export const render = (config: ZeroExInstantConfig, selector: string = DEFAULT_ZERO_EX_CONTAINER_SELECTOR) => { + assert.isValidOrderSource('orderSource', config.orderSource); + if (!_.isUndefined(config.defaultSelectedAssetData)) { + assert.isHexString('defaultSelectedAssetData', config.defaultSelectedAssetData); } - if (!_.isUndefined(props.additionalAssetMetaDataMap)) { - assert.isValidAssetMetaDataMap('props.additionalAssetMetaDataMap', props.additionalAssetMetaDataMap); + if (!_.isUndefined(config.additionalAssetMetaDataMap)) { + assert.isValidAssetMetaDataMap('props.additionalAssetMetaDataMap', config.additionalAssetMetaDataMap); } - if (!_.isUndefined(props.defaultAssetBuyAmount)) { - assert.isNumber('props.defaultAssetBuyAmount', props.defaultAssetBuyAmount); + if (!_.isUndefined(config.defaultAssetBuyAmount)) { + assert.isNumber('props.defaultAssetBuyAmount', config.defaultAssetBuyAmount); } - if (!_.isUndefined(props.networkId)) { - assert.isNumber('props.networkId', props.networkId); + if (!_.isUndefined(config.networkId)) { + assert.isNumber('props.networkId', config.networkId); } - if (!_.isUndefined(props.availableAssetDatas)) { - assert.areValidAssetDatas('availableAssetDatas', props.availableAssetDatas); + if (!_.isUndefined(config.availableAssetDatas)) { + assert.areValidAssetDatas('availableAssetDatas', config.availableAssetDatas); } - if (!_.isUndefined(props.onClose)) { - assert.isFunction('props.onClose', props.onClose); + if (!_.isUndefined(config.onClose)) { + assert.isFunction('props.onClose', config.onClose); } - if (!_.isUndefined(props.zIndex)) { - assert.isNumber('props.zIndex', props.zIndex); + if (!_.isUndefined(config.zIndex)) { + assert.isNumber('props.zIndex', config.zIndex); } - if (!_.isUndefined(props.affiliateInfo)) { - assert.isValidAffiliateInfo('props.affiliateInfo', props.affiliateInfo); + if (!_.isUndefined(config.affiliateInfo)) { + assert.isValidAffiliateInfo('props.affiliateInfo', config.affiliateInfo); } - if (!_.isUndefined(props.provider)) { - assert.isWeb3Provider('props.provider', props.provider); + if (!_.isUndefined(config.provider)) { + assert.isWeb3Provider('props.provider', config.provider); } assert.isString('selector', selector); // Render instant and return a callback that allows you to close it. @@ -47,7 +51,7 @@ export const render = (props: ZeroExInstantOverlayProps, selector: string = DEFA injectedDiv.setAttribute('class', INJECTED_DIV_CLASS); appendTo.appendChild(injectedDiv); const instantOverlayProps = { - ...props, + ...config, onClose: () => window.history.back(), }; ReactDOM.render(React.createElement(ZeroExInstantOverlay, instantOverlayProps), injectedDiv); @@ -73,8 +77,8 @@ export const render = (props: ZeroExInstantOverlayProps, selector: string = DEFA // User pressed back, so close instant. closeInstant(); delete window.onpopstate; - if (!_.isUndefined(props.onClose)) { - props.onClose(); + if (!_.isUndefined(config.onClose)) { + config.onClose(); } } }; -- cgit From 9a53a29b1f421cdea190b6175dec437ec6d76a39 Mon Sep 17 00:00:00 2001 From: fragosti Date: Fri, 16 Nov 2018 15:41:21 -0800 Subject: feat: allow integrator to disable pushstate logic --- packages/instant/src/index.umd.ts | 54 +++++++++++++++++++++------------------ 1 file changed, 29 insertions(+), 25 deletions(-) (limited to 'packages/instant/src') diff --git a/packages/instant/src/index.umd.ts b/packages/instant/src/index.umd.ts index fda21478f..381c9094b 100644 --- a/packages/instant/src/index.umd.ts +++ b/packages/instant/src/index.umd.ts @@ -8,7 +8,7 @@ import { assert } from './util/assert'; import { util } from './util/util'; export interface ZeroExInstantConfig extends ZeroExInstantOverlayProps { - shouldUseHistoryApi?: boolean; + shouldDisablePushToHistory?: boolean; } export const render = (config: ZeroExInstantConfig, selector: string = DEFAULT_ZERO_EX_CONTAINER_SELECTOR) => { @@ -50,36 +50,40 @@ export const render = (config: ZeroExInstantConfig, selector: string = DEFAULT_Z injectedDiv.setAttribute('id', INJECTED_DIV_ID); injectedDiv.setAttribute('class', INJECTED_DIV_CLASS); appendTo.appendChild(injectedDiv); + const close = () => appendTo.removeChild(injectedDiv); const instantOverlayProps = { ...config, - onClose: () => window.history.back(), + // If we are using the history API, just go back to close + onClose: () => (config.shouldDisablePushToHistory ? close() : window.history.back()), }; ReactDOM.render(React.createElement(ZeroExInstantOverlay, instantOverlayProps), injectedDiv); - const close = () => appendTo.removeChild(injectedDiv); return close; }; - // Before we render, push to history saying that instant is showing for this part of the history. - window.history.pushState({ zeroExInstantShowing: true }, '0x Instant'); - let closeInstant = renderInstant(); + if (config.shouldDisablePushToHistory) { + renderInstant(); + } else { + // Before we render, push to history saying that instant is showing for this part of the history. + window.history.pushState({ zeroExInstantShowing: true }, '0x Instant'); + let closeInstant = renderInstant(); - let prevOnPopState = util.boundNoop; - if (window.onpopstate) { - prevOnPopState = window.onpopstate.bind(window); - } - window.onpopstate = (e: PopStateEvent) => { - // Don't override integrators handler. - prevOnPopState(e); - // e.state represents the new state - if (e.state && e.state.zeroExInstantShowing) { - // The user pressed fowards, so re-render instant. - closeInstant = renderInstant(); - } else { - // User pressed back, so close instant. - closeInstant(); - delete window.onpopstate; - if (!_.isUndefined(config.onClose)) { - config.onClose(); - } + let prevOnPopState = util.boundNoop; + if (window.onpopstate) { + prevOnPopState = window.onpopstate.bind(window); } - }; + window.onpopstate = (e: PopStateEvent) => { + // Don't override integrators handler. + prevOnPopState(e); + // e.state represents the new state + if (e.state && e.state.zeroExInstantShowing) { + // The user pressed fowards, so re-render instant. + closeInstant = renderInstant(); + } else { + // User pressed back, so close instant. + closeInstant(); + if (!_.isUndefined(config.onClose)) { + config.onClose(); + } + } + }; + } }; -- cgit From a4f6cd21bd289eb2baaee8b6b7d09cbb9e0955dc Mon Sep 17 00:00:00 2001 From: fragosti Date: Fri, 16 Nov 2018 15:45:02 -0800 Subject: feat: be more specific with callback name --- packages/instant/src/index.umd.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'packages/instant/src') diff --git a/packages/instant/src/index.umd.ts b/packages/instant/src/index.umd.ts index 381c9094b..298b7733f 100644 --- a/packages/instant/src/index.umd.ts +++ b/packages/instant/src/index.umd.ts @@ -41,7 +41,7 @@ export const render = (config: ZeroExInstantConfig, selector: string = DEFAULT_Z assert.isWeb3Provider('props.provider', config.provider); } assert.isString('selector', selector); - // Render instant and return a callback that allows you to close it. + // Render instant and return a callback that allows you to remove it from the DOM. const renderInstant = () => { const appendToIfExists = document.querySelector(selector); assert.assert(!_.isNull(appendToIfExists), `Could not find div with selector: ${selector}`); @@ -50,21 +50,21 @@ export const render = (config: ZeroExInstantConfig, selector: string = DEFAULT_Z injectedDiv.setAttribute('id', INJECTED_DIV_ID); injectedDiv.setAttribute('class', INJECTED_DIV_CLASS); appendTo.appendChild(injectedDiv); - const close = () => appendTo.removeChild(injectedDiv); + const removeFromDom = () => appendTo.removeChild(injectedDiv); const instantOverlayProps = { ...config, // If we are using the history API, just go back to close - onClose: () => (config.shouldDisablePushToHistory ? close() : window.history.back()), + onClose: () => (config.shouldDisablePushToHistory ? removeFromDom() : window.history.back()), }; ReactDOM.render(React.createElement(ZeroExInstantOverlay, instantOverlayProps), injectedDiv); - return close; + return removeFromDom; }; if (config.shouldDisablePushToHistory) { renderInstant(); } else { // Before we render, push to history saying that instant is showing for this part of the history. window.history.pushState({ zeroExInstantShowing: true }, '0x Instant'); - let closeInstant = renderInstant(); + let removeInstant = renderInstant(); let prevOnPopState = util.boundNoop; if (window.onpopstate) { @@ -76,10 +76,10 @@ export const render = (config: ZeroExInstantConfig, selector: string = DEFAULT_Z // e.state represents the new state if (e.state && e.state.zeroExInstantShowing) { // The user pressed fowards, so re-render instant. - closeInstant = renderInstant(); + removeInstant = renderInstant(); } else { // User pressed back, so close instant. - closeInstant(); + removeInstant(); if (!_.isUndefined(config.onClose)) { config.onClose(); } -- cgit From 51dce3008841b7bdc9080212f8b5e12a90f6cce9 Mon Sep 17 00:00:00 2001 From: fragosti Date: Fri, 16 Nov 2018 15:48:55 -0800 Subject: feat: add assert for shouldDisablePushToHistory --- packages/instant/src/index.umd.ts | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) (limited to 'packages/instant/src') diff --git a/packages/instant/src/index.umd.ts b/packages/instant/src/index.umd.ts index 298b7733f..9703c6fc0 100644 --- a/packages/instant/src/index.umd.ts +++ b/packages/instant/src/index.umd.ts @@ -17,28 +17,31 @@ export const render = (config: ZeroExInstantConfig, selector: string = DEFAULT_Z assert.isHexString('defaultSelectedAssetData', config.defaultSelectedAssetData); } if (!_.isUndefined(config.additionalAssetMetaDataMap)) { - assert.isValidAssetMetaDataMap('props.additionalAssetMetaDataMap', config.additionalAssetMetaDataMap); + assert.isValidAssetMetaDataMap('additionalAssetMetaDataMap', config.additionalAssetMetaDataMap); } if (!_.isUndefined(config.defaultAssetBuyAmount)) { - assert.isNumber('props.defaultAssetBuyAmount', config.defaultAssetBuyAmount); + assert.isNumber('defaultAssetBuyAmount', config.defaultAssetBuyAmount); } if (!_.isUndefined(config.networkId)) { - assert.isNumber('props.networkId', config.networkId); + assert.isNumber('networkId', config.networkId); } if (!_.isUndefined(config.availableAssetDatas)) { assert.areValidAssetDatas('availableAssetDatas', config.availableAssetDatas); } if (!_.isUndefined(config.onClose)) { - assert.isFunction('props.onClose', config.onClose); + assert.isFunction('onClose', config.onClose); } if (!_.isUndefined(config.zIndex)) { - assert.isNumber('props.zIndex', config.zIndex); + assert.isNumber('zIndex', config.zIndex); } if (!_.isUndefined(config.affiliateInfo)) { - assert.isValidAffiliateInfo('props.affiliateInfo', config.affiliateInfo); + assert.isValidAffiliateInfo('affiliateInfo', config.affiliateInfo); } if (!_.isUndefined(config.provider)) { - assert.isWeb3Provider('props.provider', config.provider); + assert.isWeb3Provider('provider', config.provider); + } + if (!_.isUndefined(config.shouldDisablePushToHistory)) { + assert.isBoolean('shouldDisablePushToHistory', config.shouldDisablePushToHistory); } assert.isString('selector', selector); // Render instant and return a callback that allows you to remove it from the DOM. -- cgit From 654c13df8aee2e43992c6629d2249d56667fec67 Mon Sep 17 00:00:00 2001 From: fragosti Date: Fri, 16 Nov 2018 16:07:37 -0800 Subject: fix: bug where we did not call onClose config --- packages/instant/src/index.umd.ts | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'packages/instant/src') diff --git a/packages/instant/src/index.umd.ts b/packages/instant/src/index.umd.ts index 9703c6fc0..518326e21 100644 --- a/packages/instant/src/index.umd.ts +++ b/packages/instant/src/index.umd.ts @@ -53,14 +53,19 @@ export const render = (config: ZeroExInstantConfig, selector: string = DEFAULT_Z injectedDiv.setAttribute('id', INJECTED_DIV_ID); injectedDiv.setAttribute('class', INJECTED_DIV_CLASS); appendTo.appendChild(injectedDiv); - const removeFromDom = () => appendTo.removeChild(injectedDiv); + const closeInstant = () => { + if (config.onClose) { + config.onClose(); + } + appendTo.removeChild(injectedDiv); + }; const instantOverlayProps = { ...config, // If we are using the history API, just go back to close - onClose: () => (config.shouldDisablePushToHistory ? removeFromDom() : window.history.back()), + onClose: () => (config.shouldDisablePushToHistory ? closeInstant() : window.history.back()), }; ReactDOM.render(React.createElement(ZeroExInstantOverlay, instantOverlayProps), injectedDiv); - return removeFromDom; + return closeInstant; }; if (config.shouldDisablePushToHistory) { renderInstant(); @@ -83,9 +88,6 @@ export const render = (config: ZeroExInstantConfig, selector: string = DEFAULT_Z } else { // User pressed back, so close instant. removeInstant(); - if (!_.isUndefined(config.onClose)) { - config.onClose(); - } } }; } -- cgit From ac942faa258f604f4f6171759f6bcdf786317d29 Mon Sep 17 00:00:00 2001 From: fragosti Date: Fri, 16 Nov 2018 16:14:10 -0800 Subject: chore: use lodash where relevant --- packages/instant/src/index.umd.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'packages/instant/src') diff --git a/packages/instant/src/index.umd.ts b/packages/instant/src/index.umd.ts index 518326e21..34d893ad7 100644 --- a/packages/instant/src/index.umd.ts +++ b/packages/instant/src/index.umd.ts @@ -54,7 +54,7 @@ export const render = (config: ZeroExInstantConfig, selector: string = DEFAULT_Z injectedDiv.setAttribute('class', INJECTED_DIV_CLASS); appendTo.appendChild(injectedDiv); const closeInstant = () => { - if (config.onClose) { + if (!_.isUndefined(config.onClose)) { config.onClose(); } appendTo.removeChild(injectedDiv); -- cgit From 9384c507ac29043d0d2f68bef3dde94a43282d09 Mon Sep 17 00:00:00 2001 From: fragosti Date: Fri, 16 Nov 2018 16:33:02 -0800 Subject: feat: add isInstantRendered check to safeguard against double renders and double removes --- packages/instant/src/index.umd.ts | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) (limited to 'packages/instant/src') diff --git a/packages/instant/src/index.umd.ts b/packages/instant/src/index.umd.ts index 34d893ad7..64f888e00 100644 --- a/packages/instant/src/index.umd.ts +++ b/packages/instant/src/index.umd.ts @@ -68,7 +68,9 @@ export const render = (config: ZeroExInstantConfig, selector: string = DEFAULT_Z return closeInstant; }; if (config.shouldDisablePushToHistory) { - renderInstant(); + if (!isInstantRendered()) { + renderInstant(); + } } else { // Before we render, push to history saying that instant is showing for this part of the history. window.history.pushState({ zeroExInstantShowing: true }, '0x Instant'); @@ -83,12 +85,18 @@ export const render = (config: ZeroExInstantConfig, selector: string = DEFAULT_Z prevOnPopState(e); // e.state represents the new state if (e.state && e.state.zeroExInstantShowing) { - // The user pressed fowards, so re-render instant. - removeInstant = renderInstant(); + // We have returned to a history state that expects instant to be rendered. + if (!isInstantRendered()) { + removeInstant = renderInstant(); + } } else { - // User pressed back, so close instant. - removeInstant(); + // History has changed to a different state. + if (isInstantRendered()) { + removeInstant(); + } } }; } }; + +const isInstantRendered = (): boolean => !!document.getElementById(INJECTED_DIV_ID); -- cgit From 351e0e6f5f2add25c4d779356a8cfd4aefb305cb Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Tue, 20 Nov 2018 22:34:57 -0800 Subject: feat(instant): implement account related events --- .../containers/connected_account_payment_method.ts | 8 +++-- packages/instant/src/redux/analytics_middleware.ts | 34 ++++++++++++---------- packages/instant/src/redux/async_data.ts | 2 ++ packages/instant/src/util/analytics.ts | 13 +++++++-- 4 files changed, 37 insertions(+), 20 deletions(-) (limited to 'packages/instant/src') diff --git a/packages/instant/src/containers/connected_account_payment_method.ts b/packages/instant/src/containers/connected_account_payment_method.ts index eacbadfca..cdeb49a25 100644 --- a/packages/instant/src/containers/connected_account_payment_method.ts +++ b/packages/instant/src/containers/connected_account_payment_method.ts @@ -12,6 +12,7 @@ import { Action, actions } from '../redux/actions'; import { asyncData } from '../redux/async_data'; import { State } from '../redux/reducer'; import { Network, Omit, OperatingSystem, ProviderState, StandardSlidingPanelContent } from '../types'; +import { analytics } from '../util/analytics'; import { envUtil } from '../util/env'; export interface ConnectedAccountPaymentMethodProps {} @@ -40,8 +41,11 @@ const mapDispatchToProps = ( ownProps: ConnectedAccountPaymentMethodProps, ): ConnectedDispatch => ({ openInstallWalletPanel: () => dispatch(actions.openStandardSlidingPanel(StandardSlidingPanelContent.InstallWallet)), - unlockWalletAndDispatchToStore: async (providerState: ProviderState) => - asyncData.fetchAccountInfoAndDispatchToStore(providerState, dispatch, true), + unlockWalletAndDispatchToStore: (providerState: ProviderState) => { + analytics.trackAccountUnlockRequested(); + // tslint:disable-next-line:no-floating-promises + asyncData.fetchAccountInfoAndDispatchToStore(providerState, dispatch, true); + }, }); const mergeProps = ( diff --git a/packages/instant/src/redux/analytics_middleware.ts b/packages/instant/src/redux/analytics_middleware.ts index f971dbd33..893844f5d 100644 --- a/packages/instant/src/redux/analytics_middleware.ts +++ b/packages/instant/src/redux/analytics_middleware.ts @@ -10,20 +10,6 @@ import { Action, ActionTypes } from './actions'; import { State } from './reducer'; -const shouldTriggerWalletReady = (prevAccount: Account, curAccount: Account): boolean => { - const didJustTurnReady = curAccount.state === AccountState.Ready && prevAccount.state !== AccountState.Ready; - if (didJustTurnReady) { - return true; - } - - if (curAccount.state === AccountState.Ready && prevAccount.state === AccountState.Ready) { - // Account was ready, and is now ready again, but address has changed - return curAccount.address !== prevAccount.address; - } - - return false; -}; - export const analyticsMiddleware: Middleware = store => next => middlewareAction => { const prevState = store.getState() as State; const prevAccount = prevState.providerState.account; @@ -35,10 +21,26 @@ export const analyticsMiddleware: Middleware = store => next => middlewareAction switch (nextAction.type) { case ActionTypes.SET_ACCOUNT_STATE_READY: - if (curAccount.state === AccountState.Ready && shouldTriggerWalletReady(prevAccount, curAccount)) { + if (prevAccount.state !== AccountState.Ready && curAccount.state === AccountState.Ready) { + // if we are moving from account not ready to account ready, update the current address and track `Account - Ready` const ethAddress = curAccount.address; analytics.addUserProperties({ ethAddress }); - analytics.trackWalletReady(); + analytics.trackAccountReady(ethAddress); + } else if (prevAccount.state === AccountState.Ready && curAccount.state === AccountState.Ready) { + if (prevAccount.address !== curAccount.address) { + // if our account state was already ready and our address has changed, update the current address and track `Account - Address Changed` + const ethAddress = curAccount.address; + analytics.addUserProperties({ ethAddress }); + analytics.trackAccountAddressChanged(ethAddress); + } + } + break; + case ActionTypes.SET_ACCOUNT_STATE_LOCKED: + if (prevAccount.state !== AccountState.Locked && curAccount.state === AccountState.Locked) { + // if we are moving from account not locked to account locked, update the current address to undefined and track `Account - Locked` + const ethAddress = undefined; + analytics.addUserProperties({ ethAddress }); + analytics.trackAccountLocked(); } break; case ActionTypes.UPDATE_ACCOUNT_ETH_BALANCE: diff --git a/packages/instant/src/redux/async_data.ts b/packages/instant/src/redux/async_data.ts index 5d30388b8..6feb760e7 100644 --- a/packages/instant/src/redux/async_data.ts +++ b/packages/instant/src/redux/async_data.ts @@ -5,6 +5,7 @@ import { Dispatch } from 'redux'; import { BIG_NUMBER_ZERO } from '../constants'; import { AccountState, ERC20Asset, OrderProcessState, ProviderState } from '../types'; +import { analytics } from '../util/analytics'; import { assetUtils } from '../util/asset'; import { buyQuoteUpdater } from '../util/buy_quote_updater'; import { coinbaseApi } from '../util/coinbase_api'; @@ -58,6 +59,7 @@ export const asyncData = { ? await (provider as any).enable() : await web3Wrapper.getAvailableAddressesAsync(); } catch (e) { + analytics.trackAccountUnlockDenied(); dispatch(actions.setAccountStateLocked()); return; } diff --git a/packages/instant/src/util/analytics.ts b/packages/instant/src/util/analytics.ts index 2ffaac1dd..d36bf8fc3 100644 --- a/packages/instant/src/util/analytics.ts +++ b/packages/instant/src/util/analytics.ts @@ -15,7 +15,11 @@ export const evaluateIfEnabled = (fnCall: () => void) => { enum EventNames { INSTANT_OPENED = 'Instant - Opened', - WALLET_READY = 'Wallet - Ready', + ACCOUNT_LOCKED = 'Account - Locked', + ACCOUNT_READY = 'Account - Ready', + ACCOUNT_UNLOCK_REQUESTED = 'Account - Unlock Requested', + ACCOUNT_UNLOCK_DENIED = 'Account - Unlock Denied', + ACCOUNT_ADDRESS_CHANGED = 'Account - Address Changed', } const track = (eventName: EventNames, eventData: ObjectMap = {}): void => { evaluateIfEnabled(() => { @@ -59,6 +63,11 @@ export const analytics = { heapUtil.evaluateHeapCall(heap => heap.addEventProperties(properties)); }); }, - trackWalletReady: trackingEventFnWithoutPayload(EventNames.WALLET_READY), trackInstantOpened: trackingEventFnWithoutPayload(EventNames.INSTANT_OPENED), + trackAccountLocked: trackingEventFnWithoutPayload(EventNames.ACCOUNT_LOCKED), + trackAccountReady: (address: string) => trackingEventFnWithPayload(EventNames.ACCOUNT_READY)({ address }), + trackAccountUnlockRequested: trackingEventFnWithoutPayload(EventNames.ACCOUNT_UNLOCK_REQUESTED), + trackAccountUnlockDenied: trackingEventFnWithoutPayload(EventNames.ACCOUNT_UNLOCK_DENIED), + trackAccountAddressChanged: (address: string) => + trackingEventFnWithPayload(EventNames.ACCOUNT_ADDRESS_CHANGED)({ address }), }; -- cgit From e0beb7fb380e50e4566db4787092f5549a2d6db1 Mon Sep 17 00:00:00 2001 From: fragosti Date: Wed, 21 Nov 2018 11:42:07 -0500 Subject: feat: add more to instant dev env --- packages/instant/src/index.umd.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'packages/instant/src') diff --git a/packages/instant/src/index.umd.ts b/packages/instant/src/index.umd.ts index 59f658b33..1d62084b5 100644 --- a/packages/instant/src/index.umd.ts +++ b/packages/instant/src/index.umd.ts @@ -7,6 +7,7 @@ import { ZeroExInstantOverlay, ZeroExInstantOverlayProps } from './index'; import { assert } from './util/assert'; import { util } from './util/util'; +const isInstantRendered = (): boolean => !!document.getElementById(INJECTED_DIV_ID); export interface ZeroExInstantConfig extends ZeroExInstantOverlayProps { shouldDisablePushToHistory?: boolean; } @@ -43,8 +44,8 @@ export const render = (config: ZeroExInstantConfig, selector: string = DEFAULT_Z if (!_.isUndefined(config.shouldDisablePushToHistory)) { assert.isBoolean('shouldDisablePushToHistory', config.shouldDisablePushToHistory); } - if (!_.isUndefined(props.shouldDisableAnalyticsTracking)) { - assert.isBoolean('props.shouldDisableAnalyticsTracking', props.shouldDisableAnalyticsTracking); + if (!_.isUndefined(config.shouldDisableAnalyticsTracking)) { + assert.isBoolean('shouldDisableAnalyticsTracking', config.shouldDisableAnalyticsTracking); } assert.isString('selector', selector); // Render instant and return a callback that allows you to remove it from the DOM. @@ -101,5 +102,3 @@ export const render = (config: ZeroExInstantConfig, selector: string = DEFAULT_Z }; } }; - -const isInstantRendered = (): boolean => !!document.getElementById(INJECTED_DIV_ID); -- cgit From b494a4a4dba6c781667b690f38387f03a22fe141 Mon Sep 17 00:00:00 2001 From: fragosti Date: Wed, 21 Nov 2018 11:55:32 -0500 Subject: chore: clean up index.umd.ts a bit --- packages/instant/src/index.umd.ts | 70 +++++++++++++++++++++------------------ 1 file changed, 38 insertions(+), 32 deletions(-) (limited to 'packages/instant/src') diff --git a/packages/instant/src/index.umd.ts b/packages/instant/src/index.umd.ts index 1d62084b5..15ca59323 100644 --- a/packages/instant/src/index.umd.ts +++ b/packages/instant/src/index.umd.ts @@ -8,11 +8,8 @@ import { assert } from './util/assert'; import { util } from './util/util'; const isInstantRendered = (): boolean => !!document.getElementById(INJECTED_DIV_ID); -export interface ZeroExInstantConfig extends ZeroExInstantOverlayProps { - shouldDisablePushToHistory?: boolean; -} -export const render = (config: ZeroExInstantConfig, selector: string = DEFAULT_ZERO_EX_CONTAINER_SELECTOR) => { +const validateInstantRenderConfig = (config: ZeroExInstantConfig, selector: string) => { assert.isValidOrderSource('orderSource', config.orderSource); if (!_.isUndefined(config.defaultSelectedAssetData)) { assert.isHexString('defaultSelectedAssetData', config.defaultSelectedAssetData); @@ -48,37 +45,46 @@ export const render = (config: ZeroExInstantConfig, selector: string = DEFAULT_Z assert.isBoolean('shouldDisableAnalyticsTracking', config.shouldDisableAnalyticsTracking); } assert.isString('selector', selector); - // Render instant and return a callback that allows you to remove it from the DOM. - const renderInstant = () => { - const appendToIfExists = document.querySelector(selector); - assert.assert(!_.isNull(appendToIfExists), `Could not find div with selector: ${selector}`); - const appendTo = appendToIfExists as Element; - const injectedDiv = document.createElement('div'); - injectedDiv.setAttribute('id', INJECTED_DIV_ID); - injectedDiv.setAttribute('class', INJECTED_DIV_CLASS); - appendTo.appendChild(injectedDiv); - const closeInstant = () => { - if (!_.isUndefined(config.onClose)) { - config.onClose(); - } - appendTo.removeChild(injectedDiv); - }; - const instantOverlayProps = { - ...config, - // If we are using the history API, just go back to close - onClose: () => (config.shouldDisablePushToHistory ? closeInstant() : window.history.back()), - }; - ReactDOM.render(React.createElement(ZeroExInstantOverlay, instantOverlayProps), injectedDiv); - return closeInstant; +}; + +// Render instant and return a callback that allows you to remove it from the DOM. +const renderInstant = (config: ZeroExInstantConfig, selector: string) => { + const appendToIfExists = document.querySelector(selector); + assert.assert(!_.isNull(appendToIfExists), `Could not find div with selector: ${selector}`); + const appendTo = appendToIfExists as Element; + const injectedDiv = document.createElement('div'); + injectedDiv.setAttribute('id', INJECTED_DIV_ID); + injectedDiv.setAttribute('class', INJECTED_DIV_CLASS); + appendTo.appendChild(injectedDiv); + const closeInstant = () => { + if (!_.isUndefined(config.onClose)) { + config.onClose(); + } + appendTo.removeChild(injectedDiv); + }; + const instantOverlayProps = { + ...config, + // If we are using the history API, just go back to close + onClose: () => (config.shouldDisablePushToHistory ? closeInstant() : window.history.back()), }; + ReactDOM.render(React.createElement(ZeroExInstantOverlay, instantOverlayProps), injectedDiv); + return closeInstant; +}; + +export interface ZeroExInstantConfig extends ZeroExInstantOverlayProps { + shouldDisablePushToHistory?: boolean; +} + +export const render = (config: ZeroExInstantConfig, selector: string = DEFAULT_ZERO_EX_CONTAINER_SELECTOR) => { + validateInstantRenderConfig(config, selector); if (config.shouldDisablePushToHistory) { if (!isInstantRendered()) { - renderInstant(); + renderInstant(config, selector); } } else { // Before we render, push to history saying that instant is showing for this part of the history. window.history.pushState({ zeroExInstantShowing: true }, '0x Instant'); - let removeInstant = renderInstant(); + let removeInstant = renderInstant(config, selector); let prevOnPopState = util.boundNoop; if (window.onpopstate) { @@ -86,12 +92,12 @@ export const render = (config: ZeroExInstantConfig, selector: string = DEFAULT_Z } window.onpopstate = (e: PopStateEvent) => { // Don't override integrators handler. - prevOnPopState(e); - // e.state represents the new state - if (e.state && e.state.zeroExInstantShowing) { + // prevOnPopState(e); + const newState = e.state; + if (newState && newState.zeroExInstantShowing) { // We have returned to a history state that expects instant to be rendered. if (!isInstantRendered()) { - removeInstant = renderInstant(); + removeInstant = renderInstant(config, selector); } } else { // History has changed to a different state. -- cgit From ed91c6c874282ab069a72784b8e563b634a236bf Mon Sep 17 00:00:00 2001 From: fragosti Date: Wed, 21 Nov 2018 12:44:28 -0500 Subject: fix: multiple render and closes edge case for onpopstate render --- packages/instant/src/index.umd.ts | 52 ++++++++++++++++++++------------------- 1 file changed, 27 insertions(+), 25 deletions(-) (limited to 'packages/instant/src') diff --git a/packages/instant/src/index.umd.ts b/packages/instant/src/index.umd.ts index 15ca59323..3a8694d6a 100644 --- a/packages/instant/src/index.umd.ts +++ b/packages/instant/src/index.umd.ts @@ -81,30 +81,32 @@ export const render = (config: ZeroExInstantConfig, selector: string = DEFAULT_Z if (!isInstantRendered()) { renderInstant(config, selector); } - } else { - // Before we render, push to history saying that instant is showing for this part of the history. - window.history.pushState({ zeroExInstantShowing: true }, '0x Instant'); - let removeInstant = renderInstant(config, selector); - - let prevOnPopState = util.boundNoop; - if (window.onpopstate) { - prevOnPopState = window.onpopstate.bind(window); - } - window.onpopstate = (e: PopStateEvent) => { - // Don't override integrators handler. - // prevOnPopState(e); - const newState = e.state; - if (newState && newState.zeroExInstantShowing) { - // We have returned to a history state that expects instant to be rendered. - if (!isInstantRendered()) { - removeInstant = renderInstant(config, selector); - } - } else { - // History has changed to a different state. - if (isInstantRendered()) { - removeInstant(); - } - } - }; + return; + } + // Before we render, push to history saying that instant is showing for this part of the history. + window.history.pushState({ zeroExInstantShowing: true }, '0x Instant'); + let removeInstant = renderInstant(config, selector); + // If the integrator defined a popstate handler, save it to __zeroExInstantIntegratorsPopStateHandler + // unless we have already done so on a previous render. + const anyWindow = window as any; + if (window.onpopstate && !anyWindow.__zeroExInstantIntegratorsPopStateHandler) { + anyWindow.__zeroExInstantIntegratorsPopStateHandler = window.onpopstate.bind(window); } + const integratorsOnPopStateHandler = anyWindow.__zeroExInstantIntegratorsPopStateHandler || util.boundNoop; + const onPopStateHandler = (e: PopStateEvent) => { + integratorsOnPopStateHandler(e); + const newState = e.state; + if (newState && newState.zeroExInstantShowing) { + // We have returned to a history state that expects instant to be rendered. + if (!isInstantRendered()) { + removeInstant = renderInstant(config, selector); + } + } else { + // History has changed to a different state. + if (isInstantRendered()) { + removeInstant(); + } + } + }; + window.onpopstate = onPopStateHandler; }; -- cgit From 31d1b4ba670d25c4cd4ed93d32d12718b4804e5d Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Wed, 21 Nov 2018 12:30:52 -0800 Subject: chore(instant): refactor account tracking logic in middleware to be more readable --- packages/instant/src/redux/analytics_middleware.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'packages/instant/src') diff --git a/packages/instant/src/redux/analytics_middleware.ts b/packages/instant/src/redux/analytics_middleware.ts index 893844f5d..889cc875e 100644 --- a/packages/instant/src/redux/analytics_middleware.ts +++ b/packages/instant/src/redux/analytics_middleware.ts @@ -21,17 +21,17 @@ export const analyticsMiddleware: Middleware = store => next => middlewareAction switch (nextAction.type) { case ActionTypes.SET_ACCOUNT_STATE_READY: - if (prevAccount.state !== AccountState.Ready && curAccount.state === AccountState.Ready) { - // if we are moving from account not ready to account ready, update the current address and track `Account - Ready` + if (curAccount.state === AccountState.Ready) { + const didJustTurnReady = prevAccount.state !== AccountState.Ready; + const didJustUpdateAddress = + prevAccount.state === AccountState.Ready && prevAccount.address !== curAccount.address; const ethAddress = curAccount.address; - analytics.addUserProperties({ ethAddress }); - analytics.trackAccountReady(ethAddress); - } else if (prevAccount.state === AccountState.Ready && curAccount.state === AccountState.Ready) { - if (prevAccount.address !== curAccount.address) { - // if our account state was already ready and our address has changed, update the current address and track `Account - Address Changed` - const ethAddress = curAccount.address; + if (didJustTurnReady) { + analytics.trackAccountReady(ethAddress); analytics.addUserProperties({ ethAddress }); + } else if (didJustUpdateAddress) { analytics.trackAccountAddressChanged(ethAddress); + analytics.addUserProperties({ ethAddress }); } } break; -- cgit From 6604e2db20d6263e05b00cf5d36b56788e42d9c2 Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Wed, 21 Nov 2018 12:44:28 -0800 Subject: chore(instant): refactor usage of event properties in heap --- packages/instant/src/redux/analytics_middleware.ts | 12 ++++---- packages/instant/src/util/analytics.ts | 32 ++++++++++++---------- packages/instant/src/util/heap.ts | 4 ++- 3 files changed, 26 insertions(+), 22 deletions(-) (limited to 'packages/instant/src') diff --git a/packages/instant/src/redux/analytics_middleware.ts b/packages/instant/src/redux/analytics_middleware.ts index 889cc875e..931902187 100644 --- a/packages/instant/src/redux/analytics_middleware.ts +++ b/packages/instant/src/redux/analytics_middleware.ts @@ -27,19 +27,17 @@ export const analyticsMiddleware: Middleware = store => next => middlewareAction prevAccount.state === AccountState.Ready && prevAccount.address !== curAccount.address; const ethAddress = curAccount.address; if (didJustTurnReady) { - analytics.trackAccountReady(ethAddress); - analytics.addUserProperties({ ethAddress }); + analytics.trackAccountReady({ address: ethAddress }); + analytics.addUserProperties({ lastKnownEthAddress: ethAddress }); } else if (didJustUpdateAddress) { - analytics.trackAccountAddressChanged(ethAddress); - analytics.addUserProperties({ ethAddress }); + analytics.trackAccountAddressChanged({ address: ethAddress }); + analytics.addUserProperties({ lastKnownEthAddress: ethAddress }); } } break; case ActionTypes.SET_ACCOUNT_STATE_LOCKED: if (prevAccount.state !== AccountState.Locked && curAccount.state === AccountState.Locked) { - // if we are moving from account not locked to account locked, update the current address to undefined and track `Account - Locked` - const ethAddress = undefined; - analytics.addUserProperties({ ethAddress }); + // if we are moving from account not locked to account locked, track `Account - Locked` analytics.trackAccountLocked(); } break; diff --git a/packages/instant/src/util/analytics.ts b/packages/instant/src/util/analytics.ts index d36bf8fc3..31233fe7a 100644 --- a/packages/instant/src/util/analytics.ts +++ b/packages/instant/src/util/analytics.ts @@ -1,6 +1,4 @@ -import { ObjectMap } from '@0x/types'; - -import { heapUtil } from './heap'; +import { EventProperties, heapUtil } from './heap'; let isDisabled = false; export const disableAnalytics = (shouldDisableAnalytics: boolean) => { @@ -21,9 +19,9 @@ enum EventNames { ACCOUNT_UNLOCK_DENIED = 'Account - Unlock Denied', ACCOUNT_ADDRESS_CHANGED = 'Account - Address Changed', } -const track = (eventName: EventNames, eventData: ObjectMap = {}): void => { +const track = (eventName: EventNames, eventProperties: EventProperties = {}): void => { evaluateIfEnabled(() => { - heapUtil.evaluateHeapCall(heap => heap.track(eventName, eventData)); + heapUtil.evaluateHeapCall(heap => heap.track(eventName, eventProperties)); }); }; function trackingEventFnWithoutPayload(eventName: EventNames): () => void { @@ -32,16 +30,14 @@ function trackingEventFnWithoutPayload(eventName: EventNames): () => void { }; } // tslint:disable-next-line:no-unused-variable -function trackingEventFnWithPayload>( - eventName: EventNames, -): (eventDataProperties: T) => void { - return (eventDataProperties: T) => { - track(eventName, eventDataProperties); +function trackingEventFnWithPayload(eventName: EventNames): (eventProperties: EventProperties) => void { + return (eventProperties: EventProperties) => { + track(eventName, eventProperties); }; } export interface AnalyticsUserOptions { - ethAddress?: string; + lastKnownEthAddress?: string; ethBalanceInUnitAmount?: string; } export interface AnalyticsEventOptions { @@ -52,6 +48,13 @@ export interface AnalyticsEventOptions { gitSha?: string; npmVersion?: string; } +export interface AccountReadyEventProperties { + address: string; +} +export interface AccountAddressChangedEventProperties { + address: string; +} + export const analytics = { addUserProperties: (properties: AnalyticsUserOptions): void => { evaluateIfEnabled(() => { @@ -65,9 +68,10 @@ export const analytics = { }, trackInstantOpened: trackingEventFnWithoutPayload(EventNames.INSTANT_OPENED), trackAccountLocked: trackingEventFnWithoutPayload(EventNames.ACCOUNT_LOCKED), - trackAccountReady: (address: string) => trackingEventFnWithPayload(EventNames.ACCOUNT_READY)({ address }), + trackAccountReady: (eventProperties: AccountReadyEventProperties) => + trackingEventFnWithPayload(EventNames.ACCOUNT_READY)({ ...eventProperties }), trackAccountUnlockRequested: trackingEventFnWithoutPayload(EventNames.ACCOUNT_UNLOCK_REQUESTED), trackAccountUnlockDenied: trackingEventFnWithoutPayload(EventNames.ACCOUNT_UNLOCK_DENIED), - trackAccountAddressChanged: (address: string) => - trackingEventFnWithPayload(EventNames.ACCOUNT_ADDRESS_CHANGED)({ address }), + trackAccountAddressChanged: (eventProperties: AccountAddressChangedEventProperties) => + trackingEventFnWithPayload(EventNames.ACCOUNT_ADDRESS_CHANGED)({ ...eventProperties }), }; diff --git a/packages/instant/src/util/heap.ts b/packages/instant/src/util/heap.ts index 78ec3b3cc..7c53c9918 100644 --- a/packages/instant/src/util/heap.ts +++ b/packages/instant/src/util/heap.ts @@ -6,11 +6,13 @@ import { HEAP_ANALYTICS_ID } from '../constants'; import { AnalyticsEventOptions, AnalyticsUserOptions } from './analytics'; +export type EventProperties = ObjectMap; + export interface HeapAnalytics { loaded: boolean; appid: string; identify(id: string, idType: string): void; - track(eventName: string, eventProperties?: ObjectMap): void; + track(eventName: string, eventProperties?: EventProperties): void; resetIdentity(): void; addUserProperties(properties: AnalyticsUserOptions): void; addEventProperties(properties: AnalyticsEventOptions): void; -- cgit From 804de89796de047fe43dbb736b5e8b82bb30ee3a Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Wed, 21 Nov 2018 13:40:23 -0800 Subject: chore(instant): revert usage of event properties --- packages/instant/src/redux/analytics_middleware.ts | 4 ++-- packages/instant/src/util/analytics.ts | 13 +++---------- 2 files changed, 5 insertions(+), 12 deletions(-) (limited to 'packages/instant/src') diff --git a/packages/instant/src/redux/analytics_middleware.ts b/packages/instant/src/redux/analytics_middleware.ts index 931902187..299c2560e 100644 --- a/packages/instant/src/redux/analytics_middleware.ts +++ b/packages/instant/src/redux/analytics_middleware.ts @@ -27,10 +27,10 @@ export const analyticsMiddleware: Middleware = store => next => middlewareAction prevAccount.state === AccountState.Ready && prevAccount.address !== curAccount.address; const ethAddress = curAccount.address; if (didJustTurnReady) { - analytics.trackAccountReady({ address: ethAddress }); + analytics.trackAccountReady(ethAddress); analytics.addUserProperties({ lastKnownEthAddress: ethAddress }); } else if (didJustUpdateAddress) { - analytics.trackAccountAddressChanged({ address: ethAddress }); + analytics.trackAccountAddressChanged(ethAddress); analytics.addUserProperties({ lastKnownEthAddress: ethAddress }); } } diff --git a/packages/instant/src/util/analytics.ts b/packages/instant/src/util/analytics.ts index 31233fe7a..e389e1530 100644 --- a/packages/instant/src/util/analytics.ts +++ b/packages/instant/src/util/analytics.ts @@ -48,12 +48,6 @@ export interface AnalyticsEventOptions { gitSha?: string; npmVersion?: string; } -export interface AccountReadyEventProperties { - address: string; -} -export interface AccountAddressChangedEventProperties { - address: string; -} export const analytics = { addUserProperties: (properties: AnalyticsUserOptions): void => { @@ -68,10 +62,9 @@ export const analytics = { }, trackInstantOpened: trackingEventFnWithoutPayload(EventNames.INSTANT_OPENED), trackAccountLocked: trackingEventFnWithoutPayload(EventNames.ACCOUNT_LOCKED), - trackAccountReady: (eventProperties: AccountReadyEventProperties) => - trackingEventFnWithPayload(EventNames.ACCOUNT_READY)({ ...eventProperties }), + trackAccountReady: (address: string) => trackingEventFnWithPayload(EventNames.ACCOUNT_READY)({ address }), trackAccountUnlockRequested: trackingEventFnWithoutPayload(EventNames.ACCOUNT_UNLOCK_REQUESTED), trackAccountUnlockDenied: trackingEventFnWithoutPayload(EventNames.ACCOUNT_UNLOCK_DENIED), - trackAccountAddressChanged: (eventProperties: AccountAddressChangedEventProperties) => - trackingEventFnWithPayload(EventNames.ACCOUNT_ADDRESS_CHANGED)({ ...eventProperties }), + trackAccountAddressChanged: (address: string) => + trackingEventFnWithPayload(EventNames.ACCOUNT_ADDRESS_CHANGED)({ address }), }; -- cgit