aboutsummaryrefslogtreecommitdiffstats
path: root/packages/instant
diff options
context:
space:
mode:
authorSteve Klebanoff <steve.klebanoff@gmail.com>2018-11-27 01:18:48 +0800
committerSteve Klebanoff <steve.klebanoff@gmail.com>2018-11-27 01:18:48 +0800
commit271adcdb7e3ecb9f88f05f36ffb71d2147bac292 (patch)
tree80d17771617e540908dd99e9cb63a737630aa37d /packages/instant
parent717a3bce8cd0d4cb782918b3ad806f6c1bdb825e (diff)
parent6d565f4bff38b12515f4d8f0e29cdc223c12d1fb (diff)
downloaddexon-sol-tools-271adcdb7e3ecb9f88f05f36ffb71d2147bac292.tar
dexon-sol-tools-271adcdb7e3ecb9f88f05f36ffb71d2147bac292.tar.gz
dexon-sol-tools-271adcdb7e3ecb9f88f05f36ffb71d2147bac292.tar.bz2
dexon-sol-tools-271adcdb7e3ecb9f88f05f36ffb71d2147bac292.tar.lz
dexon-sol-tools-271adcdb7e3ecb9f88f05f36ffb71d2147bac292.tar.xz
dexon-sol-tools-271adcdb7e3ecb9f88f05f36ffb71d2147bac292.tar.zst
dexon-sol-tools-271adcdb7e3ecb9f88f05f36ffb71d2147bac292.zip
Merge branch 'development' into feature/instant/rollbar-env
Diffstat (limited to 'packages/instant')
-rw-r--r--packages/instant/CHANGELOG.json12
-rw-r--r--packages/instant/CHANGELOG.md9
-rw-r--r--packages/instant/package.json18
-rw-r--r--packages/instant/public/index.html329
-rw-r--r--packages/instant/src/containers/connected_account_payment_method.ts8
-rw-r--r--packages/instant/src/index.umd.ts111
-rw-r--r--packages/instant/src/redux/analytics_middleware.ts34
-rw-r--r--packages/instant/src/redux/async_data.ts2
-rw-r--r--packages/instant/src/util/analytics.ts32
-rw-r--r--packages/instant/src/util/heap.ts4
10 files changed, 357 insertions, 202 deletions
diff --git a/packages/instant/CHANGELOG.json b/packages/instant/CHANGELOG.json
index fe51488c7..db187140f 100644
--- a/packages/instant/CHANGELOG.json
+++ b/packages/instant/CHANGELOG.json
@@ -1 +1,11 @@
-[]
+[
+ {
+ "timestamp": 1542821676,
+ "version": "1.0.1",
+ "changes": [
+ {
+ "note": "Dependencies updated"
+ }
+ ]
+ }
+]
diff --git a/packages/instant/CHANGELOG.md b/packages/instant/CHANGELOG.md
index 8b1378917..c8be0c644 100644
--- a/packages/instant/CHANGELOG.md
+++ b/packages/instant/CHANGELOG.md
@@ -1 +1,10 @@
+<!--
+changelogUtils.file is auto-generated using the monorepo-scripts package. Don't edit directly.
+Edit the package's CHANGELOG.json file only.
+-->
+CHANGELOG
+
+## v1.0.1 - _November 21, 2018_
+
+ * Dependencies updated
diff --git a/packages/instant/package.json b/packages/instant/package.json
index e37ca1ea2..fd2f12857 100644
--- a/packages/instant/package.json
+++ b/packages/instant/package.json
@@ -1,6 +1,6 @@
{
"name": "@0x/instant",
- "version": "1.0.0",
+ "version": "1.0.1",
"engines": {
"node": ">=6.12"
},
@@ -44,15 +44,15 @@
},
"homepage": "https://github.com/0xProject/0x-monorepo/packages/instant/README.md",
"dependencies": {
- "@0x/assert": "^1.0.17",
- "@0x/asset-buyer": "^3.0.0",
- "@0x/json-schemas": "^2.1.1",
- "@0x/order-utils": "^3.0.2",
- "@0x/subproviders": "^2.1.4",
- "@0x/types": "^1.2.1",
+ "@0x/assert": "^1.0.18",
+ "@0x/asset-buyer": "^3.0.1",
+ "@0x/json-schemas": "^2.1.2",
+ "@0x/order-utils": "^3.0.3",
+ "@0x/subproviders": "^2.1.5",
+ "@0x/types": "^1.3.0",
"@0x/typescript-typings": "^3.0.4",
- "@0x/utils": "^2.0.5",
- "@0x/web3-wrapper": "^3.1.4",
+ "@0x/utils": "^2.0.6",
+ "@0x/web3-wrapper": "^3.1.5",
"bowser": "^1.9.4",
"copy-to-clipboard": "^3.0.8",
"ethereum-types": "^1.1.2",
diff --git a/packages/instant/public/index.html b/packages/instant/public/index.html
index 253cbb194..df39994ef 100644
--- a/packages/instant/public/index.html
+++ b/packages/instant/public/index.html
@@ -1,137 +1,206 @@
<!DOCTYPE html>
<html>
+ <head>
+ <meta charset="utf-8" />
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
+ <title>0x Instant Dev Environment</title>
+ <link rel="stylesheet" href="/external.css" />
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.2/css/bulma.min.css" />
+ <script type="text/javascript" src="/instant.js" charset="utf-8"></script>
+ <script type="text/javascript" src="https://unpkg.com/jsuri@1.3.1/Uri.js" charset="utf-8"></script>
+ <script type="text/javascript" src="https://unpkg.com/bignumber.js@4.1.0/bignumber.js" charset="utf-8"></script>
+ <style>
+ .flex-center {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ height: 100%;
+ width: 100%;
+ }
-<head>
- <meta charset="utf-8">
- <meta name="viewport" content="width=device-width, initial-scale=1">
- <title>0x Instant Dev Environment</title>
- <link rel="stylesheet" href="/external.css">
- <script type="text/javascript" src="/instant.js" charset="utf-8"></script>
- <script type="text/javascript" src="https://unpkg.com/jsuri@1.3.1/Uri.js" charset="utf-8"></script>
- <script type="text/javascript" src="https://unpkg.com/bignumber.js@4.1.0/bignumber.js" charset="utf-8"></script>
- <style>
- #zeroExInstantContainer {
- display: flex;
- justify-content: center;
- align-items: center;
- height: 100vh;
- }
+ .flex-center--column {
+ flex-direction: column;
+ }
- body {
- margin: 0;
- background-color: rgba(0, 0, 0, 0.2);
- }
- </style>
-</head>
+ .button {
+ margin: 10px;
+ }
-<body>
- <div id="zeroExInstantContainer"></div>
- <script>
- const removeUndefined = (obj) => {
- for (let k in obj) if (obj[k] === undefined) delete obj[k];
- return obj;
- }
- BigNumber.config({
- EXPONENTIAL_AT: 1000,
- DECIMAL_PLACES: 78,
- });
- const providedOrders = [
- // Order selling REP
- {
- senderAddress: '0x0000000000000000000000000000000000000000',
- makerAddress: '0x34a745008a643eebc58920eaa29fb1165b4a288e',
- takerAddress: '0x0000000000000000000000000000000000000000',
- makerFee: new BigNumber('0'),
- takerFee: new BigNumber('0'),
- makerAssetAmount: new BigNumber('200000000000000000000'),
- takerAssetAmount: new BigNumber('10000000000000000000'),
- makerAssetData: '0xf47261b00000000000000000000000008cb3971b8eb709c14616bd556ff6683019e90d9c',
- takerAssetData: '0xf47261b0000000000000000000000000d0a1e359811322d97991e03f863a0c30c2cf029c',
- expirationTimeSeconds: new BigNumber('1601535600'),
- feeRecipientAddress: '0x0000000000000000000000000000000000000000',
- salt: new BigNumber('3101985707338942582579795423923841749956600670712030922928319824580764688653'),
- signature: '0x1bd4d5686fea801fe33c68c4944356085e7e6cb553eb7073160abd815609f714e85fb47f44b7ffd0a2a1321ac40d72d55163869d0a50fdb5a402132150fe33a08403',
- exchangeAddress: '0x35dd2932454449b14cee11a94d3674a936d5d7b2'
- },
- // Order selling ZRX
- {
- senderAddress: '0x0000000000000000000000000000000000000000',
- makerAddress: '0x34a745008a643eebc58920eaa29fb1165b4a288e',
- takerAddress: '0x0000000000000000000000000000000000000000',
- makerFee: new BigNumber('0'),
- takerFee: new BigNumber('0'),
- makerAssetAmount: new BigNumber('300000000000000000000'),
- takerAssetAmount: new BigNumber('31000000000000000000'),
- makerAssetData: '0xf47261b00000000000000000000000002002d3812f58e35f0ea1ffbf80a75a38c32175fa',
- takerAssetData: '0xf47261b0000000000000000000000000d0a1e359811322d97991e03f863a0c30c2cf029c',
- expirationTimeSeconds: new BigNumber('2524636800'),
- feeRecipientAddress: '0x0000000000000000000000000000000000000000',
- salt: new BigNumber('64592004666704945574675477805199411288137454783320798602050822322450089238268'),
- signature: '0x1c13cacddca8d7d8248e91f412377e68f8f1f9891a59a6c1b2eea9f7b33558c30c4fb86a448e08ab7def40a28fb3a3062dcb33bb3c45302447fce5c4288b7c7f5b03',
- exchangeAddress: '0x35dd2932454449b14cee11a94d3674a936d5d7b2'
- },
- // Order selling GNT
- {
- senderAddress: '0x0000000000000000000000000000000000000000',
- makerAddress: '0x34a745008a643eebc58920eaa29fb1165b4a288e',
- takerAddress: '0x0000000000000000000000000000000000000000',
- makerFee: new BigNumber('0'),
- takerFee: new BigNumber('0'),
- makerAssetAmount: new BigNumber('250000000000000000000'),
- takerAssetAmount: new BigNumber('10000000000000000000'),
- makerAssetData: '0xf47261b000000000000000000000000031fb614e223706f15d0d3c5f4b08bdf0d5c78623',
- takerAssetData: '0xf47261b0000000000000000000000000d0a1e359811322d97991e03f863a0c30c2cf029c',
- expirationTimeSeconds: new BigNumber('1601535600'),
- feeRecipientAddress: '0x0000000000000000000000000000000000000000',
- salt: new BigNumber('40204378562212615907903051460421336779451270522691667164301816101569427926606'),
- signature: '0x1c788bf4b93769da1e8f195f52f0f59b4a298ac6da30cf6d05a87ed4be5ee974f61352ed1bc6a0844d0962b8c894c9ca08e452431255958a4e98dd93cbe1fbc73803',
- exchangeAddress: '0x35dd2932454449b14cee11a94d3674a936d5d7b2'
- },
- // Order selling MKR
- {
- senderAddress: '0x0000000000000000000000000000000000000000',
- makerAddress: '0x34a745008a643eebc58920eaa29fb1165b4a288e',
- takerAddress: '0x0000000000000000000000000000000000000000',
- makerFee: new BigNumber('0'),
- takerFee: new BigNumber('0'),
- makerAssetAmount: new BigNumber('200000000000000000000'),
- takerAssetAmount: new BigNumber('5000000000000000000'),
- makerAssetData: '0xf47261b00000000000000000000000007b6b10caa9e8e9552ba72638ea5b47c25afea1f3',
- takerAssetData: '0xf47261b0000000000000000000000000d0a1e359811322d97991e03f863a0c30c2cf029c',
- expirationTimeSeconds: new BigNumber('1601535600'),
- feeRecipientAddress: '0x0000000000000000000000000000000000000000',
- salt: new BigNumber('71338269924068280039932133924198049371838034090153601678083172009862985793828'),
- signature: '0x1bb3151d57ee1e8fa697767ce83ee4ba77d1ceb8cc1e79c7d77126b3687517704c50c6b3d9cb42c7e7d4478d574b297dfbd1626c5c18a7bc9c2a792c4c07f0797c03',
- exchangeAddress: '0x35dd2932454449b14cee11a94d3674a936d5d7b2'
+ body {
+ margin: 0;
+ height: 100vh;
+ background-color: rgba(0, 0, 0, 0.2);
}
- ];
- const queryParams = new Uri(window.location.search);
- const renderOptionsDefaults = {
- orderSource: 'https://api.radarrelay.com/0x/v2/',
- onClose: () => { console.log('0x Instant Closed') }
- }
- const orderSourceOverride = queryParams.getQueryParamValue('orderSource');
- const availableAssetDatasString = queryParams.getQueryParamValue('availableAssetDatas');
- const feeRecipientOverride = queryParams.getQueryParamValue('feeRecipient');
- const feePercentageOverride = +queryParams.getQueryParamValue('feePercentage');
- let affiliateInfoOverride;
- if (feeRecipientOverride !== undefined && feePercentageOverride !== undefined) {
- affiliateInfoOverride = {
- feeRecipient: feeRecipientOverride,
- feePercentage: feePercentageOverride
- };
- }
- const renderOptionsOverrides = {
- orderSource: orderSourceOverride === 'provided' ? providedOrders : orderSourceOverride,
- networkId: +queryParams.getQueryParamValue('networkId') || undefined,
- defaultAssetBuyAmount: +queryParams.getQueryParamValue('defaultAssetBuyAmount') || undefined,
- availableAssetDatas: availableAssetDatasString ? JSON.parse(availableAssetDatasString) : undefined,
- defaultSelectedAssetData: queryParams.getQueryParamValue('defaultSelectedAssetData'),
- affiliateInfo: affiliateInfoOverride,
- }
- const renderOptions = Object.assign({}, renderOptionsDefaults, removeUndefined(renderOptionsOverrides));
- zeroExInstant.render(renderOptions);
- </script>
-</body>
+ </style>
+ </head>
+
+ <body>
+ <div class="flex-center flex-center--column">
+ <div><button class="button is-large" onClick="renderWithUrlDefaults()">Open</button></div>
+ <div>
+ <button
+ class="button is-danger"
+ onClick="renderWithAssetData('0xf47261b00000000000000000000000001985365e9f78359a9b6ad760e32412f4a445e862')"
+ >
+ Buy REP
+ </button>
+ <button
+ class="button is-black"
+ onClick="renderWithAssetData('0xf47261b0000000000000000000000000e41d2489571d322189246dafa5ebde1f4699f498')"
+ >
+ Buy ZRX
+ </button>
+ <button
+ class="button is-info"
+ onClick="renderWithAssetData('0xf47261b00000000000000000000000006810e776880c02933d47db1b9fc05908e5386b96')"
+ >
+ Buy GNO
+ </button>
+ </div>
+ </div>
+ <div id="zeroExInstantContainer"></div>
+ <script>
+ // Simulate history
+ window.history.pushState({ page: 1 }, '0x Instant');
+ window.history.pushState({ page: 2 }, '0x Instant');
+ window.history.pushState({ page: 3 }, '0x Instant');
+ window.onpopstate = () => console.log("Integrator's onpopstate called");
-</html> \ No newline at end of file
+ const removeUndefined = obj => {
+ for (let k in obj) if (obj[k] === undefined) delete obj[k];
+ return obj;
+ };
+ BigNumber.config({
+ EXPONENTIAL_AT: 1000,
+ DECIMAL_PLACES: 78,
+ });
+ const providedOrders = [
+ // Order selling REP
+ {
+ senderAddress: '0x0000000000000000000000000000000000000000',
+ makerAddress: '0x34a745008a643eebc58920eaa29fb1165b4a288e',
+ takerAddress: '0x0000000000000000000000000000000000000000',
+ makerFee: new BigNumber('0'),
+ takerFee: new BigNumber('0'),
+ makerAssetAmount: new BigNumber('200000000000000000000'),
+ takerAssetAmount: new BigNumber('10000000000000000000'),
+ makerAssetData: '0xf47261b00000000000000000000000008cb3971b8eb709c14616bd556ff6683019e90d9c',
+ takerAssetData: '0xf47261b0000000000000000000000000d0a1e359811322d97991e03f863a0c30c2cf029c',
+ expirationTimeSeconds: new BigNumber('1601535600'),
+ feeRecipientAddress: '0x0000000000000000000000000000000000000000',
+ salt: new BigNumber('3101985707338942582579795423923841749956600670712030922928319824580764688653'),
+ signature:
+ '0x1bd4d5686fea801fe33c68c4944356085e7e6cb553eb7073160abd815609f714e85fb47f44b7ffd0a2a1321ac40d72d55163869d0a50fdb5a402132150fe33a08403',
+ exchangeAddress: '0x35dd2932454449b14cee11a94d3674a936d5d7b2',
+ },
+ // Order selling ZRX
+ {
+ senderAddress: '0x0000000000000000000000000000000000000000',
+ makerAddress: '0x34a745008a643eebc58920eaa29fb1165b4a288e',
+ takerAddress: '0x0000000000000000000000000000000000000000',
+ makerFee: new BigNumber('0'),
+ takerFee: new BigNumber('0'),
+ makerAssetAmount: new BigNumber('300000000000000000000'),
+ takerAssetAmount: new BigNumber('31000000000000000000'),
+ makerAssetData: '0xf47261b00000000000000000000000002002d3812f58e35f0ea1ffbf80a75a38c32175fa',
+ takerAssetData: '0xf47261b0000000000000000000000000d0a1e359811322d97991e03f863a0c30c2cf029c',
+ expirationTimeSeconds: new BigNumber('2524636800'),
+ feeRecipientAddress: '0x0000000000000000000000000000000000000000',
+ salt: new BigNumber(
+ '64592004666704945574675477805199411288137454783320798602050822322450089238268',
+ ),
+ signature:
+ '0x1c13cacddca8d7d8248e91f412377e68f8f1f9891a59a6c1b2eea9f7b33558c30c4fb86a448e08ab7def40a28fb3a3062dcb33bb3c45302447fce5c4288b7c7f5b03',
+ exchangeAddress: '0x35dd2932454449b14cee11a94d3674a936d5d7b2',
+ },
+ // Order selling GNT
+ {
+ senderAddress: '0x0000000000000000000000000000000000000000',
+ makerAddress: '0x34a745008a643eebc58920eaa29fb1165b4a288e',
+ takerAddress: '0x0000000000000000000000000000000000000000',
+ makerFee: new BigNumber('0'),
+ takerFee: new BigNumber('0'),
+ makerAssetAmount: new BigNumber('250000000000000000000'),
+ takerAssetAmount: new BigNumber('10000000000000000000'),
+ makerAssetData: '0xf47261b000000000000000000000000031fb614e223706f15d0d3c5f4b08bdf0d5c78623',
+ takerAssetData: '0xf47261b0000000000000000000000000d0a1e359811322d97991e03f863a0c30c2cf029c',
+ expirationTimeSeconds: new BigNumber('1601535600'),
+ feeRecipientAddress: '0x0000000000000000000000000000000000000000',
+ salt: new BigNumber(
+ '40204378562212615907903051460421336779451270522691667164301816101569427926606',
+ ),
+ signature:
+ '0x1c788bf4b93769da1e8f195f52f0f59b4a298ac6da30cf6d05a87ed4be5ee974f61352ed1bc6a0844d0962b8c894c9ca08e452431255958a4e98dd93cbe1fbc73803',
+ exchangeAddress: '0x35dd2932454449b14cee11a94d3674a936d5d7b2',
+ },
+ // Order selling MKR
+ {
+ senderAddress: '0x0000000000000000000000000000000000000000',
+ makerAddress: '0x34a745008a643eebc58920eaa29fb1165b4a288e',
+ takerAddress: '0x0000000000000000000000000000000000000000',
+ makerFee: new BigNumber('0'),
+ takerFee: new BigNumber('0'),
+ makerAssetAmount: new BigNumber('200000000000000000000'),
+ takerAssetAmount: new BigNumber('5000000000000000000'),
+ makerAssetData: '0xf47261b00000000000000000000000007b6b10caa9e8e9552ba72638ea5b47c25afea1f3',
+ takerAssetData: '0xf47261b0000000000000000000000000d0a1e359811322d97991e03f863a0c30c2cf029c',
+ expirationTimeSeconds: new BigNumber('1601535600'),
+ feeRecipientAddress: '0x0000000000000000000000000000000000000000',
+ salt: new BigNumber(
+ '71338269924068280039932133924198049371838034090153601678083172009862985793828',
+ ),
+ signature:
+ '0x1bb3151d57ee1e8fa697767ce83ee4ba77d1ceb8cc1e79c7d77126b3687517704c50c6b3d9cb42c7e7d4478d574b297dfbd1626c5c18a7bc9c2a792c4c07f0797c03',
+ exchangeAddress: '0x35dd2932454449b14cee11a94d3674a936d5d7b2',
+ },
+ ];
+ const getRenderOptionsOverridesFromUrl = () => {
+ const queryParams = new Uri(window.location.search);
+ const orderSourceOverride = queryParams.getQueryParamValue('orderSource');
+ const availableAssetDatasString = queryParams.getQueryParamValue('availableAssetDatas');
+ const feeRecipientOverride = queryParams.getQueryParamValue('feeRecipient');
+ const feePercentageOverride = +queryParams.getQueryParamValue('feePercentage');
+ let affiliateInfoOverride;
+ if (feeRecipientOverride !== undefined && feePercentageOverride !== undefined) {
+ affiliateInfoOverride = {
+ feeRecipient: feeRecipientOverride,
+ feePercentage: feePercentageOverride,
+ };
+ }
+ const renderOptionsOverrides = {
+ orderSource: orderSourceOverride === 'provided' ? providedOrders : orderSourceOverride,
+ networkId: +queryParams.getQueryParamValue('networkId') || undefined,
+ defaultAssetBuyAmount: +queryParams.getQueryParamValue('defaultAssetBuyAmount') || undefined,
+ availableAssetDatas: availableAssetDatasString ? JSON.parse(availableAssetDatasString) : undefined,
+ defaultSelectedAssetData: queryParams.getQueryParamValue('defaultSelectedAssetData'),
+ affiliateInfo: affiliateInfoOverride,
+ shouldDisablePushToHistory: !!queryParams.getQueryParamValue('shouldDisablePushToHistory'),
+ };
+ return renderOptionsOverrides;
+ };
+ const render = renderOptionsOverrides => {
+ const renderOptionsDefaults = {
+ orderSource: 'https://api.radarrelay.com/0x/v2/',
+ onClose: () => {
+ console.log('0x Instant Closed');
+ },
+ };
+ const renderOptions = Object.assign({}, renderOptionsDefaults, removeUndefined(renderOptionsOverrides));
+ zeroExInstant.render(renderOptions);
+ };
+ const renderWithUrlDefaults = (renderOptions = {}) => {
+ const finalOptions = {
+ ...getRenderOptionsOverridesFromUrl(),
+ ...renderOptions,
+ };
+ render(finalOptions);
+ };
+ renderWithUrlDefaults();
+ const renderWithAssetData = assetData => {
+ renderWithUrlDefaults({
+ defaultSelectedAssetData: assetData,
+ });
+ };
+ </script>
+ </body>
+</html>
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/index.umd.ts b/packages/instant/src/index.umd.ts
index 5010347b3..3a8694d6a 100644
--- a/packages/instant/src/index.umd.ts
+++ b/packages/instant/src/index.umd.ts
@@ -5,40 +5,50 @@ 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);
- if (!_.isUndefined(props.defaultSelectedAssetData)) {
- assert.isHexString('defaultSelectedAssetData', props.defaultSelectedAssetData);
+const isInstantRendered = (): boolean => !!document.getElementById(INJECTED_DIV_ID);
+
+const validateInstantRenderConfig = (config: ZeroExInstantConfig, selector: string) => {
+ assert.isValidOrderSource('orderSource', config.orderSource);
+ if (!_.isUndefined(config.defaultSelectedAssetData)) {
+ assert.isHexString('defaultSelectedAssetData', config.defaultSelectedAssetData);
+ }
+ if (!_.isUndefined(config.additionalAssetMetaDataMap)) {
+ assert.isValidAssetMetaDataMap('additionalAssetMetaDataMap', config.additionalAssetMetaDataMap);
}
- if (!_.isUndefined(props.additionalAssetMetaDataMap)) {
- assert.isValidAssetMetaDataMap('props.additionalAssetMetaDataMap', props.additionalAssetMetaDataMap);
+ if (!_.isUndefined(config.defaultAssetBuyAmount)) {
+ assert.isNumber('defaultAssetBuyAmount', config.defaultAssetBuyAmount);
}
- if (!_.isUndefined(props.defaultAssetBuyAmount)) {
- assert.isNumber('props.defaultAssetBuyAmount', props.defaultAssetBuyAmount);
+ if (!_.isUndefined(config.networkId)) {
+ assert.isNumber('networkId', config.networkId);
}
- if (!_.isUndefined(props.networkId)) {
- assert.isNumber('props.networkId', props.networkId);
+ if (!_.isUndefined(config.availableAssetDatas)) {
+ assert.areValidAssetDatas('availableAssetDatas', config.availableAssetDatas);
}
- if (!_.isUndefined(props.availableAssetDatas)) {
- assert.areValidAssetDatas('availableAssetDatas', props.availableAssetDatas);
+ if (!_.isUndefined(config.onClose)) {
+ assert.isFunction('onClose', config.onClose);
}
- if (!_.isUndefined(props.onClose)) {
- assert.isFunction('props.onClose', props.onClose);
+ if (!_.isUndefined(config.zIndex)) {
+ assert.isNumber('zIndex', config.zIndex);
}
- if (!_.isUndefined(props.zIndex)) {
- assert.isNumber('props.zIndex', props.zIndex);
+ if (!_.isUndefined(config.affiliateInfo)) {
+ assert.isValidAffiliateInfo('affiliateInfo', config.affiliateInfo);
}
- if (!_.isUndefined(props.affiliateInfo)) {
- assert.isValidAffiliateInfo('props.affiliateInfo', props.affiliateInfo);
+ if (!_.isUndefined(config.provider)) {
+ assert.isWeb3Provider('provider', config.provider);
}
- if (!_.isUndefined(props.provider)) {
- assert.isWeb3Provider('props.provider', props.provider);
+ 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.
+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;
@@ -46,14 +56,57 @@ export const render = (props: ZeroExInstantOverlayProps, selector: string = DEFA
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 = {
- ...props,
- onClose: () => {
- appendTo.removeChild(injectedDiv);
- if (!_.isUndefined(props.onClose)) {
- props.onClose();
- }
- },
+ ...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(config, selector);
+ }
+ 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;
};
diff --git a/packages/instant/src/redux/analytics_middleware.ts b/packages/instant/src/redux/analytics_middleware.ts
index f971dbd33..299c2560e 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,24 @@ 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 (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.trackWalletReady();
+ if (didJustTurnReady) {
+ analytics.trackAccountReady(ethAddress);
+ analytics.addUserProperties({ lastKnownEthAddress: ethAddress });
+ } else if (didJustUpdateAddress) {
+ analytics.trackAccountAddressChanged(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, track `Account - Locked`
+ 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 5382494f2..5765a7ca4 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';
@@ -61,6 +62,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..e389e1530 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) => {
@@ -15,11 +13,15 @@ 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<string | number> = {}): 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 {
@@ -28,16 +30,14 @@ function trackingEventFnWithoutPayload(eventName: EventNames): () => void {
};
}
// 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);
+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 {
@@ -48,6 +48,7 @@ export interface AnalyticsEventOptions {
gitSha?: string;
npmVersion?: string;
}
+
export const analytics = {
addUserProperties: (properties: AnalyticsUserOptions): void => {
evaluateIfEnabled(() => {
@@ -59,6 +60,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 }),
};
diff --git a/packages/instant/src/util/heap.ts b/packages/instant/src/util/heap.ts
index 10670b278..279ff3059 100644
--- a/packages/instant/src/util/heap.ts
+++ b/packages/instant/src/util/heap.ts
@@ -7,11 +7,13 @@ import { HEAP_ANALYTICS_ID } from '../constants';
import { AnalyticsEventOptions, AnalyticsUserOptions } from './analytics';
import { errorReporter } from './error_reporter';
+export type EventProperties = ObjectMap<string | number>;
+
export interface HeapAnalytics {
loaded: boolean;
appid: string;
identify(id: string, idType: string): void;
- track(eventName: string, eventProperties?: ObjectMap<string | number>): void;
+ track(eventName: string, eventProperties?: EventProperties): void;
resetIdentity(): void;
addUserProperties(properties: AnalyticsUserOptions): void;
addEventProperties(properties: AnalyticsEventOptions): void;