From 589c814ee618b0443126e598cb5726cb5a5a575a Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Mon, 9 Jul 2018 13:17:57 -0700 Subject: Update icon file names --- packages/website/public/images/token_icons/EOS.png | Bin 0 -> 6979 bytes packages/website/public/images/token_icons/QTUM.png | Bin 0 -> 32496 bytes packages/website/public/images/token_icons/TAAS.png | Bin 0 -> 14580 bytes packages/website/public/images/token_icons/WINGS.png | Bin 0 -> 3822 bytes 4 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 packages/website/public/images/token_icons/EOS.png create mode 100644 packages/website/public/images/token_icons/QTUM.png create mode 100644 packages/website/public/images/token_icons/TAAS.png create mode 100644 packages/website/public/images/token_icons/WINGS.png (limited to 'packages/website') diff --git a/packages/website/public/images/token_icons/EOS.png b/packages/website/public/images/token_icons/EOS.png new file mode 100644 index 000000000..622df61bc Binary files /dev/null and b/packages/website/public/images/token_icons/EOS.png differ diff --git a/packages/website/public/images/token_icons/QTUM.png b/packages/website/public/images/token_icons/QTUM.png new file mode 100644 index 000000000..b7f09dfd2 Binary files /dev/null and b/packages/website/public/images/token_icons/QTUM.png differ diff --git a/packages/website/public/images/token_icons/TAAS.png b/packages/website/public/images/token_icons/TAAS.png new file mode 100644 index 000000000..266e3690b Binary files /dev/null and b/packages/website/public/images/token_icons/TAAS.png differ diff --git a/packages/website/public/images/token_icons/WINGS.png b/packages/website/public/images/token_icons/WINGS.png new file mode 100644 index 000000000..c0a9ce527 Binary files /dev/null and b/packages/website/public/images/token_icons/WINGS.png differ -- cgit v1.2.3 From a3d27cd12801f52154723e4bfb52bf625cadeddc Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Mon, 9 Jul 2018 13:20:49 -0700 Subject: Delete eos.png --- packages/website/public/images/token_icons/eos.png | Bin 6979 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 packages/website/public/images/token_icons/eos.png (limited to 'packages/website') diff --git a/packages/website/public/images/token_icons/eos.png b/packages/website/public/images/token_icons/eos.png deleted file mode 100644 index 622df61bc..000000000 Binary files a/packages/website/public/images/token_icons/eos.png and /dev/null differ -- cgit v1.2.3 From 48390a187527545554b696a647d735753fd77474 Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Mon, 9 Jul 2018 13:21:12 -0700 Subject: Delete qtum.png --- packages/website/public/images/token_icons/qtum.png | Bin 32496 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 packages/website/public/images/token_icons/qtum.png (limited to 'packages/website') diff --git a/packages/website/public/images/token_icons/qtum.png b/packages/website/public/images/token_icons/qtum.png deleted file mode 100644 index b7f09dfd2..000000000 Binary files a/packages/website/public/images/token_icons/qtum.png and /dev/null differ -- cgit v1.2.3 From 50da40a72740c506c21937bd386903027660105a Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Mon, 9 Jul 2018 13:21:29 -0700 Subject: Delete taas.png --- packages/website/public/images/token_icons/taas.png | Bin 14580 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 packages/website/public/images/token_icons/taas.png (limited to 'packages/website') diff --git a/packages/website/public/images/token_icons/taas.png b/packages/website/public/images/token_icons/taas.png deleted file mode 100644 index 266e3690b..000000000 Binary files a/packages/website/public/images/token_icons/taas.png and /dev/null differ -- cgit v1.2.3 From 7efe9a9385e60ce802ce0af9c794669ab7bb45c4 Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Mon, 9 Jul 2018 13:21:46 -0700 Subject: Delete wings.png --- packages/website/public/images/token_icons/wings.png | Bin 3822 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 packages/website/public/images/token_icons/wings.png (limited to 'packages/website') diff --git a/packages/website/public/images/token_icons/wings.png b/packages/website/public/images/token_icons/wings.png deleted file mode 100644 index c0a9ce527..000000000 Binary files a/packages/website/public/images/token_icons/wings.png and /dev/null differ -- cgit v1.2.3 From bd6085fffdbe74ea414477b19bf074ceab2d8098 Mon Sep 17 00:00:00 2001 From: fragosti Date: Mon, 9 Jul 2018 13:25:18 -0700 Subject: Change Jacobs title to Ecosystem Engineer --- packages/website/ts/pages/about/about.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'packages/website') diff --git a/packages/website/ts/pages/about/about.tsx b/packages/website/ts/pages/about/about.tsx index 5bb5d06a9..41c269f40 100644 --- a/packages/website/ts/pages/about/about.tsx +++ b/packages/website/ts/pages/about/about.tsx @@ -99,7 +99,7 @@ const teamRow3: ProfileInfo[] = [ }, { name: 'Jacob Evans', - title: 'Blockchain Engineer', + title: 'Ecosystem Engineer', description: `Previously software engineer at Qantas and RSA Security.`, image: '/images/team/jacob.jpg', linkedIn: 'https://www.linkedin.com/in/dekzter/', -- cgit v1.2.3 From c8bb21d12d6acb3fa76a8d3b22b1cbab3ea63ef8 Mon Sep 17 00:00:00 2001 From: fragosti Date: Mon, 9 Jul 2018 14:26:05 -0700 Subject: Add sourcemaps for rollbar --- packages/website/package.json | 1 + packages/website/ts/components/ui/simple_menu.tsx | 2 +- packages/website/ts/utils/error_reporter.ts | 8 ++++++++ packages/website/webpack.config.js | 13 +++++++++++++ 4 files changed, 23 insertions(+), 1 deletion(-) (limited to 'packages/website') diff --git a/packages/website/package.json b/packages/website/package.json index a3ca047fa..332857dd3 100644 --- a/packages/website/package.json +++ b/packages/website/package.json @@ -92,6 +92,7 @@ "less-loader": "^2.2.3", "make-promises-safe": "^1.1.0", "raw-loader": "^0.5.1", + "rollbar-sourcemap-webpack-plugin": "^2.3.0", "shx": "^0.2.2", "source-map-loader": "^0.1.6", "style-loader": "0.13.x", diff --git a/packages/website/ts/components/ui/simple_menu.tsx b/packages/website/ts/components/ui/simple_menu.tsx index 74b8ef6ae..dcbc6946b 100644 --- a/packages/website/ts/components/ui/simple_menu.tsx +++ b/packages/website/ts/components/ui/simple_menu.tsx @@ -84,5 +84,5 @@ export interface DifferentWalletSimpleMenuItemProps { export const DifferentWalletSimpleMenuItem: React.StatelessComponent = ({ onClick, }) => { - return ; + return ; }; diff --git a/packages/website/ts/utils/error_reporter.ts b/packages/website/ts/utils/error_reporter.ts index f875141fe..83710b81f 100644 --- a/packages/website/ts/utils/error_reporter.ts +++ b/packages/website/ts/utils/error_reporter.ts @@ -13,6 +13,14 @@ const rollbarConfig = { maxItems: 500, payload: { environment: configs.ENVIRONMENT, + client: { + javascript: { + source_map_enabled: true, + // This is only defined in production environments. + code_version: process.env.GIT_SHA, + guess_uncaught_frames: true, + }, + }, }, uncaughtErrorLevel: 'error', hostWhiteList: [configs.DOMAIN_PRODUCTION, configs.DOMAIN_STAGING], diff --git a/packages/website/webpack.config.js b/packages/website/webpack.config.js index b5e9cf6dd..1326769e3 100644 --- a/packages/website/webpack.config.js +++ b/packages/website/webpack.config.js @@ -1,6 +1,13 @@ const path = require('path'); const webpack = require('webpack'); const UglifyJsPlugin = require('uglifyjs-webpack-plugin'); +const RollbarSourceMapPlugin = require('rollbar-sourcemap-webpack-plugin'); +const childProcess = require('child_process'); + +const GIT_SHA = childProcess + .execSync('git rev-parse HEAD') + .toString() + .trim(); module.exports = { entry: ['./ts/index.tsx'], @@ -80,6 +87,7 @@ module.exports = { new webpack.DefinePlugin({ 'process.env': { NODE_ENV: JSON.stringify(process.env.NODE_ENV), + GIT_SHA: GIT_SHA, }, }), // TODO: Revert to webpack bundled version with webpack v4. @@ -92,6 +100,11 @@ module.exports = { }, }, }), + new RollbarSourceMapPlugin({ + accessToken: 'a6619002b51c4464928201e6ea94de65', + version: GIT_SHA, + publicPath: 'https://0xproject.com/', + }), ] : [], }; -- cgit v1.2.3 From a481d2ab46fcc5ef1a0b843f991ba66175eb12ed Mon Sep 17 00:00:00 2001 From: fragosti Date: Mon, 9 Jul 2018 16:07:16 -0700 Subject: Use JSON stringify around GIT_SHA --- packages/website/webpack.config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'packages/website') diff --git a/packages/website/webpack.config.js b/packages/website/webpack.config.js index 1326769e3..89e6e1fd7 100644 --- a/packages/website/webpack.config.js +++ b/packages/website/webpack.config.js @@ -87,7 +87,7 @@ module.exports = { new webpack.DefinePlugin({ 'process.env': { NODE_ENV: JSON.stringify(process.env.NODE_ENV), - GIT_SHA: GIT_SHA, + GIT_SHA: JSON.stringify(GIT_SHA), }, }), // TODO: Revert to webpack bundled version with webpack v4. -- cgit v1.2.3 From ee5ac6b800c16ad16fffe45c168df2a1434e7488 Mon Sep 17 00:00:00 2001 From: fragosti Date: Mon, 9 Jul 2018 16:16:48 -0700 Subject: Fix unsubscribe bug --- packages/website/ts/blockchain.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'packages/website') diff --git a/packages/website/ts/blockchain.ts b/packages/website/ts/blockchain.ts index fde134b18..5476fcf37 100644 --- a/packages/website/ts/blockchain.ts +++ b/packages/website/ts/blockchain.ts @@ -537,7 +537,9 @@ export class Blockchain { } public destroy(): void { this._blockchainWatcher.destroy(); - this._injectedProviderObservable.unsubscribe(this._injectedProviderUpdateHandler); + if (this._injectedProviderObservable) { + this._injectedProviderObservable.unsubscribe(this._injectedProviderUpdateHandler); + } this._stopWatchingExchangeLogFillEvents(); this._stopWatchingGasPrice(); } -- cgit v1.2.3 From a2672a0d783fc53d515fa28b70e23e8036459af8 Mon Sep 17 00:00:00 2001 From: fragosti Date: Mon, 9 Jul 2018 18:04:55 -0700 Subject: Get rollbar uploads working by enabling sourcemaps --- packages/website/package.json | 9 ++++++--- packages/website/ts/utils/constants.ts | 2 +- packages/website/webpack.config.js | 3 ++- 3 files changed, 9 insertions(+), 5 deletions(-) (limited to 'packages/website') diff --git a/packages/website/package.json b/packages/website/package.json index 332857dd3..b5b4b6119 100644 --- a/packages/website/package.json +++ b/packages/website/package.json @@ -11,9 +11,12 @@ "clean": "shx rm -f public/bundle*", "lint": "tslint --project . 'ts/**/*.ts' 'ts/**/*.tsx'", "watch_without_deps": "webpack-dev-server --content-base public --https", - "deploy_dogfood": "npm run build; aws s3 sync ./public/. s3://dogfood.0xproject.com --profile 0xproject --region us-east-1 --grants read=uri=http://acs.amazonaws.com/groups/global/AllUsers", - "deploy_staging": "npm run build; aws s3 sync ./public/. s3://staging-0xproject --profile 0xproject --region us-east-1 --grants read=uri=http://acs.amazonaws.com/groups/global/AllUsers", - "deploy_live": "npm run build; aws s3 sync ./public/. s3://0xproject.com --profile 0xproject --region us-east-1 --grants read=uri=http://acs.amazonaws.com/groups/global/AllUsers" + "deploy_dogfood": + "npm run build; aws s3 sync ./public/. s3://dogfood.0xproject.com --profile 0xproject --region us-east-1 --grants read=uri=http://acs.amazonaws.com/groups/global/AllUsers", + "deploy_staging": + "npm run build; aws s3 sync ./public/. s3://staging-0xproject --profile 0xproject --region us-east-1 --grants read=uri=http://acs.amazonaws.com/groups/global/AllUsers", + "deploy_live": + "npm run build; aws s3 sync ./public/. s3://0xproject.com --profile 0xproject --region us-east-1 --grants read=uri=http://acs.amazonaws.com/groups/global/AllUsers --exclude *.map.js" }, "author": "Fabio Berger", "license": "Apache-2.0", diff --git a/packages/website/ts/utils/constants.ts b/packages/website/ts/utils/constants.ts index 4b3443d21..e43f541bf 100644 --- a/packages/website/ts/utils/constants.ts +++ b/packages/website/ts/utils/constants.ts @@ -33,7 +33,7 @@ export const constants = { PROVIDER_NAME_TOSHI: 'Toshi', PROVIDER_NAME_GENERIC: 'Injected Web3', PROVIDER_NAME_PUBLIC: '0x Public', - ROLLBAR_ACCESS_TOKEN: 'a6619002b51c4464928201e6ea94de65', + ROLLBAR_ACCESS_TOKEN: '32c39bfa4bb6440faedc1612a9c13d28', S3_DOC_BUCKET_ROOT: 'https://s3.amazonaws.com/doc-jsons', S3_STAGING_DOC_BUCKET_ROOT: 'https://s3.amazonaws.com/staging-doc-jsons', SUCCESS_STATUS: 200, diff --git a/packages/website/webpack.config.js b/packages/website/webpack.config.js index 89e6e1fd7..5647b4f93 100644 --- a/packages/website/webpack.config.js +++ b/packages/website/webpack.config.js @@ -94,6 +94,7 @@ module.exports = { // The v3 series bundled version does not support ES6 and // fails to build. new UglifyJsPlugin({ + sourceMap: true, uglifyOptions: { mangle: { reserved: ['BigNumber'], @@ -101,7 +102,7 @@ module.exports = { }, }), new RollbarSourceMapPlugin({ - accessToken: 'a6619002b51c4464928201e6ea94de65', + accessToken: '32c39bfa4bb6440faedc1612a9c13d28', version: GIT_SHA, publicPath: 'https://0xproject.com/', }), -- cgit v1.2.3 From 5dfed8cd00386c185f0397fda329f7ab7bc9401f Mon Sep 17 00:00:00 2001 From: fragosti Date: Mon, 9 Jul 2018 18:17:14 -0700 Subject: Update rollbar for telemetry --- packages/website/public/js/rollbar.umd.min.js | 2 ++ packages/website/public/js/rollbar.umd.nojson.min.js | 1 - packages/website/ts/utils/error_reporter.ts | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) create mode 100644 packages/website/public/js/rollbar.umd.min.js delete mode 100644 packages/website/public/js/rollbar.umd.nojson.min.js (limited to 'packages/website') diff --git a/packages/website/public/js/rollbar.umd.min.js b/packages/website/public/js/rollbar.umd.min.js new file mode 100644 index 000000000..2734bb8be --- /dev/null +++ b/packages/website/public/js/rollbar.umd.min.js @@ -0,0 +1,2 @@ +!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.rollbar=e():t.rollbar=e()}(this,function(){return function(t){function e(n){if(r[n])return r[n].exports;var o=r[n]={exports:{},id:n,loaded:!1};return t[n].call(o.exports,o,o.exports,e),o.loaded=!0,o.exports}var r={};return e.m=t,e.c=r,e.p="",e(0)}([function(t,e,r){t.exports=r(1)},function(t,e,r){"use strict";var n=r(2),o="undefined"!=typeof window&&window._rollbarConfig,i=o&&o.globalAlias||"Rollbar",a="undefined"!=typeof window&&window[i]&&"function"==typeof window[i].shimId&&void 0!==window[i].shimId();if("undefined"==typeof window||window._rollbarStartTime||(window._rollbarStartTime=(new Date).getTime()),!a&&o){var s=new n(o);window[i]=s}else"undefined"!=typeof window?(window.rollbar=n,window._rollbarDidLoad=!0):"undefined"!=typeof self&&(self.rollbar=n,self._rollbarDidLoad=!0);t.exports=n},function(t,e,r){"use strict";function n(t,e){this.options=c.merge(x,t);var r=new l(this.options,h,d);this.client=e||new u(this.options,r,p,"browser");var n="undefined"!=typeof window&&window||"undefined"!=typeof self&&self,o="undefined"!=typeof document&&document;i(this.client.notifier),a(this.client.queue),(this.options.captureUncaught||this.options.handleUncaughtExceptions)&&(f.captureUncaughtExceptions(n,this),f.wrapGlobals(n,this)),(this.options.captureUnhandledRejections||this.options.handleUnhandledRejections)&&f.captureUnhandledRejections(n,this),this.instrumenter=new w(this.options,this.client.telemeter,this,n,o),this.instrumenter.instrument()}function o(t){var e="Rollbar is not initialized";p.error(e),t&&t(new Error(e))}function i(t){t.addTransform(m.handleItemWithError).addTransform(m.ensureItemHasSomethingToSay).addTransform(m.addBaseInfo).addTransform(m.addRequestInfo(window)).addTransform(m.addClientInfo(window)).addTransform(m.addPluginInfo(window)).addTransform(m.addBody).addTransform(g.addMessageWithError).addTransform(g.addTelemetryData).addTransform(g.addConfigToPayload).addTransform(m.scrubPayload).addTransform(g.userTransform(p)).addTransform(g.itemToPayload)}function a(t){t.addPredicate(y.checkLevel).addPredicate(v.checkIgnore).addPredicate(y.userCheckIgnore(p)).addPredicate(y.urlIsNotBlacklisted(p)).addPredicate(y.urlIsWhitelisted(p)).addPredicate(y.messageIsIgnored(p))}function s(t){for(var e=0,r=t.length;e=1&&r>e}function o(t,e,r,n,o,a,s){var u=null;return r&&(r=new Error(r)),r||n||(u=i(t,e,o,a,s)),{error:r,shouldSend:n,payload:u}}function i(t,e,r,n,o){var i,a=e.environment||e.payload&&e.payload.environment;i=o?"item per minute limit reached, ignoring errors until timeout":"maxItems has been hit, ignoring errors until reset.";var s={body:{message:{body:i,extra:{maxItems:r,itemsPerMinute:n}}},language:"javascript",environment:a,notifier:{version:e.notifier&&e.notifier.version||e.version}};return"browser"===t?(s.platform="browser",s.framework="browser-js",s.notifier.name="rollbar-browser-js"):"server"===t?(s.framework=e.framework||"node-js",s.notifier.name=e.notifier.name):"react-native"===t&&(s.framework=e.framework||"react-native",s.notifier.name=e.notifier.name),s}r.globalSettings={startTime:(new Date).getTime(),maxItems:void 0,itemsPerMinute:void 0},r.prototype.configureGlobal=function(t){void 0!==t.startTime&&(r.globalSettings.startTime=t.startTime),void 0!==t.maxItems&&(r.globalSettings.maxItems=t.maxItems),void 0!==t.itemsPerMinute&&(r.globalSettings.itemsPerMinute=t.itemsPerMinute)},r.prototype.shouldSend=function(t,e){e=e||(new Date).getTime(),e-this.startTime>=6e4&&(this.startTime=e,this.perMinCounter=0);var i=r.globalSettings.maxItems,a=r.globalSettings.itemsPerMinute;if(n(t,i,this.counter))return o(this.platform,this.platformOptions,i+" max items reached",!1);if(n(t,a,this.perMinCounter))return o(this.platform,this.platformOptions,a+" items per minute reached",!1);this.counter++,this.perMinCounter++;var s=!n(t,i,this.counter),u=s;return s=s&&!n(t,a,this.perMinCounter),o(this.platform,this.platformOptions,null,s,i,a,u)},r.prototype.setPlatformOptions=function(t,e){this.platform=t,this.platformOptions=e},t.exports=r},function(t,e,r){"use strict";function n(t,e,r,n){this.rateLimiter=t,this.api=e,this.logger=r,this.options=n,this.predicates=[],this.pendingItems=[],this.pendingRequests=[],this.retryQueue=[],this.retryHandle=null,this.waitCallback=null,this.waitIntervalID=null}var o=r(6);n.prototype.configure=function(t){this.api&&this.api.configure(t);var e=this.options;return this.options=o.merge(e,t),this},n.prototype.addPredicate=function(t){return o.isFunction(t)&&this.predicates.push(t),this},n.prototype.addPendingItem=function(t){this.pendingItems.push(t)},n.prototype.removePendingItem=function(t){var e=this.pendingItems.indexOf(t);e!==-1&&this.pendingItems.splice(e,1)},n.prototype.addItem=function(t,e,r,n){e&&o.isFunction(e)||(e=function(){});var i=this._applyPredicates(t);if(i.stop)return this.removePendingItem(n),void e(i.err);this._maybeLog(t,r),this.removePendingItem(n),this.pendingRequests.push(t);try{this._makeApiRequest(t,function(r,n){this._dequeuePendingRequest(t),e(r,n)}.bind(this))}catch(r){this._dequeuePendingRequest(t),e(r)}},n.prototype.wait=function(t){o.isFunction(t)&&(this.waitCallback=t,this._maybeCallWait()||(this.waitIntervalID&&(this.waitIntervalID=clearInterval(this.waitIntervalID)),this.waitIntervalID=setInterval(function(){this._maybeCallWait()}.bind(this),500)))},n.prototype._applyPredicates=function(t){for(var e=null,r=0,n=this.predicates.length;rs)?(a=e.path,e.path=a.substring(0,s)+i+"&"+a.substring(s+1)):u!==-1?(a=e.path,e.path=a.substring(0,u)+i+a.substring(u)):e.path=e.path+i}function y(t,e){if(e=e||t.protocol,!e&&t.port&&(80===t.port?e="http:":443===t.port&&(e="https:")),e=e||"https:",!t.hostname)return null;var r=e+"//"+t.hostname;return t.port&&(r=r+":"+t.port),t.path&&(r+=t.path),r}function b(t,e){var r,n;try{r=R.stringify(t)}catch(o){if(e&&a(e))try{r=e(t)}catch(t){n=t}else n=o}return{error:n,value:r}}function w(t){var e,r;try{e=R.parse(t)}catch(t){r=t}return{error:r,value:e}}function _(t,e,r,n,o,i,a,s){var u={url:e||"",line:r,column:n};u.func=s.guessFunctionName(u.url,u.line),u.context=s.gatherContext(u.url,u.line);var c=document&&document.location&&document.location.href,l=window&&window.navigator&&window.navigator.userAgent;return{mode:i,message:o?String(o):t||a,url:c,stack:[u],useragent:l}}function x(t,e){return function(r,n){try{e(r,n)}catch(e){t.error(e)}}}function k(t,e,r,n,o){for(var a,s,u,c,l,p,f=[],h=0,m=t.length;h0&&(u=j(u),u.extraArgs=f);var b={message:a,err:s,custom:u,timestamp:N(),callback:c,uuid:d()};return u&&void 0!==u.level&&(b.level=u.level,delete u.level),n&&l&&(b.request=l),o&&(b.lambdaContext=o),b._originalArgs=t,b}function E(t,e){if(t){var r=e.split("."),n=t;try{for(var o=0,i=r.length;o500&&(n=n.substr(0,497)+"...");break;case"null":n="null";break;case"undefined":n="undefined";break;case"symbol":n=n.toString()}o.push(n)}return o.join(" ")}function N(){return Date.now?+Date.now():+new Date}function C(t,e){if(t&&t.user_ip&&e!==!0){var r=t.user_ip;if(e)try{var n;if(r.indexOf(".")!==-1)n=r.split("."),n.pop(),n.push("0"),r=n.join(".");else if(r.indexOf(":")!==-1){if(n=r.split(":"),n.length>2){var o=n.slice(0,3),i=o[2].indexOf("/");i!==-1&&(o[2]=o[2].substring(0,i));var a="0000:0000:0000:0000:0000";r=o.concat(a).join(":")}}else r=null}catch(t){r=null}else r=null;t.user_ip=r}}var j=r(7),R={},A=!1;n();var q={debug:0,info:1,warning:2,error:3,critical:4},D={strictMode:!1,key:["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"],q:{name:"queryKey",parser:/(?:^|&)([^&=]*)=?([^&]*)/g},parser:{strict:/^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/,loose:/^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/}};t.exports={isType:o,typeName:i,isFunction:a,isNativeFunction:s,isIterable:l,isError:p,merge:j,traverse:f,redact:h,uuid4:d,LEVELS:q,sanitizeUrl:m,addParamsAndAccessTokenToPath:v,formatUrl:y,stringify:b,jsonParse:w,makeUnhandledStackInfo:_,createItem:k,get:E,set:I,scrub:T,formatArgsAsString:L,now:N,filterIp:C}},function(t,e){"use strict";function r(){var t,e,n,o,a,s={},u=null,c=arguments.length;for(t=0;tn&&(o=this.maxQueueSize-n),this.maxQueueSize=n,this.queue.splice(0,o)},n.prototype.copyEvents=function(){return Array.prototype.slice.call(this.queue,0)},n.prototype.capture=function(t,e,r,n,a){var s={level:o(t,r),type:t,timestamp_ms:a||i.now(),body:e,source:"client"};n&&(s.uuid=n);try{if(i.isFunction(this.options.filterTelemetry)&&this.options.filterTelemetry(s))return!1}catch(t){this.options.filterTelemetry=null}return this.push(s),s},n.prototype.captureEvent=function(t,e,r){return this.capture("manual",t,e,r)},n.prototype.captureError=function(t,e,r,n){var o={message:t.message||String(t)};return t.stack&&(o.stack=t.stack),this.capture("error",o,e,r,n)},n.prototype.captureLog=function(t,e,r,n){return this.capture("log",{message:t},e,r,n)},n.prototype.captureNetwork=function(t,e,r,n){e=e||"xhr",t.subtype=t.subtype||e,n&&(t.request=n);var o=this.levelFromStatus(t.status_code);return this.capture("network",t,o,r)},n.prototype.levelFromStatus=function(t){return t>=200&&t<400?"info":0===t||t>=400?"error":"info"},n.prototype.captureDom=function(t,e,r,n,o){var i={subtype:t,element:e};return void 0!==r&&(i.value=r),void 0!==n&&(i.checked=n),this.capture("dom",i,"info",o)},n.prototype.captureNavigation=function(t,e,r){return this.capture("navigation",{from:t,to:e},"info",r)},n.prototype.captureDomContentLoaded=function(t){return this.capture("navigation",{subtype:"DOMContentLoaded"},"info",void 0,t&&t.getTime())},n.prototype.captureLoad=function(t){return this.capture("navigation",{subtype:"load"},"info",void 0,t&&t.getTime())},n.prototype.captureConnectivityChange=function(t,e){return this.captureNetwork({change:t},"connectivity",e)},n.prototype._captureRollbarItem=function(t){if(this.options.includeItemsInTelemetry)return t.err?this.captureError(t.err,t.level,t.uuid,t.timestamp):t.message?this.captureLog(t.message,t.level,t.uuid,t.timestamp):t.custom?this.capture("log",t.custom,t.level,t.uuid,t.timestamp):void 0},n.prototype.push=function(t){this.queue.push(t),this.queue.length>this.maxQueueSize&&this.queue.shift()},t.exports=n},function(t,e,r){"use strict";function n(t,e,r,n){this.options=t,this.transport=e,this.url=r,this.jsonBackup=n,this.accessToken=t.accessToken,this.transportOptions=o(t,r)}function o(t,e){return a.getTransportFromOptions(t,s,e)}var i=r(6),a=r(12),s={hostname:"api.rollbar.com",path:"/api/1/item/",search:null,version:"1",protocol:"https:",port:443};n.prototype.postItem=function(t,e){var r=a.transportOptions(this.transportOptions,"POST"),n=a.buildPayload(this.accessToken,t,this.jsonBackup);this.transport.post(this.accessToken,r,n,e)},n.prototype.configure=function(t){var e=this.oldOptions;return this.options=i.merge(e,t),this.transportOptions=o(this.options,this.url),void 0!==this.options.accessToken&&(this.accessToken=this.options.accessToken),this},t.exports=n},function(t,e,r){"use strict";function n(t,e,r){if(!s.isType(e.context,"string")){var n=s.stringify(e.context,r);n.error?e.context="Error: could not serialize 'context'":e.context=n.value||"",e.context.length>255&&(e.context=e.context.substr(0,255))}return{access_token:t,data:e}}function o(t,e,r){var n=e.hostname,o=e.protocol,i=e.port,a=e.path,s=e.search,u=t.proxy;if(t.endpoint){var c=r.parse(t.endpoint);n=c.hostname,o=c.protocol,i=c.port,a=c.pathname,s=c.search}return{hostname:n,protocol:o,port:i,path:a,search:s,proxy:u}}function i(t,e){var r=t.protocol||"https:",n=t.port||("http:"===r?80:"https:"===r?443:void 0),o=t.hostname,i=t.path;return t.search&&(i+=t.search),t.proxy&&(i=r+"//"+o+i,o=t.proxy.host||t.proxy.hostname,n=t.proxy.port,r=t.proxy.protocol||r),{protocol:r,hostname:o,path:i,port:n,method:e}}function a(t,e){var r=/\/$/.test(t),n=/^\//.test(e);return r&&n?e=e.substring(1):r||n||(e="/"+e),t+e}var s=r(6);t.exports={buildPayload:n,getTransportFromOptions:o,transportOptions:i,appendPathToPath:a}},function(t,e,r){"use strict";function n(){var t=Array.prototype.slice.call(arguments,0);t.unshift("Rollbar:"),a.ieVersion()<=8?console.error(s.formatArgsAsString(t)):console.error.apply(console,t)}function o(){var t=Array.prototype.slice.call(arguments,0);t.unshift("Rollbar:"),a.ieVersion()<=8?console.info(s.formatArgsAsString(t)):console.info.apply(console,t)}function i(){var t=Array.prototype.slice.call(arguments,0);t.unshift("Rollbar:"),a.ieVersion()<=8?console.log(s.formatArgsAsString(t)):console.log.apply(console,t)}r(14);var a=r(15),s=r(6);t.exports={error:n,info:o,log:i}},function(t,e){!function(t){ +"use strict";t.console||(t.console={});for(var e,r,n=t.console,o=function(){},i=["memory"],a="assert,clear,count,debug,dir,dirxml,error,exception,group,groupCollapsed,groupEnd,info,log,markTimeline,profile,profiles,profileEnd,show,table,time,timeEnd,timeline,timelineEnd,timeStamp,trace,warn".split(",");e=i.pop();)n[e]||(n[e]={});for(;r=a.pop();)n[r]||(n[r]=o)}("undefined"==typeof window?this:window)},function(t,e){"use strict";function r(){var t;if(!document)return t;for(var e=3,r=document.createElement("div"),n=r.getElementsByTagName("i");r.innerHTML="",n[0];);return e>4?e:t}var n={ieVersion:r};t.exports=n},function(t,e){"use strict";function r(t,e,r){if(t){var o;"function"==typeof e._rollbarOldOnError?o=e._rollbarOldOnError:t.onerror&&!t.onerror.belongsToShim&&(o=t.onerror,e._rollbarOldOnError=o);var i=function(){var r=Array.prototype.slice.call(arguments,0);n(t,e,o,r)};i.belongsToShim=r,t.onerror=i}}function n(t,e,r,n){t._rollbarWrappedError&&(n[4]||(n[4]=t._rollbarWrappedError),n[5]||(n[5]=t._rollbarWrappedError._rollbarContext),t._rollbarWrappedError=null),e.handleUncaughtException.apply(e,n),r&&r.apply(t,n)}function o(t,e,r){if(t){"function"==typeof t._rollbarURH&&t._rollbarURH.belongsToShim&&t.removeEventListener("unhandledrejection",t._rollbarURH);var n=function(t){var r,n,o;try{r=t.reason}catch(t){r=void 0}try{n=t.promise}catch(t){n="[unhandledrejection] error getting `promise` from event"}try{o=t.detail,!r&&o&&(r=o.reason,n=o.promise)}catch(t){o="[unhandledrejection] error getting `detail` from event"}r||(r="[unhandledrejection] error getting `reason` from event"),e&&e.handleUnhandledRejection&&e.handleUnhandledRejection(r,n)};n.belongsToShim=r,t._rollbarURH=n,t.addEventListener("unhandledrejection",n)}}function i(t,e,r){if(t){var n,o,i="EventTarget,Window,Node,ApplicationCache,AudioTrackList,ChannelMergerNode,CryptoOperation,EventSource,FileReader,HTMLUnknownElement,IDBDatabase,IDBRequest,IDBTransaction,KeyOperation,MediaController,MessagePort,ModalWindow,Notification,SVGElementInstance,Screen,TextTrack,TextTrackCue,TextTrackList,WebSocket,WebSocketWorker,Worker,XMLHttpRequest,XMLHttpRequestEventTarget,XMLHttpRequestUpload".split(",");for(n=0;n=400&&t.status<600}function c(t,e){var r=new Error(t);return r.code=e||"ENOTFOUND",r}var l=r(6),p=r(18),f=r(13);t.exports={get:n,post:o}},function(t,e,r){"use strict";function n(t,e){return[t,f.stringify(t,e)]}function o(t,e){var r=t.length;return r>2*e?t.slice(0,e).concat(t.slice(r-e)):t}function i(t,e,r){r="undefined"==typeof r?30:r;var n,i=t.data.body;if(i.trace_chain)for(var a=i.trace_chain,s=0;st?e.slice(0,t-3).concat("..."):e}function s(t,e,r){function n(e,r,o){switch(f.typeName(r)){case"string":return a(t,r);case"object":case"array":return f.traverse(r,n,o);default:return r}}return e=f.traverse(e,n,[]),[e,f.stringify(e,r)]}function u(t){return t.exception&&(delete t.exception.description,t.exception.message=a(255,t.exception.message)),t.frames=o(t.frames,1),t}function c(t,e){var r=t.data.body;if(r.trace_chain)for(var n=r.trace_chain,o=0;oe}function p(t,e,r){r="undefined"==typeof r?524288:r;for(var o,a,u,p=[n,i,s.bind(null,1024),s.bind(null,512),s.bind(null,256),c];o=p.shift();)if(a=o(t,e),t=a[0],u=a[1],u.error||!l(u.value,r))return u;return u}var f=r(6);t.exports={truncate:p,raw:n,truncateFrames:i,truncateStrings:s,maybeTruncateValue:a}},function(t,e){"use strict";function r(t){var e,r,n={protocol:null,auth:null,host:null,path:null,hash:null,href:t,hostname:null,port:null,pathname:null,search:null,query:null};if(e=t.indexOf("//"),e!==-1?(n.protocol=t.substring(0,e),r=e+2):r=0,e=t.indexOf("@",r),e!==-1&&(n.auth=t.substring(r,e),r=e+1),e=t.indexOf("/",r),e===-1){if(e=t.indexOf("?",r),e===-1)return e=t.indexOf("#",r),e===-1?n.host=t.substring(r):(n.host=t.substring(r,e),n.hash=t.substring(e)),n.hostname=n.host.split(":")[0],n.port=n.host.split(":")[1],n.port&&(n.port=parseInt(n.port,10)),n;n.host=t.substring(r,e),n.hostname=n.host.split(":")[0],n.port=n.host.split(":")[1],n.port&&(n.port=parseInt(n.port,10)),r=e}else n.host=t.substring(r,e),n.hostname=n.host.split(":")[0],n.port=n.host.split(":")[1],n.port&&(n.port=parseInt(n.port,10)),r=e;if(e=t.indexOf("#",r),e===-1?n.path=t.substring(r):(n.path=t.substring(r,e),n.hash=t.substring(e)),n.path){var o=n.path.split("?");n.pathname=o[0],n.query=o[1],n.search=n.query?"?"+n.query:null}return n}t.exports={parse:r}},function(t,e,r){"use strict";function n(t,e,r){if(t.data=t.data||{},t.err)try{t.stackInfo=t.err._savedStackTrace||d.parse(t.err)}catch(e){m.error("Error while parsing the error object.",e);try{t.message=t.err.message||t.err.description||t.message||String(t.err)}catch(e){t.message=String(t.err)||String(e)}delete t.err}r(null,t)}function o(t,e,r){t.message||t.stackInfo||t.custom||r(new Error("No message, stack info, or custom data"),null),r(null,t)}function i(t,e,r){var n=e.payload&&e.payload.environment||e.environment;t.data=h.merge(t.data,{environment:n,level:t.level,endpoint:e.endpoint,platform:"browser",framework:"browser-js",language:"javascript",server:{},uuid:t.uuid,notifier:{name:"rollbar-browser-js",version:e.version}}),r(null,t)}function a(t){return function(e,r,n){if(!t||!t.location)return n(null,e);var o="$remote_ip";r.captureIp?r.captureIp!==!0&&(o+="_anonymize"):o=null,h.set(e,"data.request",{url:t.location.href,query_string:t.location.search,user_ip:o}),n(null,e)}}function s(t){return function(e,r,n){if(!t)return n(null,e);var o=t.navigator||{},i=t.screen||{};h.set(e,"data.client",{runtime_ms:e.timestamp-t._rollbarStartTime,timestamp:Math.round(e.timestamp/1e3),javascript:{browser:o.userAgent,language:o.language,cookie_enabled:o.cookieEnabled,screen:{width:i.width,height:i.height}}}),n(null,e)}}function u(t){return function(e,r,n){if(!t||!t.navigator)return n(null,e);for(var o,i=[],a=t.navigator.plugins||[],s=0,u=a.length;s-1&&(e=e.replace(/eval code/g,"eval").replace(/(\(eval at [^\()]*)|(\)\,.*$)/g,""));var r=e.replace(/^\s+/,"").replace(/\(eval code/g,"(").split(/\s+/).slice(1),n=this.extractLocation(r.pop()),o=r.join(" ")||void 0,i="eval"===n[0]?void 0:n[0];return new t(o,void 0,i,n[1],n[2],e)},this)},parseFFOrSafari:function(n){var o=r(n.stack.split("\n"),function(t){return!t.match(i)},this);return e(o,function(e){if(e.indexOf(" > eval")>-1&&(e=e.replace(/ line (\d+)(?: > eval line \d+)* > eval\:\d+\:\d+/g,":$1")),e.indexOf("@")===-1&&e.indexOf(":")===-1)return new t(e);var r=e.split("@"),n=this.extractLocation(r.pop()),o=r.shift()||void 0;return new t(o,void 0,n[0],n[1],n[2],e)},this)},parseOpera:function(t){return!t.stacktrace||t.message.indexOf("\n")>-1&&t.message.split("\n").length>t.stacktrace.split("\n").length?this.parseOpera9(t):t.stack?this.parseOpera11(t):this.parseOpera10(t)},parseOpera9:function(e){for(var r=/Line (\d+).*script (?:in )?(\S+)/i,n=e.message.split("\n"),o=[],i=2,a=n.length;i/,"$2").replace(/\([^\)]*\)/g,"")||void 0;i.match(/\(([^\)]*)\)/)&&(r=i.replace(/^[^\(]+\(([^\)]*)\)$/,"$1"));var s=void 0===r||"[arguments not available]"===r?void 0:r.split(",");return new t(a,s,o[0],o[1],o[2],e)},this)}}})},function(t,e,r){var n,o,i;!function(r,a){"use strict";o=[],n=a,i="function"==typeof n?n.apply(e,o):n,!(void 0!==i&&(t.exports=i))}(this,function(){"use strict";function t(t){return!isNaN(parseFloat(t))&&isFinite(t)}function e(t,e,r,n,o,i){void 0!==t&&this.setFunctionName(t),void 0!==e&&this.setArgs(e),void 0!==r&&this.setFileName(r),void 0!==n&&this.setLineNumber(n),void 0!==o&&this.setColumnNumber(o),void 0!==i&&this.setSource(i)}return e.prototype={getFunctionName:function(){return this.functionName},setFunctionName:function(t){this.functionName=String(t)},getArgs:function(){return this.args},setArgs:function(t){if("[object Array]"!==Object.prototype.toString.call(t))throw new TypeError("Args must be an Array");this.args=t},getFileName:function(){return this.fileName},setFileName:function(t){this.fileName=String(t)},getLineNumber:function(){return this.lineNumber},setLineNumber:function(e){if(!t(e))throw new TypeError("Line Number must be a Number");this.lineNumber=Number(e)},getColumnNumber:function(){return this.columnNumber},setColumnNumber:function(e){if(!t(e))throw new TypeError("Column Number must be a Number");this.columnNumber=Number(e)},getSource:function(){return this.source},setSource:function(t){this.source=String(t)},toString:function(){var e=this.getFunctionName()||"{anonymous}",r="("+(this.getArgs()||[]).join(",")+")",n=this.getFileName()?"@"+this.getFileName():"",o=t(this.getLineNumber())?":"+this.getLineNumber():"",i=t(this.getColumnNumber())?":"+this.getColumnNumber():"";return e+r+n+o+i}},e})},function(t,e,r){"use strict";function n(t,e,r){var n=e.payload||{};n.body&&delete n.body;var o=u.merge(t.data,n);t._isUncaught&&(o._isUncaught=!0),t._originalArgs&&(o._originalArgs=t._originalArgs),r(null,o)}function o(t,e,r){t.telemetryEvents&&u.set(t,"data.body.telemetry",t.telemetryEvents),r(null,t)}function i(t,e,r){if(!t.message)return void r(null,t);var n="data.body.trace_chain.0",o=u.get(t,n);if(o||(n="data.body.trace",o=u.get(t,n)),o){if(!o.exception||!o.exception.description)return u.set(t,n+".exception.description",t.message),void r(null,t);var i=u.get(t,n+".extra")||{},a=u.merge(i,{message:t.message});u.set(t,n+".extra",a)}r(null,t)}function a(t){return function(e,r,n){var o=u.merge(e);try{u.isFunction(r.transform)&&r.transform(o.data)}catch(o){return r.transform=null,t.error("Error while calling custom transform() function. Removing custom transform().",o),void n(null,e)}n(null,o)}}function s(t,e,r){if(!e.sendConfig)return r(null,t);var n="_rollbarConfig",o=u.get(t,"data.custom")||{};o[n]=e,t.data.custom=o,r(null,t)}var u=r(6);t.exports={itemToPayload:n,addTelemetryData:o,addMessageWithError:i,userTransform:a,addConfigToPayload:s}},function(t,e,r){"use strict";function n(t,e){return!o.get(e,"plugins.jquery.ignoreAjaxErrors")||!o.get(t,"body.message.extra.isAjax")}var o=r(6);t.exports={checkIgnore:n}},function(t,e,r){"use strict";function n(t,e){var r=t.level,n=c.LEVELS[r]||0,o=e.reportLevel,i=c.LEVELS[o]||0;return!(n=0&&t.options[t.selectedIndex]&&this.captureDomEvent("input",t,t.options[t.selectedIndex].value)},s.prototype.captureDomEvent=function(t,e,r,n){if(void 0!==r)if(this.scrubTelemetryInputs||"password"===l.getElementType(e))r="[scrubbed]";else{var o=l.describeElement(e);this.telemetryScrubber?this.telemetryScrubber(o)&&(r="[scrubbed]"):this.defaultValueScrubber(o)&&(r="[scrubbed]")}var i=l.elementArrayToString(l.treeToArray(e));this.telemeter.captureDom(t,i,r,n)},s.prototype.deinstrumentNavigation=function(){var t=this._window.chrome,e=t&&t.app&&t.app.runtime,r=!e&&this._window.history&&this._window.history.pushState;r&&o(this.replacements,"navigation")},s.prototype.instrumentNavigation=function(){var t=this._window.chrome,e=t&&t.app&&t.app.runtime,r=!e&&this._window.history&&this._window.history.pushState;if(r){var o=this;n(this._window,"onpopstate",function(t){return function(){var e=o._location.href;o.handleUrlChange(o._lastHref,e),t&&t.apply(this,arguments)}},this.replacements,"navigation"),n(this._window.history,"pushState",function(t){return function(){var e=arguments.length>2?arguments[2]:void 0;return e&&o.handleUrlChange(o._lastHref,e+""),t.apply(this,arguments)}},this.replacements,"navigation")}},s.prototype.handleUrlChange=function(t,e){var r=c.parse(this._location.href),n=c.parse(e),o=c.parse(t);this._lastHref=e,r.protocol===n.protocol&&r.host===n.host&&(e=n.path+(n.hash||"")),r.protocol===o.protocol&&r.host===o.host&&(t=o.path+(o.hash||"")),this.telemeter.captureNavigation(t,e)},s.prototype.deinstrumentConnectivity=function(){("addEventListener"in this._window||"body"in this._document)&&(this._window.addEventListener?this.removeListeners("connectivity"):o(this.replacements,"connectivity"))},s.prototype.instrumentConnectivity=function(){if("addEventListener"in this._window||"body"in this._document)if(this._window.addEventListener)this.addListener("connectivity",this._window,"online",void 0,function(){this.telemeter.captureConnectivityChange("online")}.bind(this),!0),this.addListener("connectivity",this._window,"offline",void 0,function(){this.telemeter.captureConnectivityChange("offline")}.bind(this),!0);else{var t=this;n(this._document.body,"ononline",function(e){return function(){t.telemeter.captureConnectivityChange("online"),e&&e.apply(this,arguments)}},this.replacements,"connectivity"),n(this._document.body,"onoffline",function(e){return function(){t.telemeter.captureConnectivityChange("offline"),e&&e.apply(this,arguments)}},this.replacements,"connectivity")}},s.prototype.addListener=function(t,e,r,n,o,i){e.addEventListener?(e.addEventListener(r,o,i),this.eventRemovers[t].push(function(){e.removeEventListener(r,o,i)})):n&&(e.attachEvent(n,o),this.eventRemovers[t].push(function(){e.detachEvent(n,o)}))},s.prototype.removeListeners=function(t){for(var e;this.eventRemovers[t].length;)(e=this.eventRemovers[t].shift())()},t.exports=s},function(t,e){"use strict";function r(t){return(t.getAttribute("type")||"").toLowerCase()}function n(t,e,n){if(t.tagName.toLowerCase()!==e.toLowerCase())return!1;if(!n)return!0;t=r(t);for(var o=0;o ",i=o.length,a=[],u=0,c=t.length-1;c>=0;c--){if(e=s(t[c]),r=u+a.length*i+e.length,c=n+3){a.unshift("...");break}a.unshift(e),u+=e.length}return a.join(o)}function s(t){if(!t||!t.tagName)return"";var e=[t.tagName];t.id&&e.push("#"+t.id),t.classes&&e.push("."+t.classes.join("."));for(var r=0;r=6e4&&(L=i,R=0);var a=window._globalRollbarOptions.maxItems,c=window._globalRollbarOptions.itemsPerMinute,l=function(){return!n.ignoreRateLimit&&a>=1&&T>=a},p=function(){return!n.ignoreRateLimit&&c>=1&&R>=c};return l()?void o(new Error(a+" max items reached")):p()?void o(new Error(c+" items per minute reached")):(T++,R++,l()&&_._log(_.options.uncaughtErrorLevel,"maxItems has been hit. Ignoring errors for the remainder of the current page load.",null,{maxItems:a},null,!1,!0),n.ignoreRateLimit&&delete n.ignoreRateLimit,void y.post(r,t,n,function(r,t){return r?(r instanceof b&&(e.callback=function(){},setTimeout(function(){u(e)},s.RETRY_DELAY)),o(r)):o(null,t)}))}var h,g=t(4),m=t(5),v=t(8),w=t(11),y=w.XHR,b=w.ConnectionError,E=null;s.NOTIFIER_VERSION="1.9.4",s.DEFAULT_ENDPOINT="api.rollbar.com/api/1/",s.DEFAULT_SCRUB_FIELDS=["pw","pass","passwd","password","secret","confirm_password","confirmPassword","password_confirmation","passwordConfirmation","access_token","accessToken","secret_key","secretKey","secretToken"],s.DEFAULT_LOG_LEVEL="debug",s.DEFAULT_REPORT_LEVEL="debug",s.DEFAULT_UNCAUGHT_ERROR_LEVEL="error",s.DEFAULT_ITEMS_PER_MIN=60,s.DEFAULT_MAX_ITEMS=0,s.LEVELS={debug:0,info:1,warning:2,error:3,critical:4},s.RETRY_DELAY=1e4,window._rollbarPayloadQueue=window._rollbarPayloadQueue||[],window._globalRollbarOptions={startTime:(new Date).getTime(),maxItems:s.DEFAULT_MAX_ITEMS,itemsPerMinute:s.DEFAULT_ITEMS_PER_MIN};var _,x=s.prototype;x._getLogArgs=function(e){for(var r,t,n,i,a,u,c=this.options.logLevel||s.DEFAULT_LOG_LEVEL,l=[],p=0;p-1&&(r=r.replace(/eval code/g,"eval").replace(/(\(eval at [^\()]*)|(\)\,.*$)/g,""));var t=r.replace(/^\s+/,"").replace(/\(eval code/g,"(").split(/\s+/).slice(1),n=this.extractLocation(t.pop()),o=t.join(" ")||void 0,i="eval"===n[0]?void 0:n[0];return new e(o,void 0,i,n[1],n[2],r)},this)},parseFFOrSafari:function(n){var o=t(n.stack.split("\n"),function(e){return!e.match(i)},this);return r(o,function(r){if(r.indexOf(" > eval")>-1&&(r=r.replace(/ line (\d+)(?: > eval line \d+)* > eval\:\d+\:\d+/g,":$1")),r.indexOf("@")===-1&&r.indexOf(":")===-1)return new e(r);var t=r.split("@"),n=this.extractLocation(t.pop()),o=t.shift()||void 0;return new e(o,void 0,n[0],n[1],n[2],r)},this)},parseOpera:function(e){return!e.stacktrace||e.message.indexOf("\n")>-1&&e.message.split("\n").length>e.stacktrace.split("\n").length?this.parseOpera9(e):e.stack?this.parseOpera11(e):this.parseOpera10(e)},parseOpera9:function(r){for(var t=/Line (\d+).*script (?:in )?(\S+)/i,n=r.message.split("\n"),o=[],i=2,a=n.length;i/,"$2").replace(/\([^\)]*\)/g,"")||void 0;i.match(/\(([^\)]*)\)/)&&(t=i.replace(/^[^\(]+\(([^\)]*)\)$/,"$1"));var s=void 0===t||"[arguments not available]"===t?void 0:t.split(",");return new e(a,s,o[0],o[1],o[2],r)},this)}}})},function(e,r,t){var n,o,i;!function(t,a){"use strict";o=[],n=a,i="function"==typeof n?n.apply(r,o):n,!(void 0!==i&&(e.exports=i))}(this,function(){"use strict";function e(e){return!isNaN(parseFloat(e))&&isFinite(e)}function r(e,r,t,n,o,i){void 0!==e&&this.setFunctionName(e),void 0!==r&&this.setArgs(r),void 0!==t&&this.setFileName(t),void 0!==n&&this.setLineNumber(n),void 0!==o&&this.setColumnNumber(o),void 0!==i&&this.setSource(i)}return r.prototype={getFunctionName:function(){return this.functionName},setFunctionName:function(e){this.functionName=String(e)},getArgs:function(){return this.args},setArgs:function(e){if("[object Array]"!==Object.prototype.toString.call(e))throw new TypeError("Args must be an Array");this.args=e},getFileName:function(){return this.fileName},setFileName:function(e){this.fileName=String(e)},getLineNumber:function(){return this.lineNumber},setLineNumber:function(r){if(!e(r))throw new TypeError("Line Number must be a Number");this.lineNumber=Number(r)},getColumnNumber:function(){return this.columnNumber},setColumnNumber:function(r){if(!e(r))throw new TypeError("Column Number must be a Number");this.columnNumber=Number(r)},getSource:function(){return this.source},setSource:function(e){this.source=String(e)},toString:function(){var r=this.getFunctionName()||"{anonymous}",t="("+(this.getArgs()||[]).join(",")+")",n=this.getFileName()?"@"+this.getFileName():"",o=e(this.getLineNumber())?":"+this.getLineNumber():"",i=e(this.getColumnNumber())?":"+this.getColumnNumber():"";return r+t+n+o+i}},r})},function(e,r,t){"use strict";function n(e){v=e}function o(e){return{}.toString.call(e).match(/\s([a-zA-Z]+)/)[1].toLowerCase()}function i(e,r){return o(e)===r}function a(e){if(!i(e,"string"))throw new Error("received invalid input");for(var r=w,t=r.parser[r.strictMode?"strict":"loose"].exec(e),n={},o=14;o--;)n[r.key[o]]=t[o]||"";return n[r.q.name]={},n[r.key[12]].replace(r.q.parser,function(e,t,o){t&&(n[r.q.name][t]=o)}),n}function s(e){var r=a(e);return""===r.anchor&&(r.source=r.source.replace("#","")),e=r.source.replace("?"+r.query,"")}function u(e,r){var t,n,o,a=i(e,"object"),s=i(e,"array"),c=[];if(a)for(t in e)e.hasOwnProperty(t)&&c.push(t);else if(s)for(o=0;o500&&(t=t.substr(0,500)+"...")):"undefined"==typeof t&&(t="undefined"),e.push(t)}return e.join(" ")}function d(){m.ieVersion()<=8?console.error(f.apply(null,arguments)):console.error.apply(null,arguments)}function h(){m.ieVersion()<=8?console.info(f.apply(null,arguments)):console.info.apply(null,arguments)}function g(){m.ieVersion()<=8?console.log(f.apply(null,arguments)):console.log.apply(null,arguments)}t(9);var m=t(10),v=null,w={strictMode:!1,key:["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"],q:{name:"queryKey",parser:/(?:^|&)([^&=]*)=?([^&]*)/g},parser:{strict:/^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/,loose:/^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/}},y={setupJSON:n,isType:i,parseUri:a,parseUriOptions:w,redact:c,sanitizeUrl:s,traverse:u,typeName:o,uuid4:l,objectCreate:p,consoleError:d,consoleInfo:h,consoleLog:g};e.exports=y},function(e,r){!function(e){"use strict";e.console||(e.console={});for(var r,t,n=e.console,o=function(){},i=["memory"],a="assert,clear,count,debug,dir,dirxml,error,exception,group,groupCollapsed,groupEnd,info,log,markTimeline,profile,profiles,profileEnd,show,table,time,timeEnd,timeline,timelineEnd,timeStamp,trace,warn".split(",");r=i.pop();)n[r]||(n[r]={});for(;t=a.pop();)n[t]||(n[t]=o)}("undefined"==typeof window?this:window)},function(e,r){"use strict";function t(){for(var e,r=3,t=document.createElement("div"),n=t.getElementsByTagName("i");t.innerHTML="",n[0];);return r>4?r:e}var n={ieVersion:t};e.exports=n},function(e,r,t){"use strict";function n(e){a=e}function o(e){this.name="Connection Error",this.message=e,this.stack=(new Error).stack}var i=t(8),a=null;o.prototype=i.objectCreate(Error.prototype),o.prototype.constructor=o;var s={XMLHttpFactories:[function(){return new XMLHttpRequest},function(){return new ActiveXObject("Msxml2.XMLHTTP")},function(){return new ActiveXObject("Msxml3.XMLHTTP")},function(){return new ActiveXObject("Microsoft.XMLHTTP")}],createXMLHTTPObject:function(){var e,r=!1,t=s.XMLHttpFactories,n=t.length;for(e=0;e=400&&u.status<600?(403==u.status&&i.consoleError("[Rollbar]:"+e.message),n(new Error(String(u.status)))):n(new o("XHR response had no status code (likely connection failure)"))}}catch(e){var r;r=e&&e.stack?e:new Error(e),n(r)}};u.open("POST",e,!0),u.setRequestHeader&&(u.setRequestHeader("Content-Type","application/json"),u.setRequestHeader("X-Rollbar-Access-Token",r)),u.onreadystatechange=c,u.send(t)}catch(r){if("undefined"!=typeof XDomainRequest){"http:"===window.location.href.substring(0,5)&&"https"===e.substring(0,5)&&(e="http"+e.substring(5));var l=function(){n(new o("Request timed out"))},p=function(){n(new Error("Error during request"))},f=function(){n(null,a.parse(u.responseText))};u=new XDomainRequest,u.onprogress=function(){},u.ontimeout=l,u.onerror=p,u.onload=f,u.open("POST",e,!0),u.send(t)}}}catch(e){n(e)}}};e.exports={XHR:s,setupJSON:n,ConnectionError:o}}])}); diff --git a/packages/website/ts/utils/error_reporter.ts b/packages/website/ts/utils/error_reporter.ts index 83710b81f..2d0661b25 100644 --- a/packages/website/ts/utils/error_reporter.ts +++ b/packages/website/ts/utils/error_reporter.ts @@ -36,7 +36,7 @@ const rollbarConfig = { 'SecurityError (DOM Exception 18)', ], }; -import Rollbar = require('../../public/js/rollbar.umd.nojson.min.js'); +import Rollbar = require('../../public/js/rollbar.umd.min.js'); const rollbar = Rollbar.init(rollbarConfig); export const errorReporter = { -- cgit v1.2.3 From 4e1bd7b5f0a63f30c685ab3fa5bef86f9876b9fb Mon Sep 17 00:00:00 2001 From: fragosti Date: Mon, 9 Jul 2018 19:02:50 -0700 Subject: Add Peter to about page --- packages/website/public/images/team/peter.jpg | Bin 0 -> 26748 bytes packages/website/ts/pages/about/about.tsx | 6 ++++++ 2 files changed, 6 insertions(+) create mode 100644 packages/website/public/images/team/peter.jpg (limited to 'packages/website') diff --git a/packages/website/public/images/team/peter.jpg b/packages/website/public/images/team/peter.jpg new file mode 100644 index 000000000..fa976cb8d Binary files /dev/null and b/packages/website/public/images/team/peter.jpg differ diff --git a/packages/website/ts/pages/about/about.tsx b/packages/website/ts/pages/about/about.tsx index 41c269f40..7ed713643 100644 --- a/packages/website/ts/pages/about/about.tsx +++ b/packages/website/ts/pages/about/about.tsx @@ -174,6 +174,12 @@ const teamRow6: ProfileInfo[] = [ linkedIn: 'https://www.linkedin.com/in/stephenalexbrowne/', github: 'http://github.com/albrow', }, + { + name: 'Peter Zeitz', + title: 'Research Fellow', + description: `Researching decentralized governance. Previously Assistant Professor of Economics at National University of Singapore Business School. PhD in Economics at UCLA.`, + image: 'images/team/peter.jpg', + }, // { // name: 'Chris Kalani', // title: 'Director of Design', -- cgit v1.2.3 From cedd1d5596b4a1e6b822409e3f012a81beea19c7 Mon Sep 17 00:00:00 2001 From: fragosti Date: Tue, 10 Jul 2018 10:30:25 -0700 Subject: Add LinkedIn for Peter --- packages/website/ts/pages/about/about.tsx | 1 + 1 file changed, 1 insertion(+) (limited to 'packages/website') diff --git a/packages/website/ts/pages/about/about.tsx b/packages/website/ts/pages/about/about.tsx index 7ed713643..be4a67cb3 100644 --- a/packages/website/ts/pages/about/about.tsx +++ b/packages/website/ts/pages/about/about.tsx @@ -179,6 +179,7 @@ const teamRow6: ProfileInfo[] = [ title: 'Research Fellow', description: `Researching decentralized governance. Previously Assistant Professor of Economics at National University of Singapore Business School. PhD in Economics at UCLA.`, image: 'images/team/peter.jpg', + linkedIn: 'https://www.linkedin.com/in/peter-z-7b9595163/', }, // { // name: 'Chris Kalani', -- cgit v1.2.3 From 51d5b9d35d903413a83254e5a82fbd247b7ab789 Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Tue, 10 Jul 2018 11:46:31 -0700 Subject: Grab token registry information from our DB for mainnet --- packages/website/ts/blockchain.ts | 10 +++++++--- packages/website/ts/utils/backend_client.ts | 6 ++++++ 2 files changed, 13 insertions(+), 3 deletions(-) (limited to 'packages/website') diff --git a/packages/website/ts/blockchain.ts b/packages/website/ts/blockchain.ts index 5476fcf37..0e6698318 100644 --- a/packages/website/ts/blockchain.ts +++ b/packages/website/ts/blockchain.ts @@ -769,9 +769,13 @@ export class Blockchain { this._contractWrappers.exchange.unsubscribeAll(); } private async _getTokenRegistryTokensByAddressAsync(): Promise { - utils.assert(!_.isUndefined(this._contractWrappers), 'ContractWrappers must be instantiated.'); - const tokenRegistryTokens = await this._contractWrappers.tokenRegistry.getTokensAsync(); - + let tokenRegistryTokens; + if (this.networkId === constants.NETWORK_ID_MAINNET) { + tokenRegistryTokens = await backendClient.getTokenInfosAsync(); + } else { + utils.assert(!_.isUndefined(this._contractWrappers), 'ContractWrappers must be instantiated.'); + tokenRegistryTokens = await this._contractWrappers.tokenRegistry.getTokensAsync(); + } const tokenByAddress: TokenByAddress = {}; _.each(tokenRegistryTokens, (t: ZeroExToken) => { // HACK: For now we have a hard-coded list of iconUrls for the dummyTokens diff --git a/packages/website/ts/utils/backend_client.ts b/packages/website/ts/utils/backend_client.ts index 835a6ef4d..5164211df 100644 --- a/packages/website/ts/utils/backend_client.ts +++ b/packages/website/ts/utils/backend_client.ts @@ -6,6 +6,7 @@ import { WebsiteBackendJobInfo, WebsiteBackendPriceInfo, WebsiteBackendRelayerInfo, + WebsiteBackendTokenInfo, } from 'ts/types'; import { fetchUtils } from 'ts/utils/fetch_utils'; import { utils } from 'ts/utils/utils'; @@ -14,6 +15,7 @@ const ETH_GAS_STATION_ENDPOINT = '/eth_gas_station'; const JOBS_ENDPOINT = '/jobs'; const PRICES_ENDPOINT = '/prices'; const RELAYERS_ENDPOINT = '/relayers'; +const TOKENS_ENDPOINT = '/tokens'; const WIKI_ENDPOINT = '/wiki'; const SUBSCRIBE_SUBSTACK_NEWSLETTER_ENDPOINT = '/newsletter_subscriber/substack'; @@ -41,6 +43,10 @@ export const backendClient = { const result = await fetchUtils.requestAsync(utils.getBackendBaseUrl(), RELAYERS_ENDPOINT); return result; }, + async getTokenInfosAsync(): Promise { + const result = await fetchUtils.requestAsync(utils.getBackendBaseUrl(), TOKENS_ENDPOINT); + return result; + }, async getWikiArticlesBySectionAsync(): Promise { const result = await fetchUtils.requestAsync(utils.getBackendBaseUrl(), WIKI_ENDPOINT); return result; -- cgit v1.2.3 From d319b53e23047d4ff62415555475ef6da5f3d774 Mon Sep 17 00:00:00 2001 From: fragosti Date: Tue, 10 Jul 2018 15:13:54 -0700 Subject: Add Heap snippet --- packages/website/public/index.html | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'packages/website') diff --git a/packages/website/public/index.html b/packages/website/public/index.html index 060f2c3c2..2d9b722f8 100644 --- a/packages/website/public/index.html +++ b/packages/website/public/index.html @@ -82,6 +82,12 @@ })(window, document, 'https://static.hotjar.com/c/hotjar-', '.js?sv='); + + + -- cgit v1.2.3 From 9131a72a47690912db9b536186d05120daabd115 Mon Sep 17 00:00:00 2001 From: fragosti Date: Wed, 11 Jul 2018 12:14:23 -0700 Subject: Replace calls to google analytics with calls to heap --- packages/website/package.json | 10 +-- packages/website/ts/components/fill_order.tsx | 14 ++-- .../generate_order/generate_order_form.tsx | 36 ++++++---- .../ts/components/inputs/allowance_toggle.tsx | 10 +-- .../onboarding/portal_onboarding_flow.tsx | 15 ++-- packages/website/ts/components/portal/portal.tsx | 6 +- .../components/relayer_index/relayer_grid_tile.tsx | 6 +- .../relayer_index/relayer_top_tokens.tsx | 6 +- packages/website/ts/components/wallet/wallet.tsx | 4 +- .../ts/components/wallet/wrap_ether_item.tsx | 29 +++++--- packages/website/ts/index.tsx | 4 -- packages/website/ts/types.ts | 6 +- packages/website/ts/utils/analytics.ts | 80 +++++++++++++++++----- packages/website/ts/utils/configs.ts | 1 + packages/website/ts/utils/constants.ts | 1 + packages/website/ts/utils/utils.ts | 1 + 16 files changed, 147 insertions(+), 82 deletions(-) (limited to 'packages/website') diff --git a/packages/website/package.json b/packages/website/package.json index b5b4b6119..3e48a3a26 100644 --- a/packages/website/package.json +++ b/packages/website/package.json @@ -11,12 +11,9 @@ "clean": "shx rm -f public/bundle*", "lint": "tslint --project . 'ts/**/*.ts' 'ts/**/*.tsx'", "watch_without_deps": "webpack-dev-server --content-base public --https", - "deploy_dogfood": - "npm run build; aws s3 sync ./public/. s3://dogfood.0xproject.com --profile 0xproject --region us-east-1 --grants read=uri=http://acs.amazonaws.com/groups/global/AllUsers", - "deploy_staging": - "npm run build; aws s3 sync ./public/. s3://staging-0xproject --profile 0xproject --region us-east-1 --grants read=uri=http://acs.amazonaws.com/groups/global/AllUsers", - "deploy_live": - "npm run build; aws s3 sync ./public/. s3://0xproject.com --profile 0xproject --region us-east-1 --grants read=uri=http://acs.amazonaws.com/groups/global/AllUsers --exclude *.map.js" + "deploy_dogfood": "npm run build; aws s3 sync ./public/. s3://dogfood.0xproject.com --profile 0xproject --region us-east-1 --grants read=uri=http://acs.amazonaws.com/groups/global/AllUsers", + "deploy_staging": "npm run build; aws s3 sync ./public/. s3://staging-0xproject --profile 0xproject --region us-east-1 --grants read=uri=http://acs.amazonaws.com/groups/global/AllUsers", + "deploy_live": "npm run build; aws s3 sync ./public/. s3://0xproject.com --profile 0xproject --region us-east-1 --grants read=uri=http://acs.amazonaws.com/groups/global/AllUsers --exclude *.map.js" }, "author": "Fabio Berger", "license": "Apache-2.0", @@ -49,7 +46,6 @@ "react-copy-to-clipboard": "^4.2.3", "react-document-title": "^2.0.3", "react-dom": "15.6.1", - "react-ga": "^2.4.1", "react-popper": "^1.0.0-beta.6", "react-redux": "^5.0.3", "react-router-dom": "^4.1.1", diff --git a/packages/website/ts/components/fill_order.tsx b/packages/website/ts/components/fill_order.tsx index 03ba1183d..46e33061f 100644 --- a/packages/website/ts/components/fill_order.tsx +++ b/packages/website/ts/components/fill_order.tsx @@ -506,6 +506,10 @@ export class FillOrder extends React.Component { await this._checkForUntrackedTokensAndAskToAddAsync(); } + private _trackOrderEvent(eventName: string): void { + const parsedOrder = this.state.parsedOrder; + analytics.trackOrderEvent(eventName, parsedOrder); + } private async _onFillOrderClickFireAndForgetAsync(): Promise { if (this.props.blockchainErr !== BlockchainErrs.NoError || _.isEmpty(this.props.userAddress)) { this.props.dispatcher.updateShouldBlockchainErrDialogBeOpen(true); @@ -552,14 +556,12 @@ export class FillOrder extends React.Component { }); return; } - const networkName = sharedConstants.NETWORK_NAME_BY_ID[this.props.networkId]; - const eventLabel = `${parsedOrder.metadata.takerToken.symbol}-${networkName}`; try { const orderFilledAmount: BigNumber = await this.props.blockchain.fillOrderAsync( signedOrder, this.props.orderFillAmount, ); - analytics.logEvent('Portal', 'Fill Order Success', eventLabel, parsedOrder.signedOrder.takerTokenAmount); + this._trackOrderEvent('Fill Order Success'); // After fill completes, let's force fetch the token balances this.props.dispatcher.forceTokenStateRefetch(); this.setState({ @@ -573,7 +575,7 @@ export class FillOrder extends React.Component { this.setState({ isFilling: false, }); - analytics.logEvent('Portal', 'Fill Order Failure', eventLabel, parsedOrder.signedOrder.takerTokenAmount); + this._trackOrderEvent('Fill Order Failure'); const errMsg = `${err}`; if (utils.didUserDenyWeb3Request(errMsg)) { return; @@ -638,7 +640,7 @@ export class FillOrder extends React.Component { globalErrMsg: '', unavailableTakerAmount: takerTokenAmount, }); - analytics.logEvent('Portal', 'Cancel Order Success', eventLabel, parsedOrder.signedOrder.makerTokenAmount); + this._trackOrderEvent('Cancel Order Success'); return; } catch (err) { this.setState({ @@ -648,7 +650,7 @@ export class FillOrder extends React.Component { if (utils.didUserDenyWeb3Request(errMsg)) { return; } - analytics.logEvent('Portal', 'Cancel Order Failure', eventLabel, parsedOrder.signedOrder.makerTokenAmount); + this._trackOrderEvent('Cancel Order Failure'); globalErrMsg = 'Failed to cancel order, please refresh and try again'; logUtils.log(`${err}`); this.setState({ diff --git a/packages/website/ts/components/generate_order/generate_order_form.tsx b/packages/website/ts/components/generate_order/generate_order_form.tsx index d26b5c3fa..53fb3fc91 100644 --- a/packages/website/ts/components/generate_order/generate_order_form.tsx +++ b/packages/website/ts/components/generate_order/generate_order_form.tsx @@ -1,6 +1,6 @@ import { generatePseudoRandomSalt, getOrderHashHex } from '@0xproject/order-utils'; import { colors, constants as sharedConstants } from '@0xproject/react-shared'; -import { ECSignature, Order } from '@0xproject/types'; +import { ECSignature, Order as ZeroExOrder } from '@0xproject/types'; import { BigNumber, logUtils } from '@0xproject/utils'; import * as _ from 'lodash'; import Dialog from 'material-ui/Dialog'; @@ -20,7 +20,7 @@ import { SwapIcon } from 'ts/components/ui/swap_icon'; import { Dispatcher } from 'ts/redux/dispatcher'; import { portalOrderSchema } from 'ts/schemas/portal_order_schema'; import { validator } from 'ts/schemas/validator'; -import { AlertTypes, BlockchainErrs, HashData, Side, SideToAssetToken, Token, TokenByAddress } from 'ts/types'; +import { AlertTypes, BlockchainErrs, HashData, Side, SideToAssetToken, Token, TokenByAddress, Order } from 'ts/types'; import { analytics } from 'ts/utils/analytics'; import { constants } from 'ts/utils/constants'; import { errorReporter } from 'ts/utils/error_reporter'; @@ -254,7 +254,8 @@ export class GenerateOrderForm extends React.Component { + private async _signTransactionAsync(): Promise { this.setState({ signingState: SigningState.SIGNING, }); @@ -299,11 +304,11 @@ export class GenerateOrderForm extends React.Component { } private _startOnboarding(): void { - const networkName = sharedConstants.NETWORK_NAME_BY_ID[this.props.networkId]; - analytics.logEvent('Portal', 'Onboarding Started - Manual', networkName, this.props.portalOnboardingStep); + analytics.track('Onboarding Started', { + reason: 'manual', + stepIndex: this.props.portalOnboardingStep, + }); this.props.dispatcher.updatePortalOnboardingShowing(true); } private _renderWalletSection(): React.ReactNode { diff --git a/packages/website/ts/components/relayer_index/relayer_grid_tile.tsx b/packages/website/ts/components/relayer_index/relayer_grid_tile.tsx index 431cf145b..2eb04f2d6 100644 --- a/packages/website/ts/components/relayer_index/relayer_grid_tile.tsx +++ b/packages/website/ts/components/relayer_index/relayer_grid_tile.tsx @@ -64,10 +64,10 @@ export const RelayerGridTile: React.StatelessComponent = ( const link = props.relayerInfo.appUrl || props.relayerInfo.url; const topTokens = props.relayerInfo.topTokens; const weeklyTxnVolume = props.relayerInfo.weeklyTxnVolume; - const networkName = sharedConstants.NETWORK_NAME_BY_ID[props.networkId]; - const eventLabel = `${props.relayerInfo.name}-${networkName}`; const onClick = () => { - analytics.logEvent('Portal', 'Relayer Click', eventLabel); + analytics.track('Relayer Click', { + name: props.relayerInfo.name, + }); utils.openUrl(link); }; const headerImageUrl = props.relayerInfo.logoImgUrl; diff --git a/packages/website/ts/components/relayer_index/relayer_top_tokens.tsx b/packages/website/ts/components/relayer_index/relayer_top_tokens.tsx index c48b672e9..883c8d81b 100644 --- a/packages/website/ts/components/relayer_index/relayer_top_tokens.tsx +++ b/packages/website/ts/components/relayer_index/relayer_top_tokens.tsx @@ -46,11 +46,11 @@ class TokenLink extends React.Component { }; } public render(): React.ReactNode { - const networkName = sharedConstants.NETWORK_NAME_BY_ID[this.props.networkId]; - const eventLabel = `${this.props.tokenInfo.symbol}-${networkName}`; const onClick = (event: React.MouseEvent) => { event.stopPropagation(); - analytics.logEvent('Portal', 'Token Click', eventLabel); + analytics.track('Token Click', { + tokenSymbol: this.props.tokenInfo.symbol, + }); const tokenLink = this._tokenLinkFromToken(this.props.tokenInfo, this.props.networkId); utils.openUrl(tokenLink); }; diff --git a/packages/website/ts/components/wallet/wallet.tsx b/packages/website/ts/components/wallet/wallet.tsx index 6c1c495d7..940cd6c58 100644 --- a/packages/website/ts/components/wallet/wallet.tsx +++ b/packages/website/ts/components/wallet/wallet.tsx @@ -491,7 +491,7 @@ export class Wallet extends React.Component { const networkName = sharedConstants.NETWORK_NAME_BY_ID[this.props.networkId]; const action = wrappedEtherDirection === Side.Deposit ? 'Wallet - Wrap ETH Opened' : 'Wallet - Unwrap WETH Opened'; - analytics.logEvent('Portal', action, networkName); + analytics.track(action); this.setState({ wrappedEtherDirection, }); @@ -500,7 +500,7 @@ export class Wallet extends React.Component { const networkName = sharedConstants.NETWORK_NAME_BY_ID[this.props.networkId]; const action = wrappedEtherDirection === Side.Deposit ? 'Wallet - Wrap ETH Closed' : 'Wallet - Unwrap WETH Closed'; - analytics.logEvent('Portal', action, networkName); + analytics.track(action); this.setState({ wrappedEtherDirection: undefined, }); diff --git a/packages/website/ts/components/wallet/wrap_ether_item.tsx b/packages/website/ts/components/wallet/wrap_ether_item.tsx index 2b4cf93fe..01d9bdb66 100644 --- a/packages/website/ts/components/wallet/wrap_ether_item.tsx +++ b/packages/website/ts/components/wallet/wrap_ether_item.tsx @@ -188,20 +188,23 @@ export class WrapEtherItem extends React.Component(/* webpackChunkName: "ethereumTypesDocs" */ 'ts/containers/ethereum_types_documentation'), ); -analytics.init(); -// tslint:disable-next-line:no-floating-promises -analytics.logProviderAsync((window as any).web3); - render(
diff --git a/packages/website/ts/types.ts b/packages/website/ts/types.ts index e8dc694f6..f107b3b5e 100644 --- a/packages/website/ts/types.ts +++ b/packages/website/ts/types.ts @@ -516,8 +516,10 @@ export interface OutdatedWrappedEtherByNetworkId { }; } -export interface ItemByAddress { - [address: string]: T; +export type ItemByAddress = ObjectMap; + +export interface ObjectMap { + [key: string]: T; } export type TokenStateByAddress = ItemByAddress; diff --git a/packages/website/ts/utils/analytics.ts b/packages/website/ts/utils/analytics.ts index f4bfa083f..9a1684813 100644 --- a/packages/website/ts/utils/analytics.ts +++ b/packages/website/ts/utils/analytics.ts @@ -1,27 +1,71 @@ import * as _ from 'lodash'; -import * as ReactGA from 'react-ga'; -import { InjectedWeb3 } from 'ts/types'; +import { InjectedWeb3, ObjectMap, Order } from 'ts/types'; import { configs } from 'ts/utils/configs'; import { utils } from 'ts/utils/utils'; -export const analytics = { - init(): void { - ReactGA.initialize(configs.GOOGLE_ANALYTICS_ID); - }, - logEvent(category: string, action: string, label: string, value?: any): void { - ReactGA.event({ - category, - action, - label, - value, - }); - }, - async logProviderAsync(web3IfExists: InjectedWeb3): Promise { +export interface HeapAnalytics { + indentify(id: string, idType: string): void; + track(eventName: string, eventProperties?: ObjectMap): void; + resetIdentity(): void; + addUserProperties(properties: ObjectMap): void; + addEventProperties(properties: ObjectMap): void; + removeEventProperty(property: string): void; + clearEventProperties(): void; +} + +export class Analytics implements HeapAnalytics { + private _heap: HeapAnalytics; + public static init(): Analytics { + const heap = (window as any).heap; + if (!_.isUndefined(heap)) { + return new Analytics(heap); + } else { + throw new Error('Could not find the Heap SDK on the page.'); + } + } + constructor(heap: HeapAnalytics) { + this._heap = heap; + } + // HeapAnalytics Wrappers + public indentify(id: string, idType: string): void { + this._heap.indentify(id, idType); + } + public track(eventName: string, eventProperties?: ObjectMap): void { + this._heap.track(eventName, eventProperties); + } + public resetIdentity(): void { + this._heap.resetIdentity(); + } + public addUserProperties(properties: ObjectMap): void { + this._heap.addUserProperties(properties); + } + public addEventProperties(properties: ObjectMap): void { + this._heap.addEventProperties(properties); + } + public removeEventProperty(property: string): void { + this._heap.removeEventProperty(property); + } + public clearEventProperties(): void { + this._heap.clearEventProperties(); + } + // Custom methods + public trackOrderEvent(eventName: string, order: Order): void { + const orderLoggingData = { + takerTokenAmount: order.signedOrder.takerTokenAmount, + makeTokenAmount: order.signedOrder.makerTokenAmount, + takerToken: order.metadata.takerToken.symbol, + makerToken: order.metadata.makerToken.symbol, + }; + this.track(eventName, orderLoggingData); + } + public async logProviderAsync(web3IfExists: InjectedWeb3): Promise { await utils.onPageLoadAsync(); const providerType = !_.isUndefined(web3IfExists) && !_.isUndefined(web3IfExists.currentProvider) ? utils.getProviderType(web3IfExists.currentProvider) : 'NONE'; - ReactGA.ga('set', 'dimension1', providerType); - }, -}; + } +} + +// Assume heap library has loaded. +export const analytics = Analytics.init(); diff --git a/packages/website/ts/utils/configs.ts b/packages/website/ts/utils/configs.ts index 97aabd13d..a2fd6a47e 100644 --- a/packages/website/ts/utils/configs.ts +++ b/packages/website/ts/utils/configs.ts @@ -23,6 +23,7 @@ export const configs = { DOMAIN_PRODUCTION: '0xproject.com', ENVIRONMENT: isDevelopment ? Environments.DEVELOPMENT : Environments.PRODUCTION, GOOGLE_ANALYTICS_ID: 'UA-98720122-1', + HEAP_APP_ID: '410099666', LAST_LOCAL_STORAGE_FILL_CLEARANCE_DATE: '2017-11-22', LAST_LOCAL_STORAGE_TRACKED_TOKEN_CLEARANCE_DATE: '2018-7-5', OUTDATED_WRAPPED_ETHERS: [ diff --git a/packages/website/ts/utils/constants.ts b/packages/website/ts/utils/constants.ts index e43f541bf..d52b9b392 100644 --- a/packages/website/ts/utils/constants.ts +++ b/packages/website/ts/utils/constants.ts @@ -34,6 +34,7 @@ export const constants = { PROVIDER_NAME_GENERIC: 'Injected Web3', PROVIDER_NAME_PUBLIC: '0x Public', ROLLBAR_ACCESS_TOKEN: '32c39bfa4bb6440faedc1612a9c13d28', + HEAP_APP_ID: '410099666', S3_DOC_BUCKET_ROOT: 'https://s3.amazonaws.com/doc-jsons', S3_STAGING_DOC_BUCKET_ROOT: 'https://s3.amazonaws.com/staging-doc-jsons', SUCCESS_STATUS: 200, diff --git a/packages/website/ts/utils/utils.ts b/packages/website/ts/utils/utils.ts index 8c76a7592..df7f8d10f 100644 --- a/packages/website/ts/utils/utils.ts +++ b/packages/website/ts/utils/utils.ts @@ -313,6 +313,7 @@ export const utils = { const baseUrl = `https://${window.location.hostname}${hasPort ? `:${port}` : ''}`; return baseUrl; }, + // TODO: Fix this, it's a lie. async onPageLoadAsync(): Promise { if (document.readyState === 'complete') { return; // Already loaded -- cgit v1.2.3 From 098322c56475581df5bd80e12cb6c511963e4daf Mon Sep 17 00:00:00 2001 From: fragosti Date: Wed, 11 Jul 2018 15:39:12 -0700 Subject: Integrate heap analytics --- packages/website/public/index.html | 12 ++--- packages/website/ts/blockchain.ts | 2 +- packages/website/ts/components/fill_order.tsx | 6 +-- .../website/ts/components/forms/subscribe_form.tsx | 4 ++ .../generate_order/generate_order_form.tsx | 8 ++-- .../ts/components/inputs/allowance_toggle.tsx | 6 +-- .../onboarding/portal_onboarding_flow.tsx | 9 +--- packages/website/ts/components/portal/portal.tsx | 5 +- .../components/relayer_index/relayer_grid_tile.tsx | 4 +- .../relayer_index/relayer_top_tokens.tsx | 3 +- packages/website/ts/components/wallet/wallet.tsx | 8 ++-- .../ts/components/wallet/wrap_ether_item.tsx | 10 ++-- packages/website/ts/index.tsx | 1 - packages/website/ts/pages/wiki/wiki.tsx | 2 +- packages/website/ts/redux/analyticsMiddleware.ts | 41 ++++++++++++++++ packages/website/ts/redux/store.ts | 7 +-- packages/website/ts/utils/analytics.ts | 56 ++++++++++++++-------- packages/website/ts/utils/utils.ts | 12 ++--- 18 files changed, 122 insertions(+), 74 deletions(-) create mode 100644 packages/website/ts/redux/analyticsMiddleware.ts (limited to 'packages/website') diff --git a/packages/website/public/index.html b/packages/website/public/index.html index 2d9b722f8..a8a61f8ad 100644 --- a/packages/website/public/index.html +++ b/packages/website/public/index.html @@ -23,6 +23,12 @@ + + + - - - diff --git a/packages/website/ts/blockchain.ts b/packages/website/ts/blockchain.ts index 0e6698318..954595cef 100644 --- a/packages/website/ts/blockchain.ts +++ b/packages/website/ts/blockchain.ts @@ -795,7 +795,7 @@ export class Blockchain { return tokenByAddress; } private async _onPageLoadInitFireAndForgetAsync(): Promise { - await utils.onPageLoadAsync(); // wait for page to load + await utils.onPageLoadPromise; // wait for page to load const networkIdIfExists = await Blockchain._getInjectedWeb3ProviderNetworkIdIfExistsAsync(); this.networkId = !_.isUndefined(networkIdIfExists) ? networkIdIfExists : constants.NETWORK_ID_MAINNET; const injectedWeb3IfExists = Blockchain._getInjectedWeb3(); diff --git a/packages/website/ts/components/fill_order.tsx b/packages/website/ts/components/fill_order.tsx index 46e33061f..25d21c3dd 100644 --- a/packages/website/ts/components/fill_order.tsx +++ b/packages/website/ts/components/fill_order.tsx @@ -1,5 +1,5 @@ import { getOrderHashHex, isValidSignature } from '@0xproject/order-utils'; -import { colors, constants as sharedConstants } from '@0xproject/react-shared'; +import { colors } from '@0xproject/react-shared'; import { Order as ZeroExOrder } from '@0xproject/types'; import { BigNumber, logUtils } from '@0xproject/utils'; import { Web3Wrapper } from '@0xproject/web3-wrapper'; @@ -508,7 +508,7 @@ export class FillOrder extends React.Component { } private _trackOrderEvent(eventName: string): void { const parsedOrder = this.state.parsedOrder; - analytics.trackOrderEvent(eventName, parsedOrder); + analytics.trackOrderEventAsync(eventName, parsedOrder); } private async _onFillOrderClickFireAndForgetAsync(): Promise { if (this.props.blockchainErr !== BlockchainErrs.NoError || _.isEmpty(this.props.userAddress)) { @@ -630,8 +630,6 @@ export class FillOrder extends React.Component { }); return; } - const networkName = sharedConstants.NETWORK_NAME_BY_ID[this.props.networkId]; - const eventLabel = `${parsedOrder.metadata.makerToken.symbol}-${networkName}`; try { await this.props.blockchain.cancelOrderAsync(signedOrder, availableTakerTokenAmount); this.setState({ diff --git a/packages/website/ts/components/forms/subscribe_form.tsx b/packages/website/ts/components/forms/subscribe_form.tsx index 8ef58328e..19abbdf5f 100644 --- a/packages/website/ts/components/forms/subscribe_form.tsx +++ b/packages/website/ts/components/forms/subscribe_form.tsx @@ -6,6 +6,7 @@ import { Button } from 'ts/components/ui/button'; import { Container } from 'ts/components/ui/container'; import { Input } from 'ts/components/ui/input'; import { Text } from 'ts/components/ui/text'; +import { analytics } from 'ts/utils/analytics'; import { backendClient } from 'ts/utils/backend_client'; export interface SubscribeFormProps {} @@ -112,6 +113,9 @@ export class SubscribeForm extends React.Component { startOnboarding ); } - private _startOnboarding(): void { - analytics.track('Onboarding Started', { + analytics.trackAsync('Onboarding Started', { reason: 'manual', stepIndex: this.props.portalOnboardingStep, }); diff --git a/packages/website/ts/components/relayer_index/relayer_grid_tile.tsx b/packages/website/ts/components/relayer_index/relayer_grid_tile.tsx index 2eb04f2d6..937f0b79d 100644 --- a/packages/website/ts/components/relayer_index/relayer_grid_tile.tsx +++ b/packages/website/ts/components/relayer_index/relayer_grid_tile.tsx @@ -1,4 +1,4 @@ -import { constants as sharedConstants, Styles } from '@0xproject/react-shared'; +import { Styles } from '@0xproject/react-shared'; import * as _ from 'lodash'; import { GridTile as PlainGridTile } from 'material-ui/GridList'; import * as React from 'react'; @@ -65,7 +65,7 @@ export const RelayerGridTile: React.StatelessComponent = ( const topTokens = props.relayerInfo.topTokens; const weeklyTxnVolume = props.relayerInfo.weeklyTxnVolume; const onClick = () => { - analytics.track('Relayer Click', { + analytics.trackAsync('Relayer Click', { name: props.relayerInfo.name, }); utils.openUrl(link); diff --git a/packages/website/ts/components/relayer_index/relayer_top_tokens.tsx b/packages/website/ts/components/relayer_index/relayer_top_tokens.tsx index 883c8d81b..e6e0095c2 100644 --- a/packages/website/ts/components/relayer_index/relayer_top_tokens.tsx +++ b/packages/website/ts/components/relayer_index/relayer_top_tokens.tsx @@ -1,6 +1,5 @@ import { colors, - constants as sharedConstants, EtherscanLinkSuffixes, utils as sharedUtils, } from '@0xproject/react-shared'; @@ -48,7 +47,7 @@ class TokenLink extends React.Component { public render(): React.ReactNode { const onClick = (event: React.MouseEvent) => { event.stopPropagation(); - analytics.track('Token Click', { + analytics.trackAsync('Token Click', { tokenSymbol: this.props.tokenInfo.symbol, }); const tokenLink = this._tokenLinkFromToken(this.props.tokenInfo, this.props.networkId); diff --git a/packages/website/ts/components/wallet/wallet.tsx b/packages/website/ts/components/wallet/wallet.tsx index 940cd6c58..2fdcded38 100644 --- a/packages/website/ts/components/wallet/wallet.tsx +++ b/packages/website/ts/components/wallet/wallet.tsx @@ -1,4 +1,4 @@ -import { constants as sharedConstants, EtherscanLinkSuffixes, utils as sharedUtils } from '@0xproject/react-shared'; +import { EtherscanLinkSuffixes, utils as sharedUtils } from '@0xproject/react-shared'; import { BigNumber, errorUtils } from '@0xproject/utils'; import * as _ from 'lodash'; @@ -488,19 +488,17 @@ export class Wallet extends React.Component { ); } private _openWrappedEtherActionRow(wrappedEtherDirection: Side): void { - const networkName = sharedConstants.NETWORK_NAME_BY_ID[this.props.networkId]; const action = wrappedEtherDirection === Side.Deposit ? 'Wallet - Wrap ETH Opened' : 'Wallet - Unwrap WETH Opened'; - analytics.track(action); + analytics.trackAsync(action); this.setState({ wrappedEtherDirection, }); } private _closeWrappedEtherActionRow(wrappedEtherDirection: Side): void { - const networkName = sharedConstants.NETWORK_NAME_BY_ID[this.props.networkId]; const action = wrappedEtherDirection === Side.Deposit ? 'Wallet - Wrap ETH Closed' : 'Wallet - Unwrap WETH Closed'; - analytics.track(action); + analytics.trackAsync(action); this.setState({ wrappedEtherDirection: undefined, }); diff --git a/packages/website/ts/components/wallet/wrap_ether_item.tsx b/packages/website/ts/components/wallet/wrap_ether_item.tsx index 01d9bdb66..9fec8afa1 100644 --- a/packages/website/ts/components/wallet/wrap_ether_item.tsx +++ b/packages/website/ts/components/wallet/wrap_ether_item.tsx @@ -1,4 +1,4 @@ -import { constants as sharedConstants, Styles } from '@0xproject/react-shared'; +import { Styles } from '@0xproject/react-shared'; import { BigNumber, logUtils } from '@0xproject/utils'; import { Web3Wrapper } from '@0xproject/web3-wrapper'; import * as _ from 'lodash'; @@ -196,13 +196,13 @@ export class WrapEtherItem extends React.Component { articlesBySection, }, async () => { - await utils.onPageLoadAsync(); + await utils.onPageLoadPromise; const hash = this.props.location.hash.slice(1); sharedUtils.scrollToHash(hash, sharedConstants.SCROLL_CONTAINER_ID); }, diff --git a/packages/website/ts/redux/analyticsMiddleware.ts b/packages/website/ts/redux/analyticsMiddleware.ts new file mode 100644 index 000000000..2778445e7 --- /dev/null +++ b/packages/website/ts/redux/analyticsMiddleware.ts @@ -0,0 +1,41 @@ +import { Middleware } from 'redux'; +import { State } from 'ts/redux/reducer'; +import { ActionTypes } from 'ts/types'; +import { analytics } from 'ts/utils/analytics'; + +export const analyticsMiddleware: Middleware = store => next => action => { + const nextAction = next(action); + const nextState = (store.getState() as any) as State; + switch (action.type) { + case ActionTypes.UpdateInjectedProviderName: + analytics.addEventPropertiesAsync({ + injectedProviderName: nextState.injectedProviderName, + }); + break; + case ActionTypes.UpdateNetworkId: + analytics.addEventPropertiesAsync({ + networkId: nextState.networkId, + }); + break; + case ActionTypes.UpdateUserAddress: + analytics.addUserPropertiesAsync({ + ethAddress: nextState.userAddress, + }); + break; + case ActionTypes.UpdateUserEtherBalance: + if (nextState.userEtherBalanceInWei) { + analytics.addUserPropertiesAsync({ + ethBalance: nextState.userEtherBalanceInWei.toString(), + }); + } + break; + case ActionTypes.UpdatePortalOnboardingStep: + analytics.trackAsync('Update Onboarding Step', { + stepIndex: nextState.portalOnboardingStep, + }); + break; + default: + break; + } + return nextAction; +}; diff --git a/packages/website/ts/redux/store.ts b/packages/website/ts/redux/store.ts index 2672e3f61..006241371 100644 --- a/packages/website/ts/redux/store.ts +++ b/packages/website/ts/redux/store.ts @@ -1,7 +1,8 @@ import * as _ from 'lodash'; -import { createStore, Store as ReduxStore } from 'redux'; -import { devToolsEnhancer } from 'redux-devtools-extension/developmentOnly'; +import { applyMiddleware, createStore, Store as ReduxStore } from 'redux'; +import { composeWithDevTools } from 'redux-devtools-extension/developmentOnly'; import { stateStorage } from 'ts/local_storage/state_storage'; +import { analyticsMiddleware } from 'ts/redux/analyticsMiddleware'; import { reducer, State } from 'ts/redux/reducer'; const ONE_SECOND = 1000; @@ -9,7 +10,7 @@ const ONE_SECOND = 1000; export const store: ReduxStore = createStore( reducer, stateStorage.getPersistedDefaultState(), - devToolsEnhancer({ name: '0x Website Redux Store' }), + composeWithDevTools(applyMiddleware(analyticsMiddleware)), ); store.subscribe( _.throttle(() => { diff --git a/packages/website/ts/utils/analytics.ts b/packages/website/ts/utils/analytics.ts index 9a1684813..961f9af5a 100644 --- a/packages/website/ts/utils/analytics.ts +++ b/packages/website/ts/utils/analytics.ts @@ -1,9 +1,9 @@ import * as _ from 'lodash'; -import { InjectedWeb3, ObjectMap, Order } from 'ts/types'; -import { configs } from 'ts/utils/configs'; +import { ObjectMap, Order } from 'ts/types'; import { utils } from 'ts/utils/utils'; export interface HeapAnalytics { + loaded: boolean; indentify(id: string, idType: string): void; track(eventName: string, eventProperties?: ObjectMap): void; resetIdentity(): void; @@ -13,12 +13,15 @@ export interface HeapAnalytics { clearEventProperties(): void; } -export class Analytics implements HeapAnalytics { +export class Analytics { private _heap: HeapAnalytics; public static init(): Analytics { + return new Analytics(Analytics.getHeap()); + } + public static getHeap(): HeapAnalytics { const heap = (window as any).heap; if (!_.isUndefined(heap)) { - return new Analytics(heap); + return heap; } else { throw new Error('Could not find the Heap SDK on the page.'); } @@ -27,45 +30,58 @@ export class Analytics implements HeapAnalytics { this._heap = heap; } // HeapAnalytics Wrappers - public indentify(id: string, idType: string): void { + public async indentifyAsync(id: string, idType: string): Promise { + await this._heapLoadedGuardAsync(); this._heap.indentify(id, idType); } - public track(eventName: string, eventProperties?: ObjectMap): void { + public async trackAsync(eventName: string, eventProperties?: ObjectMap): Promise { + await this._heapLoadedGuardAsync(); this._heap.track(eventName, eventProperties); } - public resetIdentity(): void { + public async resetIdentityAsync(): Promise { + await this._heapLoadedGuardAsync(); this._heap.resetIdentity(); } - public addUserProperties(properties: ObjectMap): void { + public async addUserPropertiesAsync(properties: ObjectMap): Promise { + await this._heapLoadedGuardAsync(); this._heap.addUserProperties(properties); } - public addEventProperties(properties: ObjectMap): void { + public async addEventPropertiesAsync(properties: ObjectMap): Promise { + await this._heapLoadedGuardAsync(); this._heap.addEventProperties(properties); } - public removeEventProperty(property: string): void { + public async removeEventPropertyAsync(property: string): Promise { + await this._heapLoadedGuardAsync(); this._heap.removeEventProperty(property); } - public clearEventProperties(): void { + public async clearEventPropertiesAsync(): Promise { + await this._heapLoadedGuardAsync(); this._heap.clearEventProperties(); } // Custom methods - public trackOrderEvent(eventName: string, order: Order): void { + public async trackOrderEventAsync(eventName: string, order: Order): Promise { const orderLoggingData = { takerTokenAmount: order.signedOrder.takerTokenAmount, makeTokenAmount: order.signedOrder.makerTokenAmount, takerToken: order.metadata.takerToken.symbol, makerToken: order.metadata.makerToken.symbol, }; - this.track(eventName, orderLoggingData); + this.trackAsync(eventName, orderLoggingData); } - public async logProviderAsync(web3IfExists: InjectedWeb3): Promise { - await utils.onPageLoadAsync(); - const providerType = - !_.isUndefined(web3IfExists) && !_.isUndefined(web3IfExists.currentProvider) - ? utils.getProviderType(web3IfExists.currentProvider) - : 'NONE'; + /** + * Heap is not available as a UMD module, and additionally has the strange property of replacing itself with + * a different object once it's loaded. + * Instead of having an await call before every analytics use, we opt to have the awaiting logic in here by + * guarding every API call with the guard below. + */ + private async _heapLoadedGuardAsync(): Promise { + if (this._heap.loaded) { + return undefined; + } + await utils.onPageLoadPromise; + // HACK: Reset heap to loaded heap + this._heap = (window as any).heap; } } -// Assume heap library has loaded. export const analytics = Analytics.init(); diff --git a/packages/website/ts/utils/utils.ts b/packages/website/ts/utils/utils.ts index df7f8d10f..bd6a57eea 100644 --- a/packages/website/ts/utils/utils.ts +++ b/packages/website/ts/utils/utils.ts @@ -313,15 +313,13 @@ export const utils = { const baseUrl = `https://${window.location.hostname}${hasPort ? `:${port}` : ''}`; return baseUrl; }, - // TODO: Fix this, it's a lie. - async onPageLoadAsync(): Promise { + onPageLoadPromise: new Promise((resolve, _reject) => { if (document.readyState === 'complete') { - return; // Already loaded + resolve(); + return; } - return new Promise((resolve, _reject) => { - window.onload = () => resolve(); - }); - }, + window.onload = () => resolve(); + }), getProviderType(provider: Provider): Providers | string { const constructorName = provider.constructor.name; let parsedProviderName = constructorName; -- cgit v1.2.3 From 09f5609618709da0ba10520c6ab6a3e2acac438b Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Wed, 11 Jul 2018 15:23:53 -0700 Subject: Remove legacy portal code --- .../ts/components/legacy_portal/legacy_portal.tsx | 339 --------------------- .../legacy_portal/legacy_portal_menu.tsx | 73 ----- packages/website/ts/components/top_bar/top_bar.tsx | 23 +- packages/website/ts/containers/legacy_portal.ts | 92 ------ packages/website/ts/index.tsx | 11 +- packages/website/ts/utils/utils.ts | 5 - 6 files changed, 5 insertions(+), 538 deletions(-) delete mode 100644 packages/website/ts/components/legacy_portal/legacy_portal.tsx delete mode 100644 packages/website/ts/components/legacy_portal/legacy_portal_menu.tsx delete mode 100644 packages/website/ts/containers/legacy_portal.ts (limited to 'packages/website') diff --git a/packages/website/ts/components/legacy_portal/legacy_portal.tsx b/packages/website/ts/components/legacy_portal/legacy_portal.tsx deleted file mode 100644 index c85d97207..000000000 --- a/packages/website/ts/components/legacy_portal/legacy_portal.tsx +++ /dev/null @@ -1,339 +0,0 @@ -import { colors } from '@0xproject/react-shared'; -import { BigNumber } from '@0xproject/utils'; -import * as _ from 'lodash'; -import CircularProgress from 'material-ui/CircularProgress'; -import Paper from 'material-ui/Paper'; -import * as React from 'react'; -import * as DocumentTitle from 'react-document-title'; -import { Route, Switch } from 'react-router-dom'; -import { Blockchain } from 'ts/blockchain'; -import { BlockchainErrDialog } from 'ts/components/dialogs/blockchain_err_dialog'; -import { LedgerConfigDialog } from 'ts/components/dialogs/ledger_config_dialog'; -import { PortalDisclaimerDialog } from 'ts/components/dialogs/portal_disclaimer_dialog'; -import { WrappedEthSectionNoticeDialog } from 'ts/components/dialogs/wrapped_eth_section_notice_dialog'; -import { EthWrappers } from 'ts/components/eth_wrappers'; -import { FillOrder } from 'ts/components/fill_order'; -import { Footer } from 'ts/components/footer'; -import { LegacyPortalMenu } from 'ts/components/legacy_portal/legacy_portal_menu'; -import { TokenBalances } from 'ts/components/token_balances'; -import { TopBar } from 'ts/components/top_bar/top_bar'; -import { TradeHistory } from 'ts/components/trade_history/trade_history'; -import { FlashMessage } from 'ts/components/ui/flash_message'; -import { GenerateOrderForm } from 'ts/containers/generate_order_form'; -import { localStorage } from 'ts/local_storage/local_storage'; -import { Dispatcher } from 'ts/redux/dispatcher'; -import { BlockchainErrs, HashData, Order, ProviderType, ScreenWidths, TokenByAddress, WebsitePaths } from 'ts/types'; -import { constants } from 'ts/utils/constants'; -import { orderParser } from 'ts/utils/order_parser'; -import { Translate } from 'ts/utils/translate'; -import { utils } from 'ts/utils/utils'; - -const THROTTLE_TIMEOUT = 100; - -export interface LegacyPortalProps { - blockchainErr: BlockchainErrs; - blockchainIsLoaded: boolean; - dispatcher: Dispatcher; - hashData: HashData; - injectedProviderName: string; - networkId: number; - nodeVersion: string; - orderFillAmount: BigNumber; - providerType: ProviderType; - screenWidth: ScreenWidths; - tokenByAddress: TokenByAddress; - userEtherBalanceInWei?: BigNumber; - userAddress: string; - shouldBlockchainErrDialogBeOpen: boolean; - userSuppliedOrderCache: Order; - location: Location; - flashMessage?: string | React.ReactNode; - lastForceTokenStateRefetch: number; - translate: Translate; -} - -interface LegacyPortalState { - prevNetworkId: number; - prevNodeVersion: string; - prevUserAddress: string; - prevPathname: string; - isDisclaimerDialogOpen: boolean; - isWethNoticeDialogOpen: boolean; - isLedgerDialogOpen: boolean; -} - -export class LegacyPortal extends React.Component { - private _blockchain: Blockchain; - private _sharedOrderIfExists: Order; - private _throttledScreenWidthUpdate: () => void; - public static hasAlreadyDismissedWethNotice(): boolean { - const didDismissWethNotice = localStorage.getItemIfExists(constants.LOCAL_STORAGE_KEY_DISMISS_WETH_NOTICE); - const hasAlreadyDismissedWethNotice = !_.isUndefined(didDismissWethNotice) && !_.isEmpty(didDismissWethNotice); - return hasAlreadyDismissedWethNotice; - } - constructor(props: LegacyPortalProps) { - super(props); - this._sharedOrderIfExists = orderParser.parse(window.location.search); - this._throttledScreenWidthUpdate = _.throttle(this._updateScreenWidth.bind(this), THROTTLE_TIMEOUT); - - const isViewingBalances = _.includes(props.location.pathname, `${WebsitePaths.Portal}/balances`); - const hasAlreadyDismissedWethNotice = LegacyPortal.hasAlreadyDismissedWethNotice(); - - const didAcceptPortalDisclaimer = localStorage.getItemIfExists(constants.LOCAL_STORAGE_KEY_ACCEPT_DISCLAIMER); - const hasAcceptedDisclaimer = - !_.isUndefined(didAcceptPortalDisclaimer) && !_.isEmpty(didAcceptPortalDisclaimer); - this.state = { - prevNetworkId: this.props.networkId, - prevNodeVersion: this.props.nodeVersion, - prevUserAddress: this.props.userAddress, - prevPathname: this.props.location.pathname, - isDisclaimerDialogOpen: !hasAcceptedDisclaimer, - isWethNoticeDialogOpen: !hasAlreadyDismissedWethNotice && isViewingBalances, - isLedgerDialogOpen: false, - }; - } - public componentDidMount(): void { - window.addEventListener('resize', this._throttledScreenWidthUpdate); - window.scrollTo(0, 0); - } - public componentWillMount(): void { - this._blockchain = new Blockchain(this.props.dispatcher); - } - public componentWillUnmount(): void { - this._blockchain.destroy(); - window.removeEventListener('resize', this._throttledScreenWidthUpdate); - // We re-set the entire redux state when the portal is unmounted so that when it is re-rendered - // the initialization process always occurs from the same base state. This helps avoid - // initialization inconsistencies (i.e While the portal was unrendered, the user might have - // become disconnected from their backing Ethereum node, changes user accounts, etc...) - this.props.dispatcher.resetState(); - } - public componentWillReceiveProps(nextProps: LegacyPortalProps): void { - if (nextProps.networkId !== this.state.prevNetworkId) { - // tslint:disable-next-line:no-floating-promises - this._blockchain.networkIdUpdatedFireAndForgetAsync(nextProps.networkId); - this.setState({ - prevNetworkId: nextProps.networkId, - }); - } - if (nextProps.userAddress !== this.state.prevUserAddress) { - const newUserAddress = _.isEmpty(nextProps.userAddress) ? undefined : nextProps.userAddress; - // tslint:disable-next-line:no-floating-promises - this._blockchain.userAddressUpdatedFireAndForgetAsync(newUserAddress); - this.setState({ - prevUserAddress: nextProps.userAddress, - }); - } - if (nextProps.nodeVersion !== this.state.prevNodeVersion) { - // tslint:disable-next-line:no-floating-promises - this._blockchain.nodeVersionUpdatedFireAndForgetAsync(nextProps.nodeVersion); - } - if (nextProps.location.pathname !== this.state.prevPathname) { - const isViewingBalances = _.includes(nextProps.location.pathname, `${WebsitePaths.Portal}/balances`); - const hasAlreadyDismissedWethNotice = LegacyPortal.hasAlreadyDismissedWethNotice(); - this.setState({ - prevPathname: nextProps.location.pathname, - isWethNoticeDialogOpen: !hasAlreadyDismissedWethNotice && isViewingBalances, - }); - } - } - public render(): React.ReactNode { - const updateShouldBlockchainErrDialogBeOpen = this.props.dispatcher.updateShouldBlockchainErrDialogBeOpen.bind( - this.props.dispatcher, - ); - const portalStyle: React.CSSProperties = { - minHeight: '100vh', - display: 'flex', - flexDirection: 'column', - justifyContent: 'space-between', - }; - const portalMenuContainerStyle: React.CSSProperties = { - overflow: 'hidden', - backgroundColor: colors.darkestGrey, - color: colors.white, - }; - return ( -
- - -
- -
-
- -
-
-
- {this.props.blockchainIsLoaded ? ( - - - - - - - - ) : ( -
-
-
- -
-
- Loading Portal... -
-
-
- )} -
-
-
-
- - - - - -
-
-
- ); - } - public onToggleLedgerDialog(): void { - this.setState({ - isLedgerDialogOpen: !this.state.isLedgerDialogOpen, - }); - } - private _renderEthWrapper(): React.ReactNode { - return ( - - ); - } - private _renderTradeHistory(): React.ReactNode { - return ( - - ); - } - private _renderTokenBalances(): React.ReactNode { - const trackedTokens = utils.getTrackedTokens(this.props.tokenByAddress); - return ( - - ); - } - private _renderFillOrder(_match: any, _location: Location, _history: History): React.ReactNode { - const initialFillOrder = !_.isUndefined(this.props.userSuppliedOrderCache) - ? this.props.userSuppliedOrderCache - : this._sharedOrderIfExists; - return ( - - ); - } - private _renderGenerateOrderForm(_match: any, _location: Location, _history: History): React.ReactNode { - return ( - - ); - } - private _onPortalDisclaimerAccepted(): void { - localStorage.setItem(constants.LOCAL_STORAGE_KEY_ACCEPT_DISCLAIMER, 'set'); - this.setState({ - isDisclaimerDialogOpen: false, - }); - } - private _onWethNoticeAccepted(): void { - localStorage.setItem(constants.LOCAL_STORAGE_KEY_DISMISS_WETH_NOTICE, 'set'); - this.setState({ - isWethNoticeDialogOpen: false, - }); - } - private _updateScreenWidth(): void { - const newScreenWidth = utils.getScreenWidth(); - this.props.dispatcher.updateScreenWidth(newScreenWidth); - } -} diff --git a/packages/website/ts/components/legacy_portal/legacy_portal_menu.tsx b/packages/website/ts/components/legacy_portal/legacy_portal_menu.tsx deleted file mode 100644 index 1dd164f8b..000000000 --- a/packages/website/ts/components/legacy_portal/legacy_portal_menu.tsx +++ /dev/null @@ -1,73 +0,0 @@ -import * as _ from 'lodash'; -import * as React from 'react'; -import { MenuItem } from 'ts/components/ui/menu_item'; -import { WebsitePaths } from 'ts/types'; - -export interface LegacyPortalMenuProps { - menuItemStyle: React.CSSProperties; - onClick?: () => void; -} - -interface LegacyPortalMenuState {} - -export class LegacyPortalMenu extends React.Component { - public static defaultProps: Partial = { - onClick: _.noop, - }; - public render(): React.ReactNode { - return ( -
- - {this._renderMenuItemWithIcon('Generate order', 'zmdi-arrow-right-top')} - - - {this._renderMenuItemWithIcon('Fill order', 'zmdi-arrow-left-bottom')} - - - {this._renderMenuItemWithIcon('Balances', 'zmdi-balance-wallet')} - - - {this._renderMenuItemWithIcon('Trade history', 'zmdi-format-list-bulleted')} - - - {this._renderMenuItemWithIcon('Wrap ETH', 'zmdi-circle-o')} - -
- ); - } - private _renderMenuItemWithIcon(title: string, iconName: string): React.ReactNode { - return ( -
-
- -
-
{title}
-
- ); - } -} diff --git a/packages/website/ts/components/top_bar/top_bar.tsx b/packages/website/ts/components/top_bar/top_bar.tsx index 960e5a824..63ea3475a 100644 --- a/packages/website/ts/components/top_bar/top_bar.tsx +++ b/packages/website/ts/components/top_bar/top_bar.tsx @@ -7,7 +7,6 @@ import MenuItem from 'material-ui/MenuItem'; import * as React from 'react'; import { Link } from 'react-router-dom'; import { Blockchain } from 'ts/blockchain'; -import { LegacyPortalMenu } from 'ts/components/legacy_portal/legacy_portal_menu'; import { DrawerMenu } from 'ts/components/portal/drawer_menu'; import { ProviderDisplay } from 'ts/components/top_bar/provider_display'; import { TopBarMenuItem } from 'ts/components/top_bar/top_bar_menu_item'; @@ -17,7 +16,6 @@ import { Dispatcher } from 'ts/redux/dispatcher'; import { Deco, Key, ProviderType, WebsiteLegacyPaths, WebsitePaths } from 'ts/types'; import { constants } from 'ts/utils/constants'; import { Translate } from 'ts/utils/translate'; -import { utils } from 'ts/utils/utils'; export enum TopBarDisplayType { Default, @@ -213,8 +211,6 @@ export class TopBar extends React.Component {
); const popoverContent = {developerSectionMenuItems}; - // TODO : Remove this once we ship portal v2 - const shouldShowPortalV2Drawer = this._isViewingPortal() && utils.shouldShowPortalV2(); return (
{
- {shouldShowPortalV2Drawer ? this._renderPortalV2Drawer() : this._renderDrawer()} + {this._isViewingPortal() ? this._renderPortalDrawer() : this._renderDrawer()} ); } - private _renderPortalV2Drawer(): React.ReactNode { + private _renderPortalDrawer(): React.ReactNode { return ( { onRequestChange={this._onMenuButtonClick.bind(this)} >
- {this._renderPortalMenu()} {this._renderDocsMenu()} {this._renderWiki()}
@@ -478,20 +473,6 @@ export class TopBar extends React.Component {
); } - private _renderPortalMenu(): React.ReactNode { - if (!this._isViewingPortal()) { - return undefined; - } - - return ( -
-
- {this.props.translate.get(Key.PortalDApp, Deco.CapWords)} -
- -
- ); - } private _onMenuButtonClick(): void { this.setState({ isDrawerOpen: !this.state.isDrawerOpen, diff --git a/packages/website/ts/containers/legacy_portal.ts b/packages/website/ts/containers/legacy_portal.ts deleted file mode 100644 index e99f47fb7..000000000 --- a/packages/website/ts/containers/legacy_portal.ts +++ /dev/null @@ -1,92 +0,0 @@ -import { BigNumber } from '@0xproject/utils'; -import * as _ from 'lodash'; -import * as React from 'react'; -import { connect } from 'react-redux'; -import { Dispatch } from 'redux'; -import { - LegacyPortal as LegacyPortalComponent, - LegacyPortalProps as LegacyPortalComponentProps, -} from 'ts/components/legacy_portal/legacy_portal'; -import { Dispatcher } from 'ts/redux/dispatcher'; -import { State } from 'ts/redux/reducer'; -import { BlockchainErrs, HashData, Order, ProviderType, ScreenWidths, Side, TokenByAddress } from 'ts/types'; -import { constants } from 'ts/utils/constants'; -import { Translate } from 'ts/utils/translate'; - -interface ConnectedState { - blockchainErr: BlockchainErrs; - blockchainIsLoaded: boolean; - hashData: HashData; - injectedProviderName: string; - networkId: number; - nodeVersion: string; - orderFillAmount: BigNumber; - providerType: ProviderType; - tokenByAddress: TokenByAddress; - lastForceTokenStateRefetch: number; - userEtherBalanceInWei?: BigNumber; - screenWidth: ScreenWidths; - shouldBlockchainErrDialogBeOpen: boolean; - userAddress: string; - userSuppliedOrderCache: Order; - flashMessage?: string | React.ReactNode; - translate: Translate; -} - -interface ConnectedDispatch { - dispatcher: Dispatcher; -} - -const mapStateToProps = (state: State, _ownProps: LegacyPortalComponentProps): ConnectedState => { - const receiveAssetToken = state.sideToAssetToken[Side.Receive]; - const depositAssetToken = state.sideToAssetToken[Side.Deposit]; - const receiveAddress = !_.isUndefined(receiveAssetToken.address) - ? receiveAssetToken.address - : constants.NULL_ADDRESS; - const depositAddress = !_.isUndefined(depositAssetToken.address) - ? depositAssetToken.address - : constants.NULL_ADDRESS; - const receiveAmount = !_.isUndefined(receiveAssetToken.amount) ? receiveAssetToken.amount : new BigNumber(0); - const depositAmount = !_.isUndefined(depositAssetToken.amount) ? depositAssetToken.amount : new BigNumber(0); - const hashData = { - depositAmount, - depositTokenContractAddr: depositAddress, - feeRecipientAddress: constants.NULL_ADDRESS, - makerFee: constants.MAKER_FEE, - orderExpiryTimestamp: state.orderExpiryTimestamp, - orderMakerAddress: state.userAddress, - orderTakerAddress: state.orderTakerAddress !== '' ? state.orderTakerAddress : constants.NULL_ADDRESS, - receiveAmount, - receiveTokenContractAddr: receiveAddress, - takerFee: constants.TAKER_FEE, - orderSalt: state.orderSalt, - }; - return { - blockchainErr: state.blockchainErr, - blockchainIsLoaded: state.blockchainIsLoaded, - hashData, - injectedProviderName: state.injectedProviderName, - networkId: state.networkId, - nodeVersion: state.nodeVersion, - orderFillAmount: state.orderFillAmount, - providerType: state.providerType, - screenWidth: state.screenWidth, - shouldBlockchainErrDialogBeOpen: state.shouldBlockchainErrDialogBeOpen, - tokenByAddress: state.tokenByAddress, - lastForceTokenStateRefetch: state.lastForceTokenStateRefetch, - userAddress: state.userAddress, - userEtherBalanceInWei: state.userEtherBalanceInWei, - userSuppliedOrderCache: state.userSuppliedOrderCache, - flashMessage: state.flashMessage, - translate: state.translate, - }; -}; - -const mapDispatchToProps = (dispatch: Dispatch): ConnectedDispatch => ({ - dispatcher: new Dispatcher(dispatch), -}); - -export const LegacyPortal: React.ComponentClass = connect( - mapStateToProps, - mapDispatchToProps, -)(LegacyPortalComponent); diff --git a/packages/website/ts/index.tsx b/packages/website/ts/index.tsx index c7ccfdf1f..7ceec8c2c 100644 --- a/packages/website/ts/index.tsx +++ b/packages/website/ts/index.tsx @@ -35,14 +35,9 @@ import 'less/all.less'; // At the same time webpack statically parses for System.import() to determine bundle chunk split points // so each lazy import needs it's own `System.import()` declaration. -// TODO: Remove this once we ship V2 -const LazyPortal = utils.shouldShowPortalV2() - ? createLazyComponent('Portal', async () => - System.import(/* webpackChunkName: "portal" */ 'ts/containers/portal'), - ) - : createLazyComponent('LegacyPortal', async () => - System.import(/* webpackChunkName: "legacyPortal" */ 'ts/containers/legacy_portal'), - ); +const LazyPortal = createLazyComponent('Portal', async () => + System.import(/* webpackChunkName: "portal" */ 'ts/containers/portal'), +); const LazyZeroExJSDocumentation = createLazyComponent('Documentation', async () => System.import(/* webpackChunkName: "zeroExDocs" */ 'ts/containers/zero_ex_js_documentation'), ); diff --git a/packages/website/ts/utils/utils.ts b/packages/website/ts/utils/utils.ts index 8c76a7592..9ca7f607b 100644 --- a/packages/website/ts/utils/utils.ts +++ b/packages/website/ts/utils/utils.ts @@ -358,11 +358,6 @@ export const utils = { return providerType === ProviderType.Injected && injectedProviderName !== constants.PROVIDER_NAME_PUBLIC; }, isDogfood, - shouldShowPortalV2(): boolean { - // return this.isDevelopment() || this.isStaging() || this.isDogfood(); - // TODO: Remove this method entirely after launch. - return true; - }, shouldShowJobsPage(): boolean { return this.isDevelopment() || this.isStaging() || this.isDogfood(); }, -- cgit v1.2.3 From 1ee78062d7731b35e47c0d4c4e30a68628f364a9 Mon Sep 17 00:00:00 2001 From: fragosti Date: Wed, 11 Jul 2018 15:43:37 -0700 Subject: Remove unused configs and constants --- packages/website/ts/utils/configs.ts | 1 - packages/website/ts/utils/constants.ts | 1 - 2 files changed, 2 deletions(-) (limited to 'packages/website') diff --git a/packages/website/ts/utils/configs.ts b/packages/website/ts/utils/configs.ts index a2fd6a47e..97aabd13d 100644 --- a/packages/website/ts/utils/configs.ts +++ b/packages/website/ts/utils/configs.ts @@ -23,7 +23,6 @@ export const configs = { DOMAIN_PRODUCTION: '0xproject.com', ENVIRONMENT: isDevelopment ? Environments.DEVELOPMENT : Environments.PRODUCTION, GOOGLE_ANALYTICS_ID: 'UA-98720122-1', - HEAP_APP_ID: '410099666', LAST_LOCAL_STORAGE_FILL_CLEARANCE_DATE: '2017-11-22', LAST_LOCAL_STORAGE_TRACKED_TOKEN_CLEARANCE_DATE: '2018-7-5', OUTDATED_WRAPPED_ETHERS: [ diff --git a/packages/website/ts/utils/constants.ts b/packages/website/ts/utils/constants.ts index d52b9b392..e43f541bf 100644 --- a/packages/website/ts/utils/constants.ts +++ b/packages/website/ts/utils/constants.ts @@ -34,7 +34,6 @@ export const constants = { PROVIDER_NAME_GENERIC: 'Injected Web3', PROVIDER_NAME_PUBLIC: '0x Public', ROLLBAR_ACCESS_TOKEN: '32c39bfa4bb6440faedc1612a9c13d28', - HEAP_APP_ID: '410099666', S3_DOC_BUCKET_ROOT: 'https://s3.amazonaws.com/doc-jsons', S3_STAGING_DOC_BUCKET_ROOT: 'https://s3.amazonaws.com/staging-doc-jsons', SUCCESS_STATUS: 200, -- cgit v1.2.3 From 0941e0a929f2fe3ef6d0cf1de5a1274f5f45f031 Mon Sep 17 00:00:00 2001 From: fragosti Date: Wed, 11 Jul 2018 16:50:00 -0700 Subject: Add no-floating-promises ignore comments --- packages/website/ts/components/fill_order.tsx | 1 + packages/website/ts/components/forms/subscribe_form.tsx | 1 + .../website/ts/components/generate_order/generate_order_form.tsx | 2 ++ packages/website/ts/components/inputs/allowance_toggle.tsx | 2 ++ .../website/ts/components/onboarding/portal_onboarding_flow.tsx | 2 ++ packages/website/ts/components/portal/portal.tsx | 1 + packages/website/ts/components/relayer_index/relayer_grid_tile.tsx | 1 + .../website/ts/components/relayer_index/relayer_top_tokens.tsx | 7 ++----- packages/website/ts/components/wallet/wallet.tsx | 2 ++ packages/website/ts/components/wallet/wrap_ether_item.tsx | 4 ++++ packages/website/ts/redux/analyticsMiddleware.ts | 5 +++++ packages/website/ts/utils/analytics.ts | 1 + 12 files changed, 24 insertions(+), 5 deletions(-) (limited to 'packages/website') diff --git a/packages/website/ts/components/fill_order.tsx b/packages/website/ts/components/fill_order.tsx index 25d21c3dd..e4838bc0f 100644 --- a/packages/website/ts/components/fill_order.tsx +++ b/packages/website/ts/components/fill_order.tsx @@ -508,6 +508,7 @@ export class FillOrder extends React.Component { } private _trackOrderEvent(eventName: string): void { const parsedOrder = this.state.parsedOrder; + // tslint:disable-next-line:no-floating-promises analytics.trackOrderEventAsync(eventName, parsedOrder); } private async _onFillOrderClickFireAndForgetAsync(): Promise { diff --git a/packages/website/ts/components/forms/subscribe_form.tsx b/packages/website/ts/components/forms/subscribe_form.tsx index 19abbdf5f..be0468b6f 100644 --- a/packages/website/ts/components/forms/subscribe_form.tsx +++ b/packages/website/ts/components/forms/subscribe_form.tsx @@ -114,6 +114,7 @@ export class SubscribeForm extends React.Component { ); } private _startOnboarding(): void { + // tslint:disable-next-line:no-floating-promises analytics.trackAsync('Onboarding Started', { reason: 'manual', stepIndex: this.props.portalOnboardingStep, diff --git a/packages/website/ts/components/relayer_index/relayer_grid_tile.tsx b/packages/website/ts/components/relayer_index/relayer_grid_tile.tsx index 937f0b79d..475b79f8f 100644 --- a/packages/website/ts/components/relayer_index/relayer_grid_tile.tsx +++ b/packages/website/ts/components/relayer_index/relayer_grid_tile.tsx @@ -65,6 +65,7 @@ export const RelayerGridTile: React.StatelessComponent = ( const topTokens = props.relayerInfo.topTokens; const weeklyTxnVolume = props.relayerInfo.weeklyTxnVolume; const onClick = () => { + // tslint:disable-next-line:no-floating-promises analytics.trackAsync('Relayer Click', { name: props.relayerInfo.name, }); diff --git a/packages/website/ts/components/relayer_index/relayer_top_tokens.tsx b/packages/website/ts/components/relayer_index/relayer_top_tokens.tsx index e6e0095c2..33783b406 100644 --- a/packages/website/ts/components/relayer_index/relayer_top_tokens.tsx +++ b/packages/website/ts/components/relayer_index/relayer_top_tokens.tsx @@ -1,8 +1,4 @@ -import { - colors, - EtherscanLinkSuffixes, - utils as sharedUtils, -} from '@0xproject/react-shared'; +import { colors, EtherscanLinkSuffixes, utils as sharedUtils } from '@0xproject/react-shared'; import * as _ from 'lodash'; import * as React from 'react'; @@ -47,6 +43,7 @@ class TokenLink extends React.Component { public render(): React.ReactNode { const onClick = (event: React.MouseEvent) => { event.stopPropagation(); + // tslint:disable-next-line:no-floating-promises analytics.trackAsync('Token Click', { tokenSymbol: this.props.tokenInfo.symbol, }); diff --git a/packages/website/ts/components/wallet/wallet.tsx b/packages/website/ts/components/wallet/wallet.tsx index 2fdcded38..8523b819a 100644 --- a/packages/website/ts/components/wallet/wallet.tsx +++ b/packages/website/ts/components/wallet/wallet.tsx @@ -490,6 +490,7 @@ export class Wallet extends React.Component { private _openWrappedEtherActionRow(wrappedEtherDirection: Side): void { const action = wrappedEtherDirection === Side.Deposit ? 'Wallet - Wrap ETH Opened' : 'Wallet - Unwrap WETH Opened'; + // tslint:disable-next-line:no-floating-promises analytics.trackAsync(action); this.setState({ wrappedEtherDirection, @@ -498,6 +499,7 @@ export class Wallet extends React.Component { private _closeWrappedEtherActionRow(wrappedEtherDirection: Side): void { const action = wrappedEtherDirection === Side.Deposit ? 'Wallet - Wrap ETH Closed' : 'Wallet - Unwrap WETH Closed'; + // tslint:disable-next-line:no-floating-promises analytics.trackAsync(action); this.setState({ wrappedEtherDirection: undefined, diff --git a/packages/website/ts/components/wallet/wrap_ether_item.tsx b/packages/website/ts/components/wallet/wrap_ether_item.tsx index 9fec8afa1..9e3d06817 100644 --- a/packages/website/ts/components/wallet/wrap_ether_item.tsx +++ b/packages/website/ts/components/wallet/wrap_ether_item.tsx @@ -196,12 +196,14 @@ export class WrapEtherItem extends React.Component next => action => { const nextState = (store.getState() as any) as State; switch (action.type) { case ActionTypes.UpdateInjectedProviderName: + // tslint:disable-next-line:no-floating-promises analytics.addEventPropertiesAsync({ injectedProviderName: nextState.injectedProviderName, }); break; case ActionTypes.UpdateNetworkId: + // tslint:disable-next-line:no-floating-promises analytics.addEventPropertiesAsync({ networkId: nextState.networkId, }); break; case ActionTypes.UpdateUserAddress: + // tslint:disable-next-line:no-floating-promises analytics.addUserPropertiesAsync({ ethAddress: nextState.userAddress, }); break; case ActionTypes.UpdateUserEtherBalance: if (nextState.userEtherBalanceInWei) { + // tslint:disable-next-line:no-floating-promises analytics.addUserPropertiesAsync({ ethBalance: nextState.userEtherBalanceInWei.toString(), }); } break; case ActionTypes.UpdatePortalOnboardingStep: + // tslint:disable-next-line:no-floating-promises analytics.trackAsync('Update Onboarding Step', { stepIndex: nextState.portalOnboardingStep, }); diff --git a/packages/website/ts/utils/analytics.ts b/packages/website/ts/utils/analytics.ts index 961f9af5a..2ff9f8918 100644 --- a/packages/website/ts/utils/analytics.ts +++ b/packages/website/ts/utils/analytics.ts @@ -66,6 +66,7 @@ export class Analytics { takerToken: order.metadata.takerToken.symbol, makerToken: order.metadata.makerToken.symbol, }; + // tslint:disable-next-line:no-floating-promises this.trackAsync(eventName, orderLoggingData); } /** -- cgit v1.2.3 From f4b2a9625dd46080a4fd05754c525f73e5fff8b1 Mon Sep 17 00:00:00 2001 From: fragosti Date: Wed, 11 Jul 2018 18:52:22 -0700 Subject: Only upload sourcemaps to rollbar on live deploys, and log NaN error for future debugging --- packages/website/package.json | 2 +- packages/website/ts/utils/utils.ts | 4 +++ packages/website/webpack.config.js | 68 +++++++++++++++++++++----------------- 3 files changed, 43 insertions(+), 31 deletions(-) (limited to 'packages/website') diff --git a/packages/website/package.json b/packages/website/package.json index b5b4b6119..a8a761fea 100644 --- a/packages/website/package.json +++ b/packages/website/package.json @@ -16,7 +16,7 @@ "deploy_staging": "npm run build; aws s3 sync ./public/. s3://staging-0xproject --profile 0xproject --region us-east-1 --grants read=uri=http://acs.amazonaws.com/groups/global/AllUsers", "deploy_live": - "npm run build; aws s3 sync ./public/. s3://0xproject.com --profile 0xproject --region us-east-1 --grants read=uri=http://acs.amazonaws.com/groups/global/AllUsers --exclude *.map.js" + "DEPLOY_ROLLBAR_SOURCEMAPS=true npm run build; aws s3 sync ./public/. s3://0xproject.com --profile 0xproject --region us-east-1 --grants read=uri=http://acs.amazonaws.com/groups/global/AllUsers --exclude *.map.js" }, "author": "Fabio Berger", "license": "Apache-2.0", diff --git a/packages/website/ts/utils/utils.ts b/packages/website/ts/utils/utils.ts index 9ca7f607b..e515cdeb3 100644 --- a/packages/website/ts/utils/utils.ts +++ b/packages/website/ts/utils/utils.ts @@ -29,6 +29,7 @@ import { import { configs } from 'ts/utils/configs'; import { constants } from 'ts/utils/constants'; import * as u2f from 'ts/vendor/u2f_api'; +import { errorReporter } from './error_reporter'; const isDogfood = (): boolean => _.includes(window.location.href, configs.DOMAIN_DOGFOOD); @@ -389,6 +390,9 @@ export const utils = { : 2; const format = `0,0.${_.repeat('0', precision)}`; const formattedAmount = numeral(unitAmount).format(format); + if (_.isNaN(formattedAmount)) { + throw new Error(`amount ${BigNumber}, decimals ${decimals} could not be formatted and returned NaN.`); + } return formattedAmount; }, getUsdValueFormattedAmount(amount: BigNumber, decimals: number, price: BigNumber): string { diff --git a/packages/website/webpack.config.js b/packages/website/webpack.config.js index 5647b4f93..8653196a6 100644 --- a/packages/website/webpack.config.js +++ b/packages/website/webpack.config.js @@ -9,6 +9,43 @@ const GIT_SHA = childProcess .toString() .trim(); +const generatePlugins = () => { + let plugins = []; + if (process.env.NODE_ENV === 'production') { + plugins = plugins.concat([ + // Since we do not use moment's locale feature, we exclude them from the bundle. + // This reduces the bundle size by 0.4MB. + new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/), + new webpack.DefinePlugin({ + 'process.env': { + NODE_ENV: JSON.stringify(process.env.NODE_ENV), + GIT_SHA: JSON.stringify(GIT_SHA), + }, + }), + // TODO: Revert to webpack bundled version with webpack v4. + // The v3 series bundled version does not support ES6 and + // fails to build. + new UglifyJsPlugin({ + sourceMap: true, + uglifyOptions: { + mangle: { + reserved: ['BigNumber'], + }, + }, + }), + ]); + if (process.env.DEPLOY_ROLLBAR_SOURCEMAPS === 'true') { + plugins = plugins.concat([ + new RollbarSourceMapPlugin({ + accessToken: '32c39bfa4bb6440faedc1612a9c13d28', + version: GIT_SHA, + publicPath: 'https://0xproject.com/', + }), + ]); + } + } + return plugins; +}; module.exports = { entry: ['./ts/index.tsx'], output: { @@ -78,34 +115,5 @@ module.exports = { }, disableHostCheck: true, }, - plugins: - process.env.NODE_ENV === 'production' - ? [ - // Since we do not use moment's locale feature, we exclude them from the bundle. - // This reduces the bundle size by 0.4MB. - new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/), - new webpack.DefinePlugin({ - 'process.env': { - NODE_ENV: JSON.stringify(process.env.NODE_ENV), - GIT_SHA: JSON.stringify(GIT_SHA), - }, - }), - // TODO: Revert to webpack bundled version with webpack v4. - // The v3 series bundled version does not support ES6 and - // fails to build. - new UglifyJsPlugin({ - sourceMap: true, - uglifyOptions: { - mangle: { - reserved: ['BigNumber'], - }, - }, - }), - new RollbarSourceMapPlugin({ - accessToken: '32c39bfa4bb6440faedc1612a9c13d28', - version: GIT_SHA, - publicPath: 'https://0xproject.com/', - }), - ] - : [], + plugins: generatePlugins(), }; -- cgit v1.2.3 From ddb70a89ad99527e03844d23e7c0f3522e98a602 Mon Sep 17 00:00:00 2001 From: fragosti Date: Wed, 11 Jul 2018 18:55:02 -0700 Subject: Do not crash on NaN, and provide default --- packages/website/ts/utils/utils.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'packages/website') diff --git a/packages/website/ts/utils/utils.ts b/packages/website/ts/utils/utils.ts index e515cdeb3..1d669d8f0 100644 --- a/packages/website/ts/utils/utils.ts +++ b/packages/website/ts/utils/utils.ts @@ -28,8 +28,8 @@ import { } from 'ts/types'; import { configs } from 'ts/utils/configs'; import { constants } from 'ts/utils/constants'; +import { errorReporter } from 'ts/utils/error_reporter'; import * as u2f from 'ts/vendor/u2f_api'; -import { errorReporter } from './error_reporter'; const isDogfood = (): boolean => _.includes(window.location.href, configs.DOMAIN_DOGFOOD); @@ -391,7 +391,11 @@ export const utils = { const format = `0,0.${_.repeat('0', precision)}`; const formattedAmount = numeral(unitAmount).format(format); if (_.isNaN(formattedAmount)) { - throw new Error(`amount ${BigNumber}, decimals ${decimals} could not be formatted and returned NaN.`); + // tslint:disable-next-line:no-floating-promises + errorReporter.reportAsync( + new Error(`amount ${BigNumber}, decimals ${decimals} could not be formatted and returned NaN.`), + ); + return format; } return formattedAmount; }, -- cgit v1.2.3 From ac5588c7c436e2540f87e432446e103d35c9221a Mon Sep 17 00:00:00 2001 From: fragosti Date: Thu, 12 Jul 2018 15:50:13 -0700 Subject: Make error reporter not return a promise and add more environment possibilities --- packages/website/ts/blockchain.ts | 6 ++-- .../ts/components/eth_weth_conversion_button.tsx | 2 +- packages/website/ts/components/fill_order.tsx | 4 +-- .../generate_order/generate_order_form.tsx | 2 +- .../ts/components/inputs/allowance_toggle.tsx | 2 +- packages/website/ts/components/order_json.tsx | 2 +- packages/website/ts/components/send_button.tsx | 2 +- packages/website/ts/components/token_balances.tsx | 4 +-- .../ts/components/wallet/wrap_ether_item.tsx | 2 +- packages/website/ts/types.ts | 2 ++ packages/website/ts/utils/configs.ts | 5 --- packages/website/ts/utils/error_reporter.ts | 22 +++++-------- packages/website/ts/utils/fetch_utils.ts | 3 +- packages/website/ts/utils/utils.ts | 36 ++++++++++++++++------ 14 files changed, 51 insertions(+), 43 deletions(-) (limited to 'packages/website') diff --git a/packages/website/ts/blockchain.ts b/packages/website/ts/blockchain.ts index 0e6698318..868ffad03 100644 --- a/packages/website/ts/blockchain.ts +++ b/packages/website/ts/blockchain.ts @@ -571,7 +571,7 @@ export class Blockchain { configs.DEFAULT_TRACKED_TOKEN_SYMBOLS, )}) not found in tokenRegistry: ${JSON.stringify(tokenRegistryTokens)}`, ); - await errorReporter.reportAsync(err); + errorReporter.report(err); return; } if (_.isEmpty(trackedTokensByAddress)) { @@ -683,7 +683,7 @@ export class Blockchain { // errors will be thrown by `watch`. For now, let's log the error // to rollbar and stop watching when one occurs // tslint:disable-next-line:no-floating-promises - errorReporter.reportAsync(err); // fire and forget + errorReporter.report(err); // fire and forget return; } else { const decodedLog = decodedLogEvent.log; @@ -915,7 +915,7 @@ export class Blockchain { if (_.includes(errMsg, 'not been deployed to detected network')) { throw new Error(BlockchainCallErrs.ContractDoesNotExist); } else { - await errorReporter.reportAsync(err); + errorReporter.report(err); throw new Error(BlockchainCallErrs.UnhandledError); } } diff --git a/packages/website/ts/components/eth_weth_conversion_button.tsx b/packages/website/ts/components/eth_weth_conversion_button.tsx index 4b91a2ebd..d547a4e6a 100644 --- a/packages/website/ts/components/eth_weth_conversion_button.tsx +++ b/packages/website/ts/components/eth_weth_conversion_button.tsx @@ -118,7 +118,7 @@ export class EthWethConversionButton extends React.Component< ? 'Failed to wrap your ETH. Please try again.' : 'Failed to unwrap your WETH. Please try again.'; this.props.dispatcher.showFlashMessage(errorMsg); - await errorReporter.reportAsync(err); + errorReporter.report(err); } } this.setState({ diff --git a/packages/website/ts/components/fill_order.tsx b/packages/website/ts/components/fill_order.tsx index 03ba1183d..9360ba24c 100644 --- a/packages/website/ts/components/fill_order.tsx +++ b/packages/website/ts/components/fill_order.tsx @@ -583,7 +583,7 @@ export class FillOrder extends React.Component { this.setState({ globalErrMsg, }); - await errorReporter.reportAsync(err); + errorReporter.report(err); return; } } @@ -654,7 +654,7 @@ export class FillOrder extends React.Component { this.setState({ globalErrMsg, }); - await errorReporter.reportAsync(err); + errorReporter.report(err); return; } } diff --git a/packages/website/ts/components/generate_order/generate_order_form.tsx b/packages/website/ts/components/generate_order/generate_order_form.tsx index d26b5c3fa..7d7df5506 100644 --- a/packages/website/ts/components/generate_order/generate_order_form.tsx +++ b/packages/website/ts/components/generate_order/generate_order_form.tsx @@ -349,7 +349,7 @@ export class GenerateOrderForm extends React.Component ${responseBody}`); - await errorReporter.reportAsync(new Error(`Bitly returned non-200: ${JSON.stringify(response)}`)); + errorReporter.report(new Error(`Bitly returned non-200: ${JSON.stringify(response)}`)); return ''; } return bodyObj.data.url; diff --git a/packages/website/ts/components/send_button.tsx b/packages/website/ts/components/send_button.tsx index 8486dbd8b..ac55d430b 100644 --- a/packages/website/ts/components/send_button.tsx +++ b/packages/website/ts/components/send_button.tsx @@ -80,7 +80,7 @@ export class SendButton extends React.Component { - if (configs.ENVIRONMENT === Environments.DEVELOPMENT) { + report(err: Error): void { + if (utils.getEnvironment() === Environments.DEVELOPMENT) { return; // Let's not log development errors to rollbar } - - return new Promise((resolve, _reject) => { - rollbar.error(err, (rollbarErr: Error) => { - if (rollbarErr) { - logUtils.log(`Error reporting to rollbar, ignoring: ${rollbarErr}`); - // We never want to reject and cause the app to throw because of rollbar - resolve(); - } else { - resolve(); - } - }); + rollbar.error(err, (rollbarErr: Error) => { + if (rollbarErr) { + logUtils.log(`Error reporting to rollbar, ignoring: ${rollbarErr}`); + } }); }, }; diff --git a/packages/website/ts/utils/fetch_utils.ts b/packages/website/ts/utils/fetch_utils.ts index 513f7e479..a56d89262 100644 --- a/packages/website/ts/utils/fetch_utils.ts +++ b/packages/website/ts/utils/fetch_utils.ts @@ -9,8 +9,7 @@ const logErrorIfPresent = (response: Response, requestedURL: string) => { const errorText = `Error requesting url: ${requestedURL}, ${response.status}: ${response.statusText}`; logUtils.log(errorText); const error = Error(errorText); - // tslint:disable-next-line:no-floating-promises - errorReporter.reportAsync(error); + errorReporter.report(error); throw error; } }; diff --git a/packages/website/ts/utils/utils.ts b/packages/website/ts/utils/utils.ts index 1d669d8f0..240170113 100644 --- a/packages/website/ts/utils/utils.ts +++ b/packages/website/ts/utils/utils.ts @@ -31,8 +31,6 @@ import { constants } from 'ts/utils/constants'; import { errorReporter } from 'ts/utils/error_reporter'; import * as u2f from 'ts/vendor/u2f_api'; -const isDogfood = (): boolean => _.includes(window.location.href, configs.DOMAIN_DOGFOOD); - export const utils = { assert(condition: boolean, message: string): void { if (!condition) { @@ -347,10 +345,13 @@ export const utils = { return parsedProviderName; }, getBackendBaseUrl(): string { - return isDogfood() ? configs.BACKEND_BASE_STAGING_URL : configs.BACKEND_BASE_PROD_URL; + return utils.isDogfood() ? configs.BACKEND_BASE_STAGING_URL : configs.BACKEND_BASE_PROD_URL; }, isDevelopment(): boolean { - return configs.ENVIRONMENT === Environments.DEVELOPMENT; + return _.includes( + ['https://0xproject.localhost:3572', 'https://localhost:3572', 'https://127.0.0.1'], + window.location.origin, + ); }, isStaging(): boolean { return _.includes(window.location.href, configs.DOMAIN_STAGING); @@ -358,7 +359,27 @@ export const utils = { isExternallyInjected(providerType: ProviderType, injectedProviderName: string): boolean { return providerType === ProviderType.Injected && injectedProviderName !== constants.PROVIDER_NAME_PUBLIC; }, - isDogfood, + isDogfood(): boolean { + return _.includes(window.location.href, configs.DOMAIN_DOGFOOD); + }, + isProduction(): boolean { + return _.includes(window.location.href, configs.DOMAIN_PRODUCTION); + }, + getEnvironment(): Environments { + if (utils.isDogfood()) { + return Environments.DOGFOOD; + } + if (utils.isDevelopment()) { + return Environments.DEVELOPMENT; + } + if (utils.isStaging()) { + return Environments.STAGING; + } + if (utils.isProduction()) { + return Environments.PRODUCTION; + } + return undefined; + }, shouldShowJobsPage(): boolean { return this.isDevelopment() || this.isStaging() || this.isDogfood(); }, @@ -391,10 +412,7 @@ export const utils = { const format = `0,0.${_.repeat('0', precision)}`; const formattedAmount = numeral(unitAmount).format(format); if (_.isNaN(formattedAmount)) { - // tslint:disable-next-line:no-floating-promises - errorReporter.reportAsync( - new Error(`amount ${BigNumber}, decimals ${decimals} could not be formatted and returned NaN.`), - ); + // https://github.com/adamwdraper/Numeral-js/issues/596 return format; } return formattedAmount; -- cgit v1.2.3 From 254d30b8df4d04111458b639073dfbf9f82bf3d0 Mon Sep 17 00:00:00 2001 From: fragosti Date: Thu, 12 Jul 2018 15:54:35 -0700 Subject: Fix linting errors --- packages/website/ts/utils/configs.ts | 3 +-- packages/website/ts/utils/utils.ts | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) (limited to 'packages/website') diff --git a/packages/website/ts/utils/configs.ts b/packages/website/ts/utils/configs.ts index 745328d0a..9652a0925 100644 --- a/packages/website/ts/utils/configs.ts +++ b/packages/website/ts/utils/configs.ts @@ -1,5 +1,4 @@ -import * as _ from 'lodash'; -import { Environments, OutdatedWrappedEtherByNetworkId, PublicNodeUrlsByNetworkId } from 'ts/types'; +import { OutdatedWrappedEtherByNetworkId, PublicNodeUrlsByNetworkId } from 'ts/types'; const BASE_URL = window.location.origin; const INFURA_API_KEY = 'T5WSC8cautR4KXyYgsRs'; diff --git a/packages/website/ts/utils/utils.ts b/packages/website/ts/utils/utils.ts index 240170113..e8152af87 100644 --- a/packages/website/ts/utils/utils.ts +++ b/packages/website/ts/utils/utils.ts @@ -28,7 +28,6 @@ import { } from 'ts/types'; import { configs } from 'ts/utils/configs'; import { constants } from 'ts/utils/constants'; -import { errorReporter } from 'ts/utils/error_reporter'; import * as u2f from 'ts/vendor/u2f_api'; export const utils = { @@ -501,4 +500,4 @@ export const utils = { const result = `/images/token_icons/${symbol}.png`; return result; }, -}; +}; // tslint:disable:max-file-line-count -- cgit v1.2.3 From 1df074b73e05adf669b0cedc4bb1473e9e5631db Mon Sep 17 00:00:00 2001 From: fragosti Date: Thu, 12 Jul 2018 16:57:03 -0700 Subject: Make Analytics API non-async --- packages/website/ts/components/fill_order.tsx | 3 +- .../website/ts/components/forms/subscribe_form.tsx | 3 +- .../generate_order/generate_order_form.tsx | 6 +-- .../ts/components/inputs/allowance_toggle.tsx | 6 +-- .../onboarding/portal_onboarding_flow.tsx | 6 +-- packages/website/ts/components/portal/portal.tsx | 3 +- .../components/relayer_index/relayer_grid_tile.tsx | 3 +- .../relayer_index/relayer_top_tokens.tsx | 3 +- packages/website/ts/components/wallet/wallet.tsx | 6 +-- .../ts/components/wallet/wrap_ether_item.tsx | 12 ++---- packages/website/ts/redux/analyticsMiddleware.ts | 15 +++---- packages/website/ts/utils/analytics.ts | 47 ++++++++++------------ packages/website/ts/utils/utils.ts | 2 +- 13 files changed, 44 insertions(+), 71 deletions(-) (limited to 'packages/website') diff --git a/packages/website/ts/components/fill_order.tsx b/packages/website/ts/components/fill_order.tsx index e4838bc0f..ff63410c3 100644 --- a/packages/website/ts/components/fill_order.tsx +++ b/packages/website/ts/components/fill_order.tsx @@ -508,8 +508,7 @@ export class FillOrder extends React.Component { } private _trackOrderEvent(eventName: string): void { const parsedOrder = this.state.parsedOrder; - // tslint:disable-next-line:no-floating-promises - analytics.trackOrderEventAsync(eventName, parsedOrder); + analytics.trackOrderEvent(eventName, parsedOrder); } private async _onFillOrderClickFireAndForgetAsync(): Promise { if (this.props.blockchainErr !== BlockchainErrs.NoError || _.isEmpty(this.props.userAddress)) { diff --git a/packages/website/ts/components/forms/subscribe_form.tsx b/packages/website/ts/components/forms/subscribe_form.tsx index be0468b6f..ef19af644 100644 --- a/packages/website/ts/components/forms/subscribe_form.tsx +++ b/packages/website/ts/components/forms/subscribe_form.tsx @@ -114,8 +114,7 @@ export class SubscribeForm extends React.Component { ); } private _startOnboarding(): void { - // tslint:disable-next-line:no-floating-promises - analytics.trackAsync('Onboarding Started', { + analytics.track('Onboarding Started', { reason: 'manual', stepIndex: this.props.portalOnboardingStep, }); diff --git a/packages/website/ts/components/relayer_index/relayer_grid_tile.tsx b/packages/website/ts/components/relayer_index/relayer_grid_tile.tsx index 475b79f8f..193dd237a 100644 --- a/packages/website/ts/components/relayer_index/relayer_grid_tile.tsx +++ b/packages/website/ts/components/relayer_index/relayer_grid_tile.tsx @@ -65,8 +65,7 @@ export const RelayerGridTile: React.StatelessComponent = ( const topTokens = props.relayerInfo.topTokens; const weeklyTxnVolume = props.relayerInfo.weeklyTxnVolume; const onClick = () => { - // tslint:disable-next-line:no-floating-promises - analytics.trackAsync('Relayer Click', { + analytics.track('Relayer Click', { name: props.relayerInfo.name, }); utils.openUrl(link); diff --git a/packages/website/ts/components/relayer_index/relayer_top_tokens.tsx b/packages/website/ts/components/relayer_index/relayer_top_tokens.tsx index 33783b406..f3787bd27 100644 --- a/packages/website/ts/components/relayer_index/relayer_top_tokens.tsx +++ b/packages/website/ts/components/relayer_index/relayer_top_tokens.tsx @@ -43,8 +43,7 @@ class TokenLink extends React.Component { public render(): React.ReactNode { const onClick = (event: React.MouseEvent) => { event.stopPropagation(); - // tslint:disable-next-line:no-floating-promises - analytics.trackAsync('Token Click', { + analytics.track('Token Click', { tokenSymbol: this.props.tokenInfo.symbol, }); const tokenLink = this._tokenLinkFromToken(this.props.tokenInfo, this.props.networkId); diff --git a/packages/website/ts/components/wallet/wallet.tsx b/packages/website/ts/components/wallet/wallet.tsx index 8523b819a..e462ab3e0 100644 --- a/packages/website/ts/components/wallet/wallet.tsx +++ b/packages/website/ts/components/wallet/wallet.tsx @@ -490,8 +490,7 @@ export class Wallet extends React.Component { private _openWrappedEtherActionRow(wrappedEtherDirection: Side): void { const action = wrappedEtherDirection === Side.Deposit ? 'Wallet - Wrap ETH Opened' : 'Wallet - Unwrap WETH Opened'; - // tslint:disable-next-line:no-floating-promises - analytics.trackAsync(action); + analytics.track(action); this.setState({ wrappedEtherDirection, }); @@ -499,8 +498,7 @@ export class Wallet extends React.Component { private _closeWrappedEtherActionRow(wrappedEtherDirection: Side): void { const action = wrappedEtherDirection === Side.Deposit ? 'Wallet - Wrap ETH Closed' : 'Wallet - Unwrap WETH Closed'; - // tslint:disable-next-line:no-floating-promises - analytics.trackAsync(action); + analytics.track(action); this.setState({ wrappedEtherDirection: undefined, }); diff --git a/packages/website/ts/components/wallet/wrap_ether_item.tsx b/packages/website/ts/components/wallet/wrap_ether_item.tsx index 9e3d06817..2b85b69be 100644 --- a/packages/website/ts/components/wallet/wrap_ether_item.tsx +++ b/packages/website/ts/components/wallet/wrap_ether_item.tsx @@ -196,15 +196,13 @@ export class WrapEtherItem extends React.Component next => action => { const nextState = (store.getState() as any) as State; switch (action.type) { case ActionTypes.UpdateInjectedProviderName: - // tslint:disable-next-line:no-floating-promises - analytics.addEventPropertiesAsync({ + analytics.addEventProperties({ injectedProviderName: nextState.injectedProviderName, }); break; case ActionTypes.UpdateNetworkId: - // tslint:disable-next-line:no-floating-promises - analytics.addEventPropertiesAsync({ + analytics.addEventProperties({ networkId: nextState.networkId, }); break; case ActionTypes.UpdateUserAddress: - // tslint:disable-next-line:no-floating-promises - analytics.addUserPropertiesAsync({ + analytics.addUserProperties({ ethAddress: nextState.userAddress, }); break; case ActionTypes.UpdateUserEtherBalance: if (nextState.userEtherBalanceInWei) { - // tslint:disable-next-line:no-floating-promises - analytics.addUserPropertiesAsync({ + analytics.addUserProperties({ ethBalance: nextState.userEtherBalanceInWei.toString(), }); } break; case ActionTypes.UpdatePortalOnboardingStep: - // tslint:disable-next-line:no-floating-promises - analytics.trackAsync('Update Onboarding Step', { + analytics.track('Update Onboarding Step', { stepIndex: nextState.portalOnboardingStep, }); break; diff --git a/packages/website/ts/utils/analytics.ts b/packages/website/ts/utils/analytics.ts index 2ff9f8918..e39998d7a 100644 --- a/packages/website/ts/utils/analytics.ts +++ b/packages/website/ts/utils/analytics.ts @@ -12,7 +12,6 @@ export interface HeapAnalytics { removeEventProperty(property: string): void; clearEventProperties(): void; } - export class Analytics { private _heap: HeapAnalytics; public static init(): Analytics { @@ -29,45 +28,39 @@ export class Analytics { constructor(heap: HeapAnalytics) { this._heap = heap; } + // tslint:disable:no-floating-promises // HeapAnalytics Wrappers - public async indentifyAsync(id: string, idType: string): Promise { - await this._heapLoadedGuardAsync(); - this._heap.indentify(id, idType); + public indentify(id: string, idType: string): void { + this._heapLoadedGuardAsync(() => this._heap.indentify(id, idType)); } - public async trackAsync(eventName: string, eventProperties?: ObjectMap): Promise { - await this._heapLoadedGuardAsync(); - this._heap.track(eventName, eventProperties); + public track(eventName: string, eventProperties?: ObjectMap): void { + this._heapLoadedGuardAsync(() => this._heap.track(eventName, eventProperties)); } - public async resetIdentityAsync(): Promise { - await this._heapLoadedGuardAsync(); - this._heap.resetIdentity(); + public resetIdentity(): void { + this._heapLoadedGuardAsync(() => this._heap.resetIdentity()); } - public async addUserPropertiesAsync(properties: ObjectMap): Promise { - await this._heapLoadedGuardAsync(); - this._heap.addUserProperties(properties); + public addUserProperties(properties: ObjectMap): void { + this._heapLoadedGuardAsync(() => this._heap.addUserProperties(properties)); } - public async addEventPropertiesAsync(properties: ObjectMap): Promise { - await this._heapLoadedGuardAsync(); - this._heap.addEventProperties(properties); + public addEventProperties(properties: ObjectMap): void { + this._heapLoadedGuardAsync(() => this._heap.addEventProperties(properties)); } - public async removeEventPropertyAsync(property: string): Promise { - await this._heapLoadedGuardAsync(); - this._heap.removeEventProperty(property); + public removeEventProperty(property: string): void { + this._heapLoadedGuardAsync(() => this._heap.removeEventProperty(property)); } - public async clearEventPropertiesAsync(): Promise { - await this._heapLoadedGuardAsync(); - this._heap.clearEventProperties(); + public clearEventProperties(): void { + this._heapLoadedGuardAsync(() => this._heap.clearEventProperties()); } + // tslint:enable:no-floating-promises // Custom methods - public async trackOrderEventAsync(eventName: string, order: Order): Promise { + public trackOrderEvent(eventName: string, order: Order): void { const orderLoggingData = { takerTokenAmount: order.signedOrder.takerTokenAmount, makeTokenAmount: order.signedOrder.makerTokenAmount, takerToken: order.metadata.takerToken.symbol, makerToken: order.metadata.makerToken.symbol, }; - // tslint:disable-next-line:no-floating-promises - this.trackAsync(eventName, orderLoggingData); + this.track(eventName, orderLoggingData); } /** * Heap is not available as a UMD module, and additionally has the strange property of replacing itself with @@ -75,13 +68,15 @@ export class Analytics { * Instead of having an await call before every analytics use, we opt to have the awaiting logic in here by * guarding every API call with the guard below. */ - private async _heapLoadedGuardAsync(): Promise { + private async _heapLoadedGuardAsync(callback: () => void): Promise { if (this._heap.loaded) { + callback(); return undefined; } await utils.onPageLoadPromise; // HACK: Reset heap to loaded heap this._heap = (window as any).heap; + callback(); } } diff --git a/packages/website/ts/utils/utils.ts b/packages/website/ts/utils/utils.ts index bd6a57eea..9c5e12ec7 100644 --- a/packages/website/ts/utils/utils.ts +++ b/packages/website/ts/utils/utils.ts @@ -318,7 +318,7 @@ export const utils = { resolve(); return; } - window.onload = () => resolve(); + window.onload = resolve; }), getProviderType(provider: Provider): Providers | string { const constructorName = provider.constructor.name; -- cgit v1.2.3 From b4747c3f85acb7d2909c5b7673d98055e8daaebe Mon Sep 17 00:00:00 2001 From: fragosti Date: Thu, 12 Jul 2018 18:11:25 -0700 Subject: Refactor utils and add UNNKOWN environment type --- packages/website/ts/blockchain.ts | 1 - packages/website/ts/types.ts | 1 + packages/website/ts/utils/configs.ts | 2 +- packages/website/ts/utils/error_reporter.ts | 3 +-- packages/website/ts/utils/utils.ts | 36 +++++++++++------------------ 5 files changed, 16 insertions(+), 27 deletions(-) (limited to 'packages/website') diff --git a/packages/website/ts/blockchain.ts b/packages/website/ts/blockchain.ts index 868ffad03..1003cbd06 100644 --- a/packages/website/ts/blockchain.ts +++ b/packages/website/ts/blockchain.ts @@ -682,7 +682,6 @@ export class Blockchain { // Note: it's not entirely clear from the documentation which // errors will be thrown by `watch`. For now, let's log the error // to rollbar and stop watching when one occurs - // tslint:disable-next-line:no-floating-promises errorReporter.report(err); // fire and forget return; } else { diff --git a/packages/website/ts/types.ts b/packages/website/ts/types.ts index c2a0f9640..a473e50c3 100644 --- a/packages/website/ts/types.ts +++ b/packages/website/ts/types.ts @@ -247,6 +247,7 @@ export enum Environments { DOGFOOD = 'DOGFOOD', STAGING = 'STAGING', PRODUCTION = 'PRODUCTION', + UNKNOWN = 'UNKNOWN', } export type ContractInstance = any; // TODO: add type definition for Contract diff --git a/packages/website/ts/utils/configs.ts b/packages/website/ts/utils/configs.ts index 9652a0925..a1c64f9cb 100644 --- a/packages/website/ts/utils/configs.ts +++ b/packages/website/ts/utils/configs.ts @@ -14,7 +14,7 @@ export const configs = { DEFAULT_TRACKED_TOKEN_SYMBOLS: ['WETH', 'ZRX'], DOMAIN_STAGING: 'staging-0xproject.s3-website-us-east-1.amazonaws.com', DOMAIN_DOGFOOD: 'dogfood.0xproject.com', - DOMAIN_DEVELOPMENT: '0xproject.localhost:3572', + DOMAINS_DEVELOPMENT: ['0xproject.localhost:3572', 'localhost:3572', '127.0.0.1'], DOMAIN_PRODUCTION: '0xproject.com', GOOGLE_ANALYTICS_ID: 'UA-98720122-1', LAST_LOCAL_STORAGE_FILL_CLEARANCE_DATE: '2017-11-22', diff --git a/packages/website/ts/utils/error_reporter.ts b/packages/website/ts/utils/error_reporter.ts index d38269d92..6008fffed 100644 --- a/packages/website/ts/utils/error_reporter.ts +++ b/packages/website/ts/utils/error_reporter.ts @@ -1,5 +1,4 @@ import { logUtils } from '@0xproject/utils'; -import { Environments } from 'ts/types'; import { configs } from 'ts/utils/configs'; import { constants } from 'ts/utils/constants'; import { utils } from 'ts/utils/utils'; @@ -42,7 +41,7 @@ const rollbar = Rollbar.init(rollbarConfig); export const errorReporter = { report(err: Error): void { - if (utils.getEnvironment() === Environments.DEVELOPMENT) { + if (utils.isDevelopment()) { return; // Let's not log development errors to rollbar } rollbar.error(err, (rollbarErr: Error) => { diff --git a/packages/website/ts/utils/utils.ts b/packages/website/ts/utils/utils.ts index e8152af87..77b0846a9 100644 --- a/packages/website/ts/utils/utils.ts +++ b/packages/website/ts/utils/utils.ts @@ -175,18 +175,6 @@ export const utils = { _.includes(errMsg, ledgerDenialErrMsg); return isUserDeniedErrMsg; }, - getCurrentEnvironment(): string { - switch (location.host) { - case configs.DOMAIN_DEVELOPMENT: - return 'development'; - case configs.DOMAIN_STAGING: - return 'staging'; - case configs.DOMAIN_PRODUCTION: - return 'production'; - default: - return 'production'; - } - }, getAddressBeginAndEnd(address: string): string { const truncatedAddress = `${address.substring(0, 6)}...${address.substr(-4)}`; // 0x3d5a...b287 return truncatedAddress; @@ -347,10 +335,7 @@ export const utils = { return utils.isDogfood() ? configs.BACKEND_BASE_STAGING_URL : configs.BACKEND_BASE_PROD_URL; }, isDevelopment(): boolean { - return _.includes( - ['https://0xproject.localhost:3572', 'https://localhost:3572', 'https://127.0.0.1'], - window.location.origin, - ); + return _.includes(configs.DOMAINS_DEVELOPMENT, window.location.origin); }, isStaging(): boolean { return _.includes(window.location.href, configs.DOMAIN_STAGING); @@ -377,7 +362,7 @@ export const utils = { if (utils.isProduction()) { return Environments.PRODUCTION; } - return undefined; + return Environments.UNKNOWN; }, shouldShowJobsPage(): boolean { return this.isDevelopment() || this.isStaging() || this.isDogfood(); @@ -405,21 +390,26 @@ export const utils = { const unitAmount = Web3Wrapper.toUnitAmount(amount, decimals); // if the unit amount is less than 1, show the natural number of decimal places with a max of 4 // if the unit amount is greater than or equal to 1, show only 2 decimal places - const precision = unitAmount.lt(1) - ? Math.min(constants.TOKEN_AMOUNT_DISPLAY_PRECISION, unitAmount.decimalPlaces()) - : 2; + const lessThanOnePrecision = Math.min(constants.TOKEN_AMOUNT_DISPLAY_PRECISION, unitAmount.decimalPlaces()); + const greaterThanOnePrecision = 2; + const precision = unitAmount.lt(1) ? lessThanOnePrecision : greaterThanOnePrecision; const format = `0,0.${_.repeat('0', precision)}`; const formattedAmount = numeral(unitAmount).format(format); if (_.isNaN(formattedAmount)) { // https://github.com/adamwdraper/Numeral-js/issues/596 - return format; + return '0'; } return formattedAmount; }, getUsdValueFormattedAmount(amount: BigNumber, decimals: number, price: BigNumber): string { const unitAmount = Web3Wrapper.toUnitAmount(amount, decimals); const value = unitAmount.mul(price); - return numeral(value).format(constants.NUMERAL_USD_FORMAT); + const formattedAmount = numeral(value).format(constants.NUMERAL_USD_FORMAT); + if (_.isNaN(formattedAmount)) { + // https://github.com/adamwdraper/Numeral-js/issues/596 + return numeral(new BigNumber(0)).format(constants.NUMERAL_USD_FORMAT); + } + return formattedAmount; }, openUrl(url: string): void { window.open(url, '_blank'); @@ -500,4 +490,4 @@ export const utils = { const result = `/images/token_icons/${symbol}.png`; return result; }, -}; // tslint:disable:max-file-line-count +}; -- cgit v1.2.3 From 65af78c85d7872891c0bffeac76687a72a61dd59 Mon Sep 17 00:00:00 2001 From: fragosti Date: Thu, 12 Jul 2018 18:20:46 -0700 Subject: Fix indentify typo --- packages/website/ts/components/forms/subscribe_form.tsx | 2 +- packages/website/ts/utils/analytics.ts | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'packages/website') diff --git a/packages/website/ts/components/forms/subscribe_form.tsx b/packages/website/ts/components/forms/subscribe_form.tsx index ef19af644..761db7517 100644 --- a/packages/website/ts/components/forms/subscribe_form.tsx +++ b/packages/website/ts/components/forms/subscribe_form.tsx @@ -114,7 +114,7 @@ export class SubscribeForm extends React.Component): void; resetIdentity(): void; addUserProperties(properties: ObjectMap): void; @@ -30,8 +30,8 @@ export class Analytics { } // tslint:disable:no-floating-promises // HeapAnalytics Wrappers - public indentify(id: string, idType: string): void { - this._heapLoadedGuardAsync(() => this._heap.indentify(id, idType)); + public identify(id: string, idType: string): void { + this._heapLoadedGuardAsync(() => this._heap.identify(id, idType)); } public track(eventName: string, eventProperties?: ObjectMap): void { this._heapLoadedGuardAsync(() => this._heap.track(eventName, eventProperties)); -- cgit v1.2.3 From ee54438e92f191637ecb0d36e9d79e707d1c976c Mon Sep 17 00:00:00 2001 From: fragosti Date: Thu, 12 Jul 2018 18:30:01 -0700 Subject: Fix logging typo --- packages/website/ts/components/onboarding/portal_onboarding_flow.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'packages/website') diff --git a/packages/website/ts/components/onboarding/portal_onboarding_flow.tsx b/packages/website/ts/components/onboarding/portal_onboarding_flow.tsx index 94a6338ee..a51170735 100644 --- a/packages/website/ts/components/onboarding/portal_onboarding_flow.tsx +++ b/packages/website/ts/components/onboarding/portal_onboarding_flow.tsx @@ -236,7 +236,7 @@ class PlainPortalOnboardingFlow extends React.Component Date: Fri, 13 Jul 2018 12:42:01 +0200 Subject: -fetch'; --- packages/website/package.json | 1 - packages/website/ts/blockchain.ts | 14 ++++---------- packages/website/ts/components/order_json.tsx | 4 ++-- packages/website/ts/components/token_balances.tsx | 4 ++-- packages/website/ts/index.tsx | 1 - packages/website/ts/utils/doc_utils.ts | 6 +++--- packages/website/ts/utils/fetch_utils.ts | 6 +++--- 7 files changed, 14 insertions(+), 22 deletions(-) (limited to 'packages/website') diff --git a/packages/website/package.json b/packages/website/package.json index b5b4b6119..2d054693b 100644 --- a/packages/website/package.json +++ b/packages/website/package.json @@ -63,7 +63,6 @@ "thenby": "^1.2.3", "truffle-contract": "2.0.1", "web3-provider-engine": "14.0.6", - "whatwg-fetch": "^2.0.3", "xml-js": "^1.6.4" }, "devDependencies": { diff --git a/packages/website/ts/blockchain.ts b/packages/website/ts/blockchain.ts index 0e6698318..31d8ba2d6 100644 --- a/packages/website/ts/blockchain.ts +++ b/packages/website/ts/blockchain.ts @@ -15,6 +15,7 @@ import { ledgerEthereumBrowserClientFactoryAsync, LedgerSubprovider, RedundantSubprovider, + RPCSubprovider, SignerSubprovider, Subprovider, } from '@0xproject/subproviders'; @@ -62,7 +63,6 @@ import { errorReporter } from 'ts/utils/error_reporter'; import { utils } from 'ts/utils/utils'; import ProviderEngine = require('web3-provider-engine'); import FilterSubprovider = require('web3-provider-engine/subproviders/filters'); -import RpcSubprovider = require('web3-provider-engine/subproviders/rpc'); import * as MintableArtifacts from '../contracts/Mintable.json'; @@ -157,9 +157,7 @@ export class Blockchain { provider.addProvider(ledgerSubprovider); provider.addProvider(new FilterSubprovider()); const rpcSubproviders = _.map(configs.PUBLIC_NODE_URLS_BY_NETWORK_ID[networkIdIfExists], publicNodeUrl => { - return new RpcSubprovider({ - rpcUrl: publicNodeUrl, - }); + return new RPCSubprovider(publicNodeUrl); }); provider.addProvider(new RedundantSubprovider(rpcSubproviders as Subprovider[])); provider.start(); @@ -171,9 +169,7 @@ export class Blockchain { provider.addProvider(new SignerSubprovider(injectedWeb3.currentProvider)); provider.addProvider(new FilterSubprovider()); const rpcSubproviders = _.map(publicNodeUrlsIfExistsForNetworkId, publicNodeUrl => { - return new RpcSubprovider({ - rpcUrl: publicNodeUrl, - }); + return new RPCSubprovider(publicNodeUrl); }); provider.addProvider(new RedundantSubprovider(rpcSubproviders as Subprovider[])); provider.start(); @@ -189,9 +185,7 @@ export class Blockchain { provider.addProvider(new FilterSubprovider()); const networkId = constants.NETWORK_ID_MAINNET; const rpcSubproviders = _.map(configs.PUBLIC_NODE_URLS_BY_NETWORK_ID[networkId], publicNodeUrl => { - return new RpcSubprovider({ - rpcUrl: publicNodeUrl, - }); + return new RPCSubprovider(publicNodeUrl); }); provider.addProvider(new RedundantSubprovider(rpcSubproviders as Subprovider[])); provider.start(); diff --git a/packages/website/ts/components/order_json.tsx b/packages/website/ts/components/order_json.tsx index 35188c024..7a732de6a 100644 --- a/packages/website/ts/components/order_json.tsx +++ b/packages/website/ts/components/order_json.tsx @@ -1,5 +1,5 @@ import { ECSignature } from '@0xproject/types'; -import { BigNumber, logUtils } from '@0xproject/utils'; +import { BigNumber, fetchAsync, logUtils } from '@0xproject/utils'; import * as _ from 'lodash'; import Paper from 'material-ui/Paper'; import TextField from 'material-ui/TextField'; @@ -148,7 +148,7 @@ You can see and fill it here: ${this.state.shareLink}`); const bitlyRequestUrl = `${constants.URL_BITLY_API}/v3/shorten?access_token=${ configs.BITLY_ACCESS_TOKEN }&longUrl=${longUrl}`; - const response = await fetch(bitlyRequestUrl); + const response = await fetchAsync(bitlyRequestUrl); const responseBody = await response.text(); const bodyObj = JSON.parse(responseBody); if (response.status !== 200 || bodyObj.status_code !== 200) { diff --git a/packages/website/ts/components/token_balances.tsx b/packages/website/ts/components/token_balances.tsx index 3fae83c00..1f2dfccb0 100644 --- a/packages/website/ts/components/token_balances.tsx +++ b/packages/website/ts/components/token_balances.tsx @@ -5,7 +5,7 @@ import { Styles, utils as sharedUtils, } from '@0xproject/react-shared'; -import { BigNumber, errorUtils, logUtils } from '@0xproject/utils'; +import { BigNumber, errorUtils, fetchAsync, logUtils } from '@0xproject/utils'; import { Web3Wrapper } from '@0xproject/web3-wrapper'; import * as _ from 'lodash'; import Dialog from 'material-ui/Dialog'; @@ -548,7 +548,7 @@ export class TokenBalances extends React.Component { - const response = await fetch(s3DocJsonRoot); + const response = await fetchAsync(s3DocJsonRoot); if (response.status !== 200) { // TODO: Show the user an error message when the docs fail to load const errMsg = await response.text(); @@ -73,7 +73,7 @@ export const docUtils = { }, async getJSONDocFileAsync(filePath: string, s3DocJsonRoot: string): Promise { const endpoint = `${s3DocJsonRoot}/${filePath}`; - const response = await fetch(endpoint); + const response = await fetchAsync(endpoint); if (response.status !== 200) { // TODO: Show the user an error message when the docs fail to load const errMsg = await response.text(); diff --git a/packages/website/ts/utils/fetch_utils.ts b/packages/website/ts/utils/fetch_utils.ts index 513f7e479..f159e3180 100644 --- a/packages/website/ts/utils/fetch_utils.ts +++ b/packages/website/ts/utils/fetch_utils.ts @@ -1,4 +1,4 @@ -import { logUtils } from '@0xproject/utils'; +import { fetchAsync, logUtils } from '@0xproject/utils'; import * as _ from 'lodash'; import * as queryString from 'query-string'; @@ -19,14 +19,14 @@ export const fetchUtils = { async requestAsync(baseUrl: string, path: string, queryParams?: object): Promise { const query = queryStringFromQueryParams(queryParams); const url = `${baseUrl}${path}${query}`; - const response = await fetch(url); + const response = await fetchAsync(url); logErrorIfPresent(response, url); const result = await response.json(); return result; }, async postAsync(baseUrl: string, path: string, body: object): Promise { const url = `${baseUrl}${path}`; - const response = await fetch(url, { + const response = await fetchAsync(url, { method: 'POST', headers: { 'Content-Type': 'application/json', -- cgit v1.2.3 From 512502ca0873a290accb53777ca9d93f8d28e84b Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Fri, 13 Jul 2018 14:26:02 +0200 Subject: Export Web3ProviderEngine from subproviders package --- packages/website/ts/blockchain.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'packages/website') diff --git a/packages/website/ts/blockchain.ts b/packages/website/ts/blockchain.ts index 31d8ba2d6..099171c45 100644 --- a/packages/website/ts/blockchain.ts +++ b/packages/website/ts/blockchain.ts @@ -18,6 +18,7 @@ import { RPCSubprovider, SignerSubprovider, Subprovider, + Web3ProviderEngine, } from '@0xproject/subproviders'; import { BlockParam, @@ -61,7 +62,6 @@ import { configs } from 'ts/utils/configs'; import { constants } from 'ts/utils/constants'; import { errorReporter } from 'ts/utils/error_reporter'; import { utils } from 'ts/utils/utils'; -import ProviderEngine = require('web3-provider-engine'); import FilterSubprovider = require('web3-provider-engine/subproviders/filters'); import * as MintableArtifacts from '../contracts/Mintable.json'; @@ -148,7 +148,7 @@ export class Blockchain { if (!isU2FSupported) { throw new Error('Cannot update providerType to LEDGER without U2F support'); } - const provider = new ProviderEngine(); + const provider = new Web3ProviderEngine(); const ledgerWalletConfigs = { networkId: networkIdIfExists, ledgerEthereumClientFactoryAsync: ledgerEthereumBrowserClientFactoryAsync, @@ -165,7 +165,7 @@ export class Blockchain { } else if (doesInjectedWeb3Exist && isPublicNodeAvailableForNetworkId) { // We catch all requests involving a users account and send it to the injectedWeb3 // instance. All other requests go to the public hosted node. - const provider = new ProviderEngine(); + const provider = new Web3ProviderEngine(); provider.addProvider(new SignerSubprovider(injectedWeb3.currentProvider)); provider.addProvider(new FilterSubprovider()); const rpcSubproviders = _.map(publicNodeUrlsIfExistsForNetworkId, publicNodeUrl => { @@ -181,7 +181,7 @@ export class Blockchain { // If no injectedWeb3 instance, all requests fallback to our public hosted mainnet/testnet node // We do this so that users can still browse the 0x Portal DApp even if they do not have web3 // injected into their browser. - const provider = new ProviderEngine(); + const provider = new Web3ProviderEngine(); provider.addProvider(new FilterSubprovider()); const networkId = constants.NETWORK_ID_MAINNET; const rpcSubproviders = _.map(configs.PUBLIC_NODE_URLS_BY_NETWORK_ID[networkId], publicNodeUrl => { -- cgit v1.2.3 From de1029d5ef7f069a2215557e901f3230f6da98fa Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Fri, 13 Jul 2018 18:51:21 +0200 Subject: Fix linter issues --- packages/website/ts/blockchain.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'packages/website') diff --git a/packages/website/ts/blockchain.ts b/packages/website/ts/blockchain.ts index 099171c45..805b48856 100644 --- a/packages/website/ts/blockchain.ts +++ b/packages/website/ts/blockchain.ts @@ -17,7 +17,6 @@ import { RedundantSubprovider, RPCSubprovider, SignerSubprovider, - Subprovider, Web3ProviderEngine, } from '@0xproject/subproviders'; import { @@ -159,7 +158,7 @@ export class Blockchain { const rpcSubproviders = _.map(configs.PUBLIC_NODE_URLS_BY_NETWORK_ID[networkIdIfExists], publicNodeUrl => { return new RPCSubprovider(publicNodeUrl); }); - provider.addProvider(new RedundantSubprovider(rpcSubproviders as Subprovider[])); + provider.addProvider(new RedundantSubprovider(rpcSubproviders)); provider.start(); return [provider, ledgerSubprovider]; } else if (doesInjectedWeb3Exist && isPublicNodeAvailableForNetworkId) { @@ -171,7 +170,7 @@ export class Blockchain { const rpcSubproviders = _.map(publicNodeUrlsIfExistsForNetworkId, publicNodeUrl => { return new RPCSubprovider(publicNodeUrl); }); - provider.addProvider(new RedundantSubprovider(rpcSubproviders as Subprovider[])); + provider.addProvider(new RedundantSubprovider(rpcSubproviders)); provider.start(); return [provider, undefined]; } else if (doesInjectedWeb3Exist) { @@ -187,7 +186,7 @@ export class Blockchain { const rpcSubproviders = _.map(configs.PUBLIC_NODE_URLS_BY_NETWORK_ID[networkId], publicNodeUrl => { return new RPCSubprovider(publicNodeUrl); }); - provider.addProvider(new RedundantSubprovider(rpcSubproviders as Subprovider[])); + provider.addProvider(new RedundantSubprovider(rpcSubproviders)); provider.start(); return [provider, undefined]; } -- cgit v1.2.3 From c5fcdd06579b67b5b129749474acd9a4d1d4db65 Mon Sep 17 00:00:00 2001 From: fragosti Date: Fri, 13 Jul 2018 11:10:06 -0700 Subject: Move format to helper function --- packages/website/ts/utils/utils.ts | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) (limited to 'packages/website') diff --git a/packages/website/ts/utils/utils.ts b/packages/website/ts/utils/utils.ts index 77b0846a9..f2baeb849 100644 --- a/packages/website/ts/utils/utils.ts +++ b/packages/website/ts/utils/utils.ts @@ -386,6 +386,14 @@ export const utils = { getFormattedAmountFromToken(token: Token, tokenState: TokenState): string { return utils.getFormattedAmount(tokenState.balance, token.decimals); }, + format(value: BigNumber, format: string): string { + const formattedAmount = numeral(value).format(format); + if (_.isNaN(formattedAmount)) { + // https://github.com/adamwdraper/Numeral-js/issues/596 + return numeral(new BigNumber(0)).format(format); + } + return formattedAmount; + }, getFormattedAmount(amount: BigNumber, decimals: number): string { const unitAmount = Web3Wrapper.toUnitAmount(amount, decimals); // if the unit amount is less than 1, show the natural number of decimal places with a max of 4 @@ -394,22 +402,12 @@ export const utils = { const greaterThanOnePrecision = 2; const precision = unitAmount.lt(1) ? lessThanOnePrecision : greaterThanOnePrecision; const format = `0,0.${_.repeat('0', precision)}`; - const formattedAmount = numeral(unitAmount).format(format); - if (_.isNaN(formattedAmount)) { - // https://github.com/adamwdraper/Numeral-js/issues/596 - return '0'; - } - return formattedAmount; + return utils.format(unitAmount, format); }, getUsdValueFormattedAmount(amount: BigNumber, decimals: number, price: BigNumber): string { const unitAmount = Web3Wrapper.toUnitAmount(amount, decimals); const value = unitAmount.mul(price); - const formattedAmount = numeral(value).format(constants.NUMERAL_USD_FORMAT); - if (_.isNaN(formattedAmount)) { - // https://github.com/adamwdraper/Numeral-js/issues/596 - return numeral(new BigNumber(0)).format(constants.NUMERAL_USD_FORMAT); - } - return formattedAmount; + return utils.format(value, constants.NUMERAL_USD_FORMAT); }, openUrl(url: string): void { window.open(url, '_blank'); -- cgit v1.2.3 From 5e4b1eed3067208fecdd5c10f1c1cc16f6b4647b Mon Sep 17 00:00:00 2001 From: fragosti Date: Fri, 13 Jul 2018 14:09:34 -0700 Subject: Move update onboarding step tracking to onboarding flow code --- packages/website/ts/components/onboarding/portal_onboarding_flow.tsx | 3 +++ packages/website/ts/redux/analyticsMiddleware.ts | 5 ----- 2 files changed, 3 insertions(+), 5 deletions(-) (limited to 'packages/website') diff --git a/packages/website/ts/components/onboarding/portal_onboarding_flow.tsx b/packages/website/ts/components/onboarding/portal_onboarding_flow.tsx index a51170735..f395674a1 100644 --- a/packages/website/ts/components/onboarding/portal_onboarding_flow.tsx +++ b/packages/website/ts/components/onboarding/portal_onboarding_flow.tsx @@ -233,6 +233,9 @@ class PlainPortalOnboardingFlow extends React.Component next => action => { }); } break; - case ActionTypes.UpdatePortalOnboardingStep: - analytics.track('Update Onboarding Step', { - stepIndex: nextState.portalOnboardingStep, - }); - break; default: break; } -- cgit v1.2.3 From 0c04d490bb3217d4f2c7e2ba07e48d12f73e5c24 Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Mon, 16 Jul 2018 17:48:24 -0700 Subject: Fix ocean link --- packages/website/ts/utils/constants.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'packages/website') diff --git a/packages/website/ts/utils/constants.ts b/packages/website/ts/utils/constants.ts index e43f541bf..20441cd75 100644 --- a/packages/website/ts/utils/constants.ts +++ b/packages/website/ts/utils/constants.ts @@ -58,7 +58,7 @@ export const constants = { PROJECT_URL_MAKER: 'https://makerdao.com', PROJECT_URL_ARAGON: 'https://aragon.one', PROJECT_URL_BLOCKNET: 'https://blocknet.co', - PROJECT_URL_0CEAN: 'http://the0cean.com', + PROJECT_URL_0CEAN: 'https://theocean.trade', PROJECT_URL_IMTOKEN: 'https://tokenlon.token.im/', PROJECT_URL_AUGUR: 'https://augur.net', PROJECT_URL_AUCTUS: 'https://auctus.org', -- cgit v1.2.3 From a9038f2afc974cecf567a9aef50267d29a995e02 Mon Sep 17 00:00:00 2001 From: fragosti Date: Tue, 17 Jul 2018 01:16:29 -0700 Subject: Add chris to website --- packages/website/ts/pages/about/about.tsx | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'packages/website') diff --git a/packages/website/ts/pages/about/about.tsx b/packages/website/ts/pages/about/about.tsx index be4a67cb3..33581c938 100644 --- a/packages/website/ts/pages/about/about.tsx +++ b/packages/website/ts/pages/about/about.tsx @@ -181,14 +181,14 @@ const teamRow6: ProfileInfo[] = [ image: 'images/team/peter.jpg', linkedIn: 'https://www.linkedin.com/in/peter-z-7b9595163/', }, - // { - // name: 'Chris Kalani', - // title: 'Director of Design', - // description: `Previously founded Wake (acquired by InVision). Early Facebook product designer.`, - // image: 'images/team/chris.png', - // linkedIn: 'https://www.linkedin.com/in/chriskalani/', - // github: 'https://github.com/chriskalani', - // }, + { + name: 'Chris Kalani', + title: 'Director of Design', + description: `Previously founded Wake (acquired by InVision). Early Facebook product designer.`, + image: 'images/team/chris.png', + linkedIn: 'https://www.linkedin.com/in/chriskalani/', + github: 'https://github.com/chriskalani', + }, ]; const advisors: ProfileInfo[] = [ -- cgit v1.2.3 From edcdc9b1b903158cc61529853d7e9028ecbc266a Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Tue, 17 Jul 2018 12:58:42 +0200 Subject: Upgrade tslint to the newest version --- packages/website/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'packages/website') diff --git a/packages/website/package.json b/packages/website/package.json index ef314ba2d..80e49cd70 100644 --- a/packages/website/package.json +++ b/packages/website/package.json @@ -97,7 +97,7 @@ "shx": "^0.2.2", "source-map-loader": "^0.1.6", "style-loader": "0.13.x", - "tslint": "5.8.0", + "tslint": "5.11.0", "tslint-config-0xproject": "^0.0.2", "typescript": "2.7.1", "uglifyjs-webpack-plugin": "^1.2.5", -- cgit v1.2.3 From bf8ac3b9e6ee59f267f7850418febfe84dedceb8 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Tue, 17 Jul 2018 12:59:02 +0200 Subject: Fix tslint issues --- packages/website/ts/blockchain.ts | 10 +++++++--- packages/website/ts/blockchain_watcher.ts | 6 +++--- .../ts/components/dialogs/u2f_not_supported_dialog.tsx | 4 ++-- .../ts/components/eth_weth_conversion_button.tsx | 2 +- packages/website/ts/components/fill_warning_dialog.tsx | 6 +++--- .../ts/components/generate_order/asset_picker.tsx | 2 +- .../website/ts/components/inputs/allowance_toggle.tsx | 2 +- .../ts/components/inputs/balance_bounded_input.tsx | 4 ++-- .../website/ts/components/inputs/expiration_input.tsx | 2 +- packages/website/ts/components/order_json.tsx | 2 +- packages/website/ts/components/portal/portal.tsx | 4 ++-- packages/website/ts/components/ui/menu_item.tsx | 2 +- packages/website/ts/components/ui/overlay.tsx | 2 +- packages/website/ts/components/ui/simple_menu.tsx | 2 +- packages/website/ts/components/wallet/wallet.tsx | 2 +- packages/website/ts/local_storage/local_storage.ts | 8 ++++---- .../website/ts/local_storage/tracked_token_storage.ts | 4 ++-- .../website/ts/local_storage/trade_history_storage.tsx | 18 +++++++++--------- packages/website/ts/pages/jobs/jobs.tsx | 2 +- packages/website/ts/pages/landing/landing.tsx | 2 +- packages/website/ts/redux/dispatcher.ts | 2 +- packages/website/ts/utils/utils.ts | 10 +++++----- 22 files changed, 51 insertions(+), 47 deletions(-) (limited to 'packages/website') diff --git a/packages/website/ts/blockchain.ts b/packages/website/ts/blockchain.ts index e8168d975..88461f8a9 100644 --- a/packages/website/ts/blockchain.ts +++ b/packages/website/ts/blockchain.ts @@ -83,11 +83,11 @@ export class Blockchain { public networkId: number; public nodeVersion: string; private _contractWrappers: ContractWrappers; - private _dispatcher: Dispatcher; + private readonly _dispatcher: Dispatcher; private _web3Wrapper?: Web3Wrapper; private _blockchainWatcher?: BlockchainWatcher; private _injectedProviderObservable?: InjectedProviderObservable; - private _injectedProviderUpdateHandler: (update: InjectedProviderUpdate) => Promise; + private readonly _injectedProviderUpdateHandler: (update: InjectedProviderUpdate) => Promise; private _userAddressIfExists: string; private _ledgerSubprovider: LedgerSubprovider; private _defaultGasPrice: BigNumber; @@ -125,7 +125,11 @@ export class Blockchain { let networkIdIfExists: number; if (!_.isUndefined(injectedWeb3IfExists)) { try { - networkIdIfExists = _.parseInt(await promisify(injectedWeb3IfExists.version.getNetwork)()); + networkIdIfExists = _.parseInt( + await promisify( + injectedWeb3IfExists.version.getNetwork.bind(injectedWeb3IfExists.version), + )(), + ); } catch (err) { // Ignore error and proceed with networkId undefined } diff --git a/packages/website/ts/blockchain_watcher.ts b/packages/website/ts/blockchain_watcher.ts index 4b23aa98a..39ed8b08b 100644 --- a/packages/website/ts/blockchain_watcher.ts +++ b/packages/website/ts/blockchain_watcher.ts @@ -4,9 +4,9 @@ import * as _ from 'lodash'; import { Dispatcher } from 'ts/redux/dispatcher'; export class BlockchainWatcher { - private _dispatcher: Dispatcher; - private _web3Wrapper: Web3Wrapper; - private _shouldPollUserAddress: boolean; + private readonly _dispatcher: Dispatcher; + private readonly _web3Wrapper: Web3Wrapper; + private readonly _shouldPollUserAddress: boolean; private _watchBalanceIntervalId: NodeJS.Timer; private _prevUserEtherBalanceInWei?: BigNumber; private _prevUserAddressIfExists: string; diff --git a/packages/website/ts/components/dialogs/u2f_not_supported_dialog.tsx b/packages/website/ts/components/dialogs/u2f_not_supported_dialog.tsx index ce86df856..3ebab03ef 100644 --- a/packages/website/ts/components/dialogs/u2f_not_supported_dialog.tsx +++ b/packages/website/ts/components/dialogs/u2f_not_supported_dialog.tsx @@ -14,9 +14,9 @@ export const U2fNotSupportedDialog = (props: U2fNotSupportedDialogProps) => { ]} + actions={[]} open={props.isOpen} - onRequestClose={props.onToggleDialog.bind(this)} + onRequestClose={props.onToggleDialog} autoScrollBodyContent={true} >
diff --git a/packages/website/ts/components/eth_weth_conversion_button.tsx b/packages/website/ts/components/eth_weth_conversion_button.tsx index d547a4e6a..b0091a1c1 100644 --- a/packages/website/ts/components/eth_weth_conversion_button.tsx +++ b/packages/website/ts/components/eth_weth_conversion_button.tsx @@ -37,7 +37,7 @@ export class EthWethConversionButton extends React.Component< > { public static defaultProps: Partial = { isDisabled: false, - onConversionSuccessful: _.noop, + onConversionSuccessful: _.noop.bind(_), }; public constructor(props: EthWethConversionButtonProps) { super(props); diff --git a/packages/website/ts/components/fill_warning_dialog.tsx b/packages/website/ts/components/fill_warning_dialog.tsx index 83095b1d3..45c492221 100644 --- a/packages/website/ts/components/fill_warning_dialog.tsx +++ b/packages/website/ts/components/fill_warning_dialog.tsx @@ -18,16 +18,16 @@ export const FillWarningDialog = (props: FillWarningDialogProps) => { props.onToggleDialog(didCancel)} // tslint:disable-line:jsx-no-lambda />, props.onToggleDialog(!didCancel)} // tslint:disable-line:jsx-no-lambda />, ]} open={props.isOpen} - onRequestClose={props.onToggleDialog.bind(this)} + onRequestClose={() => props.onToggleDialog(didCancel)} // tslint:disable-line:jsx-no-lambda autoScrollBodyContent={true} modal={true} > diff --git a/packages/website/ts/components/generate_order/asset_picker.tsx b/packages/website/ts/components/generate_order/asset_picker.tsx index 5eada37b6..2dca3483f 100644 --- a/packages/website/ts/components/generate_order/asset_picker.tsx +++ b/packages/website/ts/components/generate_order/asset_picker.tsx @@ -46,7 +46,7 @@ export class AssetPicker extends React.Component = { tokenVisibility: TokenVisibility.ALL, }; - private _dialogConfigsByAssetView: { [assetView: string]: DialogConfigs }; + private readonly _dialogConfigsByAssetView: { [assetView: string]: DialogConfigs }; constructor(props: AssetPickerProps) { super(props); this.state = { diff --git a/packages/website/ts/components/inputs/allowance_toggle.tsx b/packages/website/ts/components/inputs/allowance_toggle.tsx index 297617bef..05dce134a 100644 --- a/packages/website/ts/components/inputs/allowance_toggle.tsx +++ b/packages/website/ts/components/inputs/allowance_toggle.tsx @@ -57,7 +57,7 @@ const styles: Styles = { export class AllowanceToggle extends React.Component { public static defaultProps = { - onErrorOccurred: _.noop, + onErrorOccurred: _.noop.bind(_), isDisabled: false, }; constructor(props: AllowanceToggleProps) { diff --git a/packages/website/ts/components/inputs/balance_bounded_input.tsx b/packages/website/ts/components/inputs/balance_bounded_input.tsx index f23beb436..eb01e3ea6 100644 --- a/packages/website/ts/components/inputs/balance_bounded_input.tsx +++ b/packages/website/ts/components/inputs/balance_bounded_input.tsx @@ -35,7 +35,7 @@ export class BalanceBoundedInput extends React.Component void = _.noop): void { + private _setAmountState(amount: string, balance: BigNumber, callback: () => void = _.noop.bind(_)): void { const errorMsg = this._validate(amount, balance); this.props.onErrorMsgChange(errorMsg); this.setState( diff --git a/packages/website/ts/components/inputs/expiration_input.tsx b/packages/website/ts/components/inputs/expiration_input.tsx index 79dd2f568..5417ce715 100644 --- a/packages/website/ts/components/inputs/expiration_input.tsx +++ b/packages/website/ts/components/inputs/expiration_input.tsx @@ -17,7 +17,7 @@ interface ExpirationInputState { } export class ExpirationInput extends React.Component { - private _earliestPickableMoment: moment.Moment; + private readonly _earliestPickableMoment: moment.Moment; constructor(props: ExpirationInputProps) { super(props); // Set the earliest pickable date to today at 00:00, so users can only pick the current or later dates diff --git a/packages/website/ts/components/order_json.tsx b/packages/website/ts/components/order_json.tsx index c2606bd56..cf06f10c8 100644 --- a/packages/website/ts/components/order_json.tsx +++ b/packages/website/ts/components/order_json.tsx @@ -127,7 +127,7 @@ export class OrderJSON extends React.Component { href: this.state.shareLink, method: 'share', }, - _.noop, + _.noop.bind(_), ); } private _shareViaEmailAsync(): void { diff --git a/packages/website/ts/components/portal/portal.tsx b/packages/website/ts/components/portal/portal.tsx index ea821d038..1790a9678 100644 --- a/packages/website/ts/components/portal/portal.tsx +++ b/packages/website/ts/components/portal/portal.tsx @@ -110,8 +110,8 @@ const SIDE_PADDING = 20; export class Portal extends React.Component { private _blockchain: Blockchain; - private _sharedOrderIfExists: Order; - private _throttledScreenWidthUpdate: () => void; + private readonly _sharedOrderIfExists: Order; + private readonly _throttledScreenWidthUpdate: () => void; constructor(props: PortalProps) { super(props); this._sharedOrderIfExists = orderParser.parse(window.location.search); diff --git a/packages/website/ts/components/ui/menu_item.tsx b/packages/website/ts/components/ui/menu_item.tsx index 64c0dc49d..0cb4b387c 100644 --- a/packages/website/ts/components/ui/menu_item.tsx +++ b/packages/website/ts/components/ui/menu_item.tsx @@ -15,7 +15,7 @@ interface MenuItemState { export class MenuItem extends React.Component { public static defaultProps: Partial = { - onClick: _.noop, + onClick: _.noop.bind(_), className: '', }; public constructor(props: MenuItemProps) { diff --git a/packages/website/ts/components/ui/overlay.tsx b/packages/website/ts/components/ui/overlay.tsx index da26317de..fc7507475 100644 --- a/packages/website/ts/components/ui/overlay.tsx +++ b/packages/website/ts/components/ui/overlay.tsx @@ -26,7 +26,7 @@ export const Overlay: React.StatelessComponent = props => ( Overlay.defaultProps = { style: {}, - onClick: _.noop, + onClick: _.noop.bind(_), }; Overlay.displayName = 'Overlay'; diff --git a/packages/website/ts/components/ui/simple_menu.tsx b/packages/website/ts/components/ui/simple_menu.tsx index dcbc6946b..8a9349c6d 100644 --- a/packages/website/ts/components/ui/simple_menu.tsx +++ b/packages/website/ts/components/ui/simple_menu.tsx @@ -41,7 +41,7 @@ export const SimpleMenuItem: React.StatelessComponent = ({ {displayText} diff --git a/packages/website/ts/components/wallet/wallet.tsx b/packages/website/ts/components/wallet/wallet.tsx index e462ab3e0..40a8a23ea 100644 --- a/packages/website/ts/components/wallet/wallet.tsx +++ b/packages/website/ts/components/wallet/wallet.tsx @@ -204,7 +204,7 @@ export class Wallet extends React.Component {
); - const onClick = _.noop; + const onClick = _.noop.bind(_); const accessory = ( { diff --git a/packages/website/ts/local_storage/trade_history_storage.tsx b/packages/website/ts/local_storage/trade_history_storage.tsx index 2e2f4e64e..a9b042820 100644 --- a/packages/website/ts/local_storage/trade_history_storage.tsx +++ b/packages/website/ts/local_storage/trade_history_storage.tsx @@ -27,31 +27,31 @@ export const tradeHistoryStorage = { localStorage.setItem(FILL_CLEAR_KEY, configs.LAST_LOCAL_STORAGE_FILL_CLEARANCE_DATE); }, addFillToUser(userAddress: string, networkId: number, fill: Fill): void { - const fillsByHash = this.getUserFillsByHash(userAddress, networkId); - const fillHash = this._getFillHash(fill); + const fillsByHash = tradeHistoryStorage.getUserFillsByHash(userAddress, networkId); + const fillHash = tradeHistoryStorage._getFillHash(fill); const doesFillExist = !_.isUndefined(fillsByHash[fillHash]); if (doesFillExist) { return; // noop } fillsByHash[fillHash] = fill; const userFillsJSONString = JSON.stringify(fillsByHash); - const userFillsKey = this._getUserFillsKey(userAddress, networkId); + const userFillsKey = tradeHistoryStorage._getUserFillsKey(userAddress, networkId); localStorage.setItem(userFillsKey, userFillsJSONString); }, removeFillFromUser(userAddress: string, networkId: number, fill: Fill): void { - const fillsByHash = this.getUserFillsByHash(userAddress, networkId); - const fillHash = this._getFillHash(fill); + const fillsByHash = tradeHistoryStorage.getUserFillsByHash(userAddress, networkId); + const fillHash = tradeHistoryStorage._getFillHash(fill); const doesFillExist = !_.isUndefined(fillsByHash[fillHash]); if (!doesFillExist) { return; // noop } delete fillsByHash[fillHash]; const userFillsJSONString = JSON.stringify(fillsByHash); - const userFillsKey = this._getUserFillsKey(userAddress, networkId); + const userFillsKey = tradeHistoryStorage._getUserFillsKey(userAddress, networkId); localStorage.setItem(userFillsKey, userFillsJSONString); }, getUserFillsByHash(userAddress: string, networkId: number): { [fillHash: string]: Fill } { - const userFillsKey = this._getUserFillsKey(userAddress, networkId); + const userFillsKey = tradeHistoryStorage._getUserFillsKey(userAddress, networkId); const userFillsJSONString = localStorage.getItemIfExists(userFillsKey); if (_.isEmpty(userFillsJSONString)) { return {}; @@ -66,7 +66,7 @@ export const tradeHistoryStorage = { return userFillsByHash; }, getFillsLatestBlock(userAddress: string, networkId: number): number { - const userFillsLatestBlockKey = this._getFillsLatestBlockKey(userAddress, networkId); + const userFillsLatestBlockKey = tradeHistoryStorage._getFillsLatestBlockKey(userAddress, networkId); const blockNumberStr = localStorage.getItemIfExists(userFillsLatestBlockKey); if (_.isEmpty(blockNumberStr)) { return constants.GENESIS_ORDER_BLOCK_BY_NETWORK_ID[networkId]; @@ -75,7 +75,7 @@ export const tradeHistoryStorage = { return blockNumber; }, setFillsLatestBlock(userAddress: string, networkId: number, blockNumber: number): void { - const userFillsLatestBlockKey = this._getFillsLatestBlockKey(userAddress, networkId); + const userFillsLatestBlockKey = tradeHistoryStorage._getFillsLatestBlockKey(userAddress, networkId); localStorage.setItem(userFillsLatestBlockKey, `${blockNumber}`); }, _getUserFillsKey(userAddress: string, networkId: number): string { diff --git a/packages/website/ts/pages/jobs/jobs.tsx b/packages/website/ts/pages/jobs/jobs.tsx index 314669ee9..38cefa832 100644 --- a/packages/website/ts/pages/jobs/jobs.tsx +++ b/packages/website/ts/pages/jobs/jobs.tsx @@ -33,7 +33,7 @@ export interface JobsState {} export class Jobs extends React.Component { // TODO: consolidate this small screen scaffolding into one place (its being used in portal and docs as well) - private _throttledScreenWidthUpdate: () => void; + private readonly _throttledScreenWidthUpdate: () => void; public constructor(props: JobsProps) { super(props); this._throttledScreenWidthUpdate = _.throttle(this._updateScreenWidth.bind(this), THROTTLE_TIMEOUT); diff --git a/packages/website/ts/pages/landing/landing.tsx b/packages/website/ts/pages/landing/landing.tsx index b2cf4d979..2a51ee3c0 100644 --- a/packages/website/ts/pages/landing/landing.tsx +++ b/packages/website/ts/pages/landing/landing.tsx @@ -171,7 +171,7 @@ interface LandingState { } export class Landing extends React.Component { - private _throttledScreenWidthUpdate: () => void; + private readonly _throttledScreenWidthUpdate: () => void; constructor(props: LandingProps) { super(props); this.state = { diff --git a/packages/website/ts/redux/dispatcher.ts b/packages/website/ts/redux/dispatcher.ts index e0ce43ae5..db008d319 100644 --- a/packages/website/ts/redux/dispatcher.ts +++ b/packages/website/ts/redux/dispatcher.ts @@ -17,7 +17,7 @@ import { } from 'ts/types'; export class Dispatcher { - private _dispatch: Dispatch; + private readonly _dispatch: Dispatch; constructor(dispatch: Dispatch) { this._dispatch = dispatch; } diff --git a/packages/website/ts/utils/utils.ts b/packages/website/ts/utils/utils.ts index 739bb7b66..e656d5963 100644 --- a/packages/website/ts/utils/utils.ts +++ b/packages/website/ts/utils/utils.ts @@ -59,7 +59,7 @@ export const utils = { return moment.unix(unixTimestampSec.toNumber()); }, convertToReadableDateTimeFromUnixTimestamp(unixTimestampSec: BigNumber): string { - const m = this.convertToMomentFromUnixTimestamp(unixTimestampSec); + const m = utils.convertToMomentFromUnixTimestamp(unixTimestampSec); const formattedDate: string = m.format('h:MMa MMMM D YYYY'); return formattedDate; }, @@ -299,12 +299,12 @@ export const utils = { const baseUrl = `https://${window.location.hostname}${hasPort ? `:${port}` : ''}`; return baseUrl; }, - onPageLoadPromise: new Promise((resolve, _reject) => { + onPageLoadPromise: new Promise((resolve, _reject) => { if (document.readyState === 'complete') { resolve(); return; } - window.onload = resolve; + window.onload = () => resolve(); }), getProviderType(provider: Provider): Providers | string { const constructorName = provider.constructor.name; @@ -364,7 +364,7 @@ export const utils = { return Environments.UNKNOWN; }, shouldShowJobsPage(): boolean { - return this.isDevelopment() || this.isStaging() || this.isDogfood(); + return utils.isDevelopment() || utils.isStaging() || utils.isDogfood(); }, getEthToken(tokenByAddress: TokenByAddress): Token { return utils.getTokenBySymbol(constants.ETHER_TOKEN_SYMBOL, tokenByAddress); @@ -379,7 +379,7 @@ export const utils = { }, getTrackedTokens(tokenByAddress: TokenByAddress): Token[] { const allTokens = _.values(tokenByAddress); - const trackedTokens = _.filter(allTokens, t => this.isTokenTracked(t)); + const trackedTokens = _.filter(allTokens, t => utils.isTokenTracked(t)); return trackedTokens; }, getFormattedAmountFromToken(token: Token, tokenState: TokenState): string { -- cgit v1.2.3 From 50ed7d2af26d6210f869352ed41084875d2af3d0 Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Tue, 17 Jul 2018 16:41:55 +0200 Subject: Export missing types and add to doc ref whitelist --- .../ts/containers/zero_ex_js_documentation.ts | 26 ++++++++++++++++++++++ 1 file changed, 26 insertions(+) (limited to 'packages/website') diff --git a/packages/website/ts/containers/zero_ex_js_documentation.ts b/packages/website/ts/containers/zero_ex_js_documentation.ts index bd0d1732a..9d3be56f5 100644 --- a/packages/website/ts/containers/zero_ex_js_documentation.ts +++ b/packages/website/ts/containers/zero_ex_js_documentation.ts @@ -181,6 +181,32 @@ const docsInfoConfig: DocsInfoConfig = { 'JSONRPCErrorCallback', 'LogEntryEvent', 'LogEntry', + 'ERC20AssetData', + 'ERC721AssetData', + 'AssetProxyId', + 'WETH9Events', + 'WETH9WithdrawalEventArgs', + 'WETH9ApprovalEventArgs', + 'WETH9EventArgs', + 'WETH9DepositEventArgs', + 'WETH9TransferEventArgs', + 'ERC20TokenTransferEventArgs', + 'ERC20TokenApprovalEventArgs', + 'ERC20TokenEvents', + 'ERC20TokenEventArgs', + 'ERC721TokenApprovalEventArgs', + 'ERC721TokenApprovalForAllEventArgs', + 'ERC721TokenTransferEventArgs', + 'ERC721TokenEvents', + 'ExchangeCancelUpToEventArgs', + 'ExchangeAssetProxyRegisteredEventArgs', + 'ExchangeFillEventArgs', + 'ExchangeCancelEventArgs', + 'ExchangeEventArgs', + 'ContractWrappersConfig', + 'MessagePrefixType', + 'MessagePrefixOpts', + 'OrderInfo', ], typeNameToPrefix: {}, typeNameToExternalLink: { -- cgit v1.2.3 From f99232095b3effea261b5b24bc01db4f96c416f6 Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Wed, 18 Jul 2018 15:48:09 +0200 Subject: Update package versions --- packages/website/package.json | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'packages/website') diff --git a/packages/website/package.json b/packages/website/package.json index 80e49cd70..4cefa19a9 100644 --- a/packages/website/package.json +++ b/packages/website/package.json @@ -1,6 +1,6 @@ { "name": "@0xproject/website", - "version": "0.0.38", + "version": "0.0.39", "engines": { "node": ">=6.12" }, @@ -22,14 +22,14 @@ "license": "Apache-2.0", "dependencies": { "@0xproject/contract-wrappers": "^0.0.5", - "@0xproject/order-utils": "^0.0.8", - "@0xproject/react-docs": "^0.0.15", - "@0xproject/react-shared": "^0.2.2", - "@0xproject/subproviders": "^0.10.5", + "@0xproject/order-utils": "^0.0.9", + "@0xproject/react-docs": "^0.0.16", + "@0xproject/react-shared": "^0.2.3", + "@0xproject/subproviders": "^0.10.6", "@0xproject/types": "^0.8.1", - "@0xproject/typescript-typings": "^0.4.2", - "@0xproject/utils": "^0.7.2", - "@0xproject/web3-wrapper": "^0.7.2", + "@0xproject/typescript-typings": "^0.4.3", + "@0xproject/utils": "^0.7.3", + "@0xproject/web3-wrapper": "^0.7.3", "accounting": "^0.4.1", "basscss": "^8.0.3", "blockies": "^0.0.2", -- cgit v1.2.3 From 55336f96d70d05f07725564bf6aec573dc3246c2 Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Wed, 18 Jul 2018 15:53:33 -0700 Subject: Fix broken links in sol-cov documentation --- packages/website/md/docs/sol_cov/usage.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'packages/website') diff --git a/packages/website/md/docs/sol_cov/usage.md b/packages/website/md/docs/sol_cov/usage.md index 433cfad96..c747005fb 100644 --- a/packages/website/md/docs/sol_cov/usage.md +++ b/packages/website/md/docs/sol_cov/usage.md @@ -8,7 +8,7 @@ In order to use `CoverageSubprovider` with your favorite framework you need to p ### Sol-compiler -If you are generating your artifacts with [@0xproject/sol-compiler](LINK) you can use the `SolCompilerArtifactsAdapter` we've implemented for you. +If you are generating your artifacts with [@0xproject/sol-compiler](https://0xproject.com/docs/sol-compiler) you can use the `SolCompilerArtifactsAdapter` we've implemented for you. ```typescript import { SolCompilerArtifactsAdapter } from '@0xproject/sol-cov'; @@ -19,7 +19,7 @@ const artifactsAdapter = new SolCompilerArtifactsAdapter(artifactsPath, contract ### Truffle -If your project is using [Truffle](LINK), we've written a `TruffleArtifactsAdapter`for you. +If your project is using [Truffle](https://truffleframework.com/), we've written a `TruffleArtifactsAdapter`for you. ```typescript import { TruffleArtifactAdapter } from '@0xproject/sol-cov'; -- cgit v1.2.3