diff options
-rw-r--r-- | packages/website/package.json | 2 | ||||
-rw-r--r-- | packages/website/ts/blockchain.ts | 16 | ||||
-rw-r--r-- | packages/website/ts/components/wallet/wallet.tsx | 23 | ||||
-rw-r--r-- | packages/website/ts/pages/wiki/wiki.tsx | 53 | ||||
-rw-r--r-- | packages/website/ts/types.ts | 9 | ||||
-rw-r--r-- | packages/website/ts/utils/backend_client.ts | 59 | ||||
-rw-r--r-- | yarn.lock | 13 |
7 files changed, 123 insertions, 52 deletions
diff --git a/packages/website/package.json b/packages/website/package.json index 79d4c95cc..169231fac 100644 --- a/packages/website/package.json +++ b/packages/website/package.json @@ -32,6 +32,7 @@ "lodash": "^4.17.4", "material-ui": "^0.17.1", "moment": "2.21.0", + "query-string": "^6.0.0", "react": "15.6.1", "react-copy-to-clipboard": "^4.2.3", "react-document-title": "^2.0.3", @@ -58,6 +59,7 @@ "@types/lodash": "4.14.104", "@types/material-ui": "0.18.0", "@types/node": "^8.0.53", + "@types/query-string": "^5.1.0", "@types/react": "^16.0.34", "@types/react-copy-to-clipboard": "^4.2.0", "@types/react-dom": "^16.0.3", diff --git a/packages/website/ts/blockchain.ts b/packages/website/ts/blockchain.ts index 3edc00644..e90dfa747 100644 --- a/packages/website/ts/blockchain.ts +++ b/packages/website/ts/blockchain.ts @@ -47,6 +47,7 @@ import { Token, TokenByAddress, } from 'ts/types'; +import { backendClient } from 'ts/utils/backend_client'; import { configs } from 'ts/utils/configs'; import { constants } from 'ts/utils/constants'; import { errorReporter } from 'ts/utils/error_reporter'; @@ -854,14 +855,13 @@ export class Blockchain { } } private async _updateDefaultGasPriceAsync() { - const endpoint = `${configs.BACKEND_BASE_URL}/eth_gas_station`; - const response = await fetch(endpoint); - if (response.status !== 200) { - return; // noop and we keep hard-coded default + try { + const gasInfo = await backendClient.getGasInfoAsync(); + const gasPriceInGwei = new BigNumber(gasInfo.average / 10); + const gasPriceInWei = gasPriceInGwei.mul(1000000000); + this._defaultGasPrice = gasPriceInWei; + } catch (err) { + return; } - const gasInfo = await response.json(); - const gasPriceInGwei = new BigNumber(gasInfo.average / 10); - const gasPriceInWei = gasPriceInGwei.mul(1000000000); - this._defaultGasPrice = gasPriceInWei; } } // tslint:disable:max-file-line-count diff --git a/packages/website/ts/components/wallet/wallet.tsx b/packages/website/ts/components/wallet/wallet.tsx index 8c9e3be0f..d1ae38550 100644 --- a/packages/website/ts/components/wallet/wallet.tsx +++ b/packages/website/ts/components/wallet/wallet.tsx @@ -36,7 +36,7 @@ import { TokenState, TokenStateByAddress, } from 'ts/types'; -import { configs } from 'ts/utils/configs'; +import { backendClient } from 'ts/utils/backend_client'; import { constants } from 'ts/utils/constants'; import { utils } from 'ts/utils/utils'; import { styles as walletItemStyles } from 'ts/utils/wallet_item_styles'; @@ -72,11 +72,6 @@ interface AccessoryItemConfig { allowanceToggleConfig?: AllowanceToggleConfig; } -interface WebsiteBackendPriceInfo { - price: string; - address: string; -} - const styles: Styles = { root: { width: 346, @@ -496,17 +491,15 @@ export class Wallet extends React.Component<WalletProps, WalletState> { if (_.isEmpty(tokenAddresses)) { return {}; } - const tokenAddressesQueryString = tokenAddresses.join(','); - const endpoint = `${configs.BACKEND_BASE_URL}/prices?tokens=${tokenAddressesQueryString}`; - const response = await fetch(endpoint); - if (response.status !== 200) { + try { + const websiteBackendPriceInfos = await backendClient.getPriceInfosAsync(tokenAddresses); + const addresses = _.map(websiteBackendPriceInfos, info => info.address); + const prices = _.map(websiteBackendPriceInfos, info => new BigNumber(info.price)); + const pricesByAddress = _.zipObject(addresses, prices); + return pricesByAddress; + } catch (err) { return {}; } - const websiteBackendPriceInfos: WebsiteBackendPriceInfo[] = await response.json(); - const addresses = _.map(websiteBackendPriceInfos, info => info.address); - const prices = _.map(websiteBackendPriceInfos, info => new BigNumber(info.price)); - const pricesByAddress = _.zipObject(addresses, prices); - return pricesByAddress; } private _openWrappedEtherActionRow(wrappedEtherDirection: Side) { this.setState({ diff --git a/packages/website/ts/pages/wiki/wiki.tsx b/packages/website/ts/pages/wiki/wiki.tsx index 1330cbf86..7ed2b750d 100644 --- a/packages/website/ts/pages/wiki/wiki.tsx +++ b/packages/website/ts/pages/wiki/wiki.tsx @@ -19,6 +19,7 @@ import { SidebarHeader } from 'ts/components/sidebar_header'; import { TopBar } from 'ts/components/top_bar/top_bar'; import { Dispatcher } from 'ts/redux/dispatcher'; import { Article, ArticlesBySection, WebsitePaths } from 'ts/types'; +import { backendClient } from 'ts/utils/backend_client'; import { configs } from 'ts/utils/configs'; import { constants } from 'ts/utils/constants'; import { Translate } from 'ts/utils/translate'; @@ -200,34 +201,30 @@ export class Wiki extends React.Component<WikiProps, WikiState> { ); } private async _fetchArticlesBySectionAsync(): Promise<void> { - const endpoint = `${configs.BACKEND_BASE_URL}${WebsitePaths.Wiki}`; - const response = await fetch(endpoint); - if (response.status === constants.HTTP_NO_CONTENT_STATUS_CODE) { - // We need to backoff and try fetching again later - this._wikiBackoffTimeoutId = window.setTimeout(() => { - // tslint:disable-next-line:no-floating-promises - this._fetchArticlesBySectionAsync(); - }, WIKI_NOT_READY_BACKOUT_TIMEOUT_MS); - return; - } - if (response.status !== 200) { - // TODO: Show the user an error message when the wiki fail to load - const errMsg = await response.text(); - logUtils.log(`Failed to load wiki: ${response.status} ${errMsg}`); - return; - } - const articlesBySection = await response.json(); - if (!this._isUnmounted) { - this.setState( - { - articlesBySection, - }, - async () => { - await utils.onPageLoadAsync(); - const hash = this.props.location.hash.slice(1); - sharedUtils.scrollToHash(hash, sharedConstants.SCROLL_CONTAINER_ID); - }, - ); + try { + const articlesBySection = await backendClient.getWikiArticlesBySectionAsync(); + if (!this._isUnmounted) { + this.setState( + { + articlesBySection, + }, + async () => { + await utils.onPageLoadAsync(); + const hash = this.props.location.hash.slice(1); + sharedUtils.scrollToHash(hash, sharedConstants.SCROLL_CONTAINER_ID); + }, + ); + } + } catch (err) { + const errMsg = `${err}`; + if (_.includes(errMsg, `${constants.HTTP_NO_CONTENT_STATUS_CODE}`)) { + // We need to backoff and try fetching again later + this._wikiBackoffTimeoutId = window.setTimeout(() => { + // tslint:disable-next-line:no-floating-promises + this._fetchArticlesBySectionAsync(); + }, WIKI_NOT_READY_BACKOUT_TIMEOUT_MS); + return; + } } } private _getMenuSubsectionsBySection(articlesBySection: ArticlesBySection) { diff --git a/packages/website/ts/types.ts b/packages/website/ts/types.ts index 989c0a032..98d080afb 100644 --- a/packages/website/ts/types.ts +++ b/packages/website/ts/types.ts @@ -507,4 +507,13 @@ export interface RelayerInfo { marketShare: number; topTokens: Token[]; } + +export interface WebsiteBackendPriceInfo { + price: string; + address: string; +} + +export interface WebsiteBackendGasInfo { + average: number; +} // tslint:disable:max-file-line-count diff --git a/packages/website/ts/utils/backend_client.ts b/packages/website/ts/utils/backend_client.ts new file mode 100644 index 000000000..366519856 --- /dev/null +++ b/packages/website/ts/utils/backend_client.ts @@ -0,0 +1,59 @@ +import { BigNumber, logUtils } from '@0xproject/utils'; +import * as _ from 'lodash'; +import * as queryString from 'query-string'; + +import { ArticlesBySection, ItemByAddress, WebsiteBackendGasInfo, WebsiteBackendPriceInfo } from 'ts/types'; +import { configs } from 'ts/utils/configs'; +import { errorReporter } from 'ts/utils/error_reporter'; + +const ETH_GAS_STATION_ENDPOINT = '/eth_gas_station'; +const PRICES_ENDPOINT = '/prices'; +const WIKI_ENDPOINT = '/wiki'; + +export const backendClient = { + async getGasInfoAsync(): Promise<WebsiteBackendGasInfo> { + const result = await requestAsync(ETH_GAS_STATION_ENDPOINT); + return result; + }, + async getPriceInfosAsync(tokenAddresses: string[]): Promise<WebsiteBackendPriceInfo[]> { + if (_.isEmpty(tokenAddresses)) { + return []; + } + const joinedTokenAddresses = tokenAddresses.join(','); + const queryParams = { + tokens: joinedTokenAddresses, + }; + const result = await requestAsync(PRICES_ENDPOINT, queryParams); + return result; + }, + async getWikiArticlesBySectionAsync(): Promise<ArticlesBySection> { + const result = await requestAsync(WIKI_ENDPOINT); + return result; + }, +}; + +async function requestAsync(endpoint: string, queryParams?: object): Promise<any> { + const query = queryStringFromQueryParams(queryParams); + const url = `${configs.BACKEND_BASE_URL}${endpoint}${query}`; + const response = await fetch(url); + if (response.status !== 200) { + const errorText = `Error requesting url: ${url}, ${response.status}: ${response.statusText}`; + logUtils.log(errorText); + const error = Error(errorText); + // tslint:disable-next-line:no-floating-promises + errorReporter.reportAsync(error); + throw error; + } + const result = await response.json(); + return result; +} + +function queryStringFromQueryParams(queryParams?: object): string { + // if params are undefined or empty, return an empty string + if (_.isUndefined(queryParams) || _.isEmpty(queryParams)) { + return ''; + } + // stringify the formatted object + const stringifiedParams = queryString.stringify(queryParams); + return `?${stringifiedParams}`; +} @@ -275,7 +275,7 @@ dependencies: "@types/node" "*" -"@types/query-string@^5.0.1": +"@types/query-string@^5.0.1", "@types/query-string@^5.1.0": version "5.1.0" resolved "https://registry.yarnpkg.com/@types/query-string/-/query-string-5.1.0.tgz#7f40cdea49ddafa0ea4f3db35fb6c24d3bfd4dcc" @@ -8451,6 +8451,13 @@ query-string@^5.0.1: object-assign "^4.1.0" strict-uri-encode "^1.0.0" +query-string@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/query-string/-/query-string-6.0.0.tgz#8b8f39447b73e8290d6f5e3581779218e9171142" + dependencies: + decode-uri-component "^0.2.0" + strict-uri-encode "^2.0.0" + querystring-es3@^0.2.0: version "0.2.1" resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73" @@ -9930,6 +9937,10 @@ strict-uri-encode@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713" +strict-uri-encode@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz#b9c7330c7042862f6b142dc274bbcc5866ce3546" + string-editor@^0.1.0: version "0.1.2" resolved "https://registry.yarnpkg.com/string-editor/-/string-editor-0.1.2.tgz#f5ff1b5ac4aed7ac6c2fb8de236d1551b20f61d0" |