aboutsummaryrefslogtreecommitdiffstats
path: root/packages/instant/src/util
diff options
context:
space:
mode:
Diffstat (limited to 'packages/instant/src/util')
-rw-r--r--packages/instant/src/util/analytics.ts64
-rw-r--r--packages/instant/src/util/heap.ts113
-rw-r--r--packages/instant/src/util/provider_state_factory.ts2
3 files changed, 178 insertions, 1 deletions
diff --git a/packages/instant/src/util/analytics.ts b/packages/instant/src/util/analytics.ts
new file mode 100644
index 000000000..2ffaac1dd
--- /dev/null
+++ b/packages/instant/src/util/analytics.ts
@@ -0,0 +1,64 @@
+import { ObjectMap } from '@0x/types';
+
+import { heapUtil } from './heap';
+
+let isDisabled = false;
+export const disableAnalytics = (shouldDisableAnalytics: boolean) => {
+ isDisabled = shouldDisableAnalytics;
+};
+export const evaluateIfEnabled = (fnCall: () => void) => {
+ if (isDisabled) {
+ return;
+ }
+ fnCall();
+};
+
+enum EventNames {
+ INSTANT_OPENED = 'Instant - Opened',
+ WALLET_READY = 'Wallet - Ready',
+}
+const track = (eventName: EventNames, eventData: ObjectMap<string | number> = {}): void => {
+ evaluateIfEnabled(() => {
+ heapUtil.evaluateHeapCall(heap => heap.track(eventName, eventData));
+ });
+};
+function trackingEventFnWithoutPayload(eventName: EventNames): () => void {
+ return () => {
+ track(eventName);
+ };
+}
+// tslint:disable-next-line:no-unused-variable
+function trackingEventFnWithPayload<T extends ObjectMap<string | number>>(
+ eventName: EventNames,
+): (eventDataProperties: T) => void {
+ return (eventDataProperties: T) => {
+ track(eventName, eventDataProperties);
+ };
+}
+
+export interface AnalyticsUserOptions {
+ ethAddress?: string;
+ ethBalanceInUnitAmount?: string;
+}
+export interface AnalyticsEventOptions {
+ embeddedHost?: string;
+ embeddedUrl?: string;
+ networkId?: number;
+ providerName?: string;
+ gitSha?: string;
+ npmVersion?: string;
+}
+export const analytics = {
+ addUserProperties: (properties: AnalyticsUserOptions): void => {
+ evaluateIfEnabled(() => {
+ heapUtil.evaluateHeapCall(heap => heap.addUserProperties(properties));
+ });
+ },
+ addEventProperties: (properties: AnalyticsEventOptions): void => {
+ evaluateIfEnabled(() => {
+ heapUtil.evaluateHeapCall(heap => heap.addEventProperties(properties));
+ });
+ },
+ trackWalletReady: trackingEventFnWithoutPayload(EventNames.WALLET_READY),
+ trackInstantOpened: trackingEventFnWithoutPayload(EventNames.INSTANT_OPENED),
+};
diff --git a/packages/instant/src/util/heap.ts b/packages/instant/src/util/heap.ts
new file mode 100644
index 000000000..78ec3b3cc
--- /dev/null
+++ b/packages/instant/src/util/heap.ts
@@ -0,0 +1,113 @@
+import { ObjectMap } from '@0x/types';
+import { logUtils } from '@0x/utils';
+import * as _ from 'lodash';
+
+import { HEAP_ANALYTICS_ID } from '../constants';
+
+import { AnalyticsEventOptions, AnalyticsUserOptions } from './analytics';
+
+export interface HeapAnalytics {
+ loaded: boolean;
+ appid: string;
+ identify(id: string, idType: string): void;
+ track(eventName: string, eventProperties?: ObjectMap<string | number>): void;
+ resetIdentity(): void;
+ addUserProperties(properties: AnalyticsUserOptions): void;
+ addEventProperties(properties: AnalyticsEventOptions): void;
+ removeEventProperty(property: string): void;
+ clearEventProperties(): void;
+}
+interface ModifiedWindow {
+ heap?: HeapAnalytics;
+ zeroExInstantLoadedHeap?: boolean;
+}
+const getWindow = (): ModifiedWindow => {
+ return window as ModifiedWindow;
+};
+
+const setupZeroExInstantHeap = () => {
+ if (_.isUndefined(HEAP_ANALYTICS_ID)) {
+ return;
+ }
+
+ const curWindow = getWindow();
+ // Set property to specify that this is zeroEx's heap
+ curWindow.zeroExInstantLoadedHeap = true;
+
+ // Typescript-compatible version of https://docs.heapanalytics.com/docs/installation
+ /* tslint:disable */
+ ((window as any).heap = (window as any).heap || []),
+ ((window as any).heap.load = function(e: any, t: any) {
+ ((window as any).heap.appid = e), ((window as any).heap.config = t = t || {});
+ var r = t.forceSSL || 'https:' === (document.location as Location).protocol,
+ a = document.createElement('script');
+ (a.type = 'text/javascript'),
+ (a.async = !0),
+ (a.src = (r ? 'https:' : 'http:') + '//cdn.heapanalytics.com/js/heap-' + e + '.js');
+ var n = document.getElementsByTagName('script')[0];
+ (n.parentNode as Node).insertBefore(a, n);
+ for (
+ var o = function(e: any) {
+ return function() {
+ (window as any).heap.push([e].concat(Array.prototype.slice.call(arguments, 0)));
+ };
+ },
+ p = [
+ 'addEventProperties',
+ 'addUserProperties',
+ 'clearEventProperties',
+ 'identify',
+ 'resetIdentity',
+ 'removeEventProperty',
+ 'setEventProperties',
+ 'track',
+ 'unsetEventProperty',
+ ],
+ c = 0;
+ c < p.length;
+ c++
+ )
+ (window as any).heap[p[c]] = o(p[c]);
+ });
+ (window as any).heap.load(HEAP_ANALYTICS_ID);
+ /* tslint:enable */
+
+ return curWindow.heap as HeapAnalytics;
+};
+
+export const heapUtil = {
+ getHeap: (): HeapAnalytics | undefined => {
+ const curWindow = getWindow();
+ const hasOtherExistingHeapIntegration = curWindow.heap && !curWindow.zeroExInstantLoadedHeap;
+ if (hasOtherExistingHeapIntegration) {
+ return undefined;
+ }
+
+ const zeroExInstantHeapIntegration = curWindow.zeroExInstantLoadedHeap && curWindow.heap;
+ if (zeroExInstantHeapIntegration) {
+ return zeroExInstantHeapIntegration;
+ }
+
+ return setupZeroExInstantHeap();
+ },
+ evaluateHeapCall: (heapFunctionCall: (heap: HeapAnalytics) => void): void => {
+ if (_.isUndefined(HEAP_ANALYTICS_ID)) {
+ return;
+ }
+
+ const curHeap = heapUtil.getHeap();
+ if (curHeap) {
+ try {
+ if (curHeap.appid !== HEAP_ANALYTICS_ID) {
+ // Integrator has included heap after us and reset the app id
+ return;
+ }
+ heapFunctionCall(curHeap);
+ } catch (e) {
+ // We never want analytics to crash our React component
+ // TODO(sk): error reporter here
+ logUtils.log('Analytics error', e);
+ }
+ }
+ },
+};
diff --git a/packages/instant/src/util/provider_state_factory.ts b/packages/instant/src/util/provider_state_factory.ts
index 452a71460..7c788dff2 100644
--- a/packages/instant/src/util/provider_state_factory.ts
+++ b/packages/instant/src/util/provider_state_factory.ts
@@ -56,7 +56,7 @@ export const providerStateFactory = {
getInitialProviderStateFallback: (orderSource: OrderSource, network: Network): ProviderState => {
const provider = providerFactory.getFallbackNoSigningProvider(network);
const providerState: ProviderState = {
- name: envUtil.getProviderName(provider),
+ name: 'Fallback',
provider,
web3Wrapper: new Web3Wrapper(provider),
assetBuyer: assetBuyerFactory.getAssetBuyer(provider, orderSource, network),