From e51f9b3593c86c5ab4ec0ecb7e7ea8a9857a7c74 Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Sun, 22 Apr 2018 13:02:47 -0400 Subject: Grab price information from crypto compare api --- packages/website/ts/components/wallet/wallet.tsx | 45 +++++++++++++++++++----- 1 file changed, 37 insertions(+), 8 deletions(-) (limited to 'packages/website/ts/components') diff --git a/packages/website/ts/components/wallet/wallet.tsx b/packages/website/ts/components/wallet/wallet.tsx index d1ae38550..44bf69455 100644 --- a/packages/website/ts/components/wallet/wallet.tsx +++ b/packages/website/ts/components/wallet/wallet.tsx @@ -6,7 +6,7 @@ import { Styles, utils as sharedUtils, } from '@0xproject/react-shared'; -import { BigNumber } from '@0xproject/utils'; +import { BigNumber, logUtils } from '@0xproject/utils'; import * as _ from 'lodash'; import FlatButton from 'material-ui/FlatButton'; import { List, ListItem } from 'material-ui/List'; @@ -37,7 +37,9 @@ import { TokenStateByAddress, } 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'; import { utils } from 'ts/utils/utils'; import { styles as walletItemStyles } from 'ts/utils/wallet_item_styles'; @@ -491,15 +493,42 @@ export class Wallet extends React.Component { if (_.isEmpty(tokenAddresses)) { return {}; } - 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) { + // for each input token address, search for the corresponding symbol in this.props.tokenByAddress, if it exists + // create a mapping from existing symbols -> address + const tokenAddressBySymbol = _.fromPairs( + _.compact( + _.map(tokenAddresses, address => { + const tokenIfExists = _.get(this.props.tokenByAddress, address); + if (!_.isUndefined(tokenIfExists)) { + const symbol = tokenIfExists.symbol; + // the crypto compare api doesn't understand 'WETH' so we need to replace it with 'ETH' + const key = symbol === ETHER_TOKEN_SYMBOL ? ETHER_SYMBOL : symbol; + return [key, address]; + } else { + return undefined; + } + }), + ), + ); + const joinedTokenSymbols = _.keys(tokenAddressBySymbol).join(','); + const url = `${configs.CRYPTO_COMPARE_BASE_URL}/pricemulti?fsyms=${joinedTokenSymbols}&tsyms=USD`; + 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); return {}; } + const priceInfoBySymbol = await response.json(); + const priceInfoByAddress = _.mapKeys(priceInfoBySymbol, (value, symbol) => _.get(tokenAddressBySymbol, symbol)); + const result = _.mapValues(priceInfoByAddress, priceInfo => { + const price = _.get(priceInfo, 'USD'); + const priceBigNumber = new BigNumber(price); + return priceBigNumber; + }); + return result; } private _openWrappedEtherActionRow(wrappedEtherDirection: Side) { this.setState({ -- cgit v1.2.3 From fb31c493176ec952f6c3621348e328e38ade2174 Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Sun, 22 Apr 2018 13:27:16 -0400 Subject: Refactor common fetch logic into fetch_utils --- packages/website/ts/components/wallet/wallet.tsx | 39 ++++++++++++++---------- 1 file changed, 23 insertions(+), 16 deletions(-) (limited to 'packages/website/ts/components') diff --git a/packages/website/ts/components/wallet/wallet.tsx b/packages/website/ts/components/wallet/wallet.tsx index 44bf69455..3f0a4fdca 100644 --- a/packages/website/ts/components/wallet/wallet.tsx +++ b/packages/website/ts/components/wallet/wallet.tsx @@ -40,6 +40,7 @@ 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'; +import { fetchUtils } from 'ts/utils/fetch_utils'; import { utils } from 'ts/utils/utils'; import { styles as walletItemStyles } from 'ts/utils/wallet_item_styles'; @@ -130,6 +131,7 @@ const FOOTER_ITEM_KEY = 'FOOTER'; const DISCONNECTED_ITEM_KEY = 'DISCONNECTED'; const ETHER_ITEM_KEY = 'ETHER'; const USD_DECIMAL_PLACES = 2; +const CRYPTO_COMPARE_MULTI_ENDPOINT = '/pricemulti'; export class Wallet extends React.Component { private _isUnmounted: boolean; @@ -511,24 +513,29 @@ export class Wallet extends React.Component { ), ); const joinedTokenSymbols = _.keys(tokenAddressBySymbol).join(','); - const url = `${configs.CRYPTO_COMPARE_BASE_URL}/pricemulti?fsyms=${joinedTokenSymbols}&tsyms=USD`; - 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); + const baseCurrency = 'USD'; + const queryParams = { + fsyms: joinedTokenSymbols, + tsyms: baseCurrency, + }; + try { + const priceInfoBySymbol = await fetchUtils.requestAsync( + configs.CRYPTO_COMPARE_BASE_URL, + CRYPTO_COMPARE_MULTI_ENDPOINT, + queryParams, + ); + const priceInfoByAddress = _.mapKeys(priceInfoBySymbol, (value, symbol) => + _.get(tokenAddressBySymbol, symbol), + ); + const result = _.mapValues(priceInfoByAddress, priceInfo => { + const price = _.get(priceInfo, baseCurrency); + const priceBigNumber = new BigNumber(price); + return priceBigNumber; + }); + return result; + } catch (err) { return {}; } - const priceInfoBySymbol = await response.json(); - const priceInfoByAddress = _.mapKeys(priceInfoBySymbol, (value, symbol) => _.get(tokenAddressBySymbol, symbol)); - const result = _.mapValues(priceInfoByAddress, priceInfo => { - const price = _.get(priceInfo, 'USD'); - const priceBigNumber = new BigNumber(price); - return priceBigNumber; - }); - return result; } private _openWrappedEtherActionRow(wrappedEtherDirection: Side) { this.setState({ -- cgit v1.2.3 From 121b6949a1e185c0cc9768c2b7042eb3daf124b7 Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Sun, 22 Apr 2018 14:05:03 -0400 Subject: Rate limit crypto compare calls --- packages/website/ts/components/wallet/wallet.tsx | 28 +++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) (limited to 'packages/website/ts/components') diff --git a/packages/website/ts/components/wallet/wallet.tsx b/packages/website/ts/components/wallet/wallet.tsx index 3f0a4fdca..231045bc5 100644 --- a/packages/website/ts/components/wallet/wallet.tsx +++ b/packages/website/ts/components/wallet/wallet.tsx @@ -132,9 +132,12 @@ const DISCONNECTED_ITEM_KEY = 'DISCONNECTED'; const ETHER_ITEM_KEY = 'ETHER'; const USD_DECIMAL_PLACES = 2; const CRYPTO_COMPARE_MULTI_ENDPOINT = '/pricemulti'; +// Crypto compare recommends requesting no more than once every 10s: https://www.cryptocompare.com/api/?javascript#requests +const CRYPTO_COMPARE_UPDATE_INTERVAL_MS = 10 * 1000; export class Wallet extends React.Component { private _isUnmounted: boolean; + private _cryptoCompareLastFetchTimestampMs?: number; constructor(props: WalletProps) { super(props); this._isUnmounted = false; @@ -465,16 +468,27 @@ export class Wallet extends React.Component { ); balanceAndAllowanceTupleByAddress[tokenAddress] = balanceAndAllowanceTuple; } - const pricesByAddress = await this._getPricesByAddressAsync(tokenAddresses); + // if we are allowed to fetch prices do so, if not, keep the old price state + const canFetchPrices = this._canGetPrice(); + let priceByAddress: ItemByAddress = {}; + if (canFetchPrices) { + priceByAddress = await this._getPricesByAddressAsync(tokenAddresses); + } else { + const cachedPricesByAddress = _.mapValues( + this.state.trackedTokenStateByAddress, + tokenState => tokenState.price, + ); + priceByAddress = cachedPricesByAddress; + } const trackedTokenStateByAddress = _.reduce( tokenAddresses, (acc, address) => { const [balance, allowance] = balanceAndAllowanceTupleByAddress[address]; - const price = pricesByAddress[address]; + const priceIfExists = _.get(priceByAddress, address); acc[address] = { balance, allowance, - price, + price: priceIfExists, isLoaded: true, }; return acc; @@ -519,6 +533,7 @@ export class Wallet extends React.Component { tsyms: baseCurrency, }; try { + this._cryptoCompareLastFetchTimestampMs = Date.now(); const priceInfoBySymbol = await fetchUtils.requestAsync( configs.CRYPTO_COMPARE_BASE_URL, CRYPTO_COMPARE_MULTI_ENDPOINT, @@ -537,6 +552,13 @@ export class Wallet extends React.Component { return {}; } } + private _canGetPrice() { + const currentTimeStamp = Date.now(); + const result = + _.isUndefined(this._cryptoCompareLastFetchTimestampMs) || + this._cryptoCompareLastFetchTimestampMs + CRYPTO_COMPARE_UPDATE_INTERVAL_MS < currentTimeStamp; + return result; + } private _openWrappedEtherActionRow(wrappedEtherDirection: Side) { this.setState({ wrappedEtherDirection, -- cgit v1.2.3 From 96568957263858c6832ae972f9df5f02913549c6 Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Sun, 22 Apr 2018 14:17:34 -0400 Subject: Remove some unused imports --- packages/website/ts/components/wallet/wallet.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'packages/website/ts/components') diff --git a/packages/website/ts/components/wallet/wallet.tsx b/packages/website/ts/components/wallet/wallet.tsx index 231045bc5..257ea8ac4 100644 --- a/packages/website/ts/components/wallet/wallet.tsx +++ b/packages/website/ts/components/wallet/wallet.tsx @@ -6,7 +6,7 @@ import { Styles, utils as sharedUtils, } from '@0xproject/react-shared'; -import { BigNumber, logUtils } from '@0xproject/utils'; +import { BigNumber } from '@0xproject/utils'; import * as _ from 'lodash'; import FlatButton from 'material-ui/FlatButton'; import { List, ListItem } from 'material-ui/List'; @@ -39,7 +39,6 @@ import { 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'; import { fetchUtils } from 'ts/utils/fetch_utils'; import { utils } from 'ts/utils/utils'; import { styles as walletItemStyles } from 'ts/utils/wallet_item_styles'; -- cgit v1.2.3 From 9b535e3cec4073205c1343306829bcdec3168002 Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Sun, 22 Apr 2018 14:20:42 -0400 Subject: Rename baseCurrency to quoteCurrency --- packages/website/ts/components/wallet/wallet.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'packages/website/ts/components') diff --git a/packages/website/ts/components/wallet/wallet.tsx b/packages/website/ts/components/wallet/wallet.tsx index 257ea8ac4..2097c0eab 100644 --- a/packages/website/ts/components/wallet/wallet.tsx +++ b/packages/website/ts/components/wallet/wallet.tsx @@ -526,10 +526,10 @@ export class Wallet extends React.Component { ), ); const joinedTokenSymbols = _.keys(tokenAddressBySymbol).join(','); - const baseCurrency = 'USD'; + const quoteCurrency = 'USD'; const queryParams = { fsyms: joinedTokenSymbols, - tsyms: baseCurrency, + tsyms: quoteCurrency, }; try { this._cryptoCompareLastFetchTimestampMs = Date.now(); @@ -542,7 +542,7 @@ export class Wallet extends React.Component { _.get(tokenAddressBySymbol, symbol), ); const result = _.mapValues(priceInfoByAddress, priceInfo => { - const price = _.get(priceInfo, baseCurrency); + const price = _.get(priceInfo, quoteCurrency); const priceBigNumber = new BigNumber(price); return priceBigNumber; }); -- cgit v1.2.3 From feb7dfffa107211e76b87d2028b8c821e914f0d6 Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Fri, 27 Apr 2018 14:59:22 -0700 Subject: Move quote currency string into config --- packages/website/ts/components/wallet/wallet.tsx | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'packages/website/ts/components') diff --git a/packages/website/ts/components/wallet/wallet.tsx b/packages/website/ts/components/wallet/wallet.tsx index 2097c0eab..33b8bbffb 100644 --- a/packages/website/ts/components/wallet/wallet.tsx +++ b/packages/website/ts/components/wallet/wallet.tsx @@ -526,10 +526,9 @@ export class Wallet extends React.Component { ), ); const joinedTokenSymbols = _.keys(tokenAddressBySymbol).join(','); - const quoteCurrency = 'USD'; const queryParams = { fsyms: joinedTokenSymbols, - tsyms: quoteCurrency, + tsyms: configs.FIAT_QUOTE_CURRENCY_SYMBOL, }; try { this._cryptoCompareLastFetchTimestampMs = Date.now(); @@ -542,7 +541,7 @@ export class Wallet extends React.Component { _.get(tokenAddressBySymbol, symbol), ); const result = _.mapValues(priceInfoByAddress, priceInfo => { - const price = _.get(priceInfo, quoteCurrency); + const price = _.get(priceInfo, configs.FIAT_QUOTE_CURRENCY_SYMBOL); const priceBigNumber = new BigNumber(price); return priceBigNumber; }); -- cgit v1.2.3 From 2403323463be66166dae9f8ca7903caab2546717 Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Fri, 27 Apr 2018 15:01:19 -0700 Subject: Style suggestions --- packages/website/ts/components/wallet/wallet.tsx | 25 ++++++++++-------------- 1 file changed, 10 insertions(+), 15 deletions(-) (limited to 'packages/website/ts/components') diff --git a/packages/website/ts/components/wallet/wallet.tsx b/packages/website/ts/components/wallet/wallet.tsx index 33b8bbffb..51399ae0b 100644 --- a/packages/website/ts/components/wallet/wallet.tsx +++ b/packages/website/ts/components/wallet/wallet.tsx @@ -510,21 +510,16 @@ export class Wallet extends React.Component { } // for each input token address, search for the corresponding symbol in this.props.tokenByAddress, if it exists // create a mapping from existing symbols -> address - const tokenAddressBySymbol = _.fromPairs( - _.compact( - _.map(tokenAddresses, address => { - const tokenIfExists = _.get(this.props.tokenByAddress, address); - if (!_.isUndefined(tokenIfExists)) { - const symbol = tokenIfExists.symbol; - // the crypto compare api doesn't understand 'WETH' so we need to replace it with 'ETH' - const key = symbol === ETHER_TOKEN_SYMBOL ? ETHER_SYMBOL : symbol; - return [key, address]; - } else { - return undefined; - } - }), - ), - ); + const tokenAddressBySymbol: { [symbol: string]: string } = {}; + _.each(tokenAddresses, address => { + const tokenIfExists = _.get(this.props.tokenByAddress, address); + if (!_.isUndefined(tokenIfExists)) { + const symbol = tokenIfExists.symbol; + // the crypto compare api doesn't understand 'WETH' so we need to replace it with 'ETH' + const key = symbol === ETHER_TOKEN_SYMBOL ? ETHER_SYMBOL : symbol; + tokenAddressBySymbol[key] = address; + } + }); const joinedTokenSymbols = _.keys(tokenAddressBySymbol).join(','); const queryParams = { fsyms: joinedTokenSymbols, -- cgit v1.2.3 From 1131d66b3db2bde04b5108d710801fab7eaf0ede Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Mon, 30 Apr 2018 16:36:42 -0700 Subject: Hit website backend for price information --- packages/website/ts/components/wallet/wallet.tsx | 46 ++++-------------------- 1 file changed, 6 insertions(+), 40 deletions(-) (limited to 'packages/website/ts/components') diff --git a/packages/website/ts/components/wallet/wallet.tsx b/packages/website/ts/components/wallet/wallet.tsx index 51399ae0b..9022eb1c9 100644 --- a/packages/website/ts/components/wallet/wallet.tsx +++ b/packages/website/ts/components/wallet/wallet.tsx @@ -37,9 +37,7 @@ import { TokenStateByAddress, } from 'ts/types'; import { backendClient } from 'ts/utils/backend_client'; -import { configs } from 'ts/utils/configs'; import { constants } from 'ts/utils/constants'; -import { fetchUtils } from 'ts/utils/fetch_utils'; import { utils } from 'ts/utils/utils'; import { styles as walletItemStyles } from 'ts/utils/wallet_item_styles'; @@ -130,13 +128,9 @@ const FOOTER_ITEM_KEY = 'FOOTER'; const DISCONNECTED_ITEM_KEY = 'DISCONNECTED'; const ETHER_ITEM_KEY = 'ETHER'; const USD_DECIMAL_PLACES = 2; -const CRYPTO_COMPARE_MULTI_ENDPOINT = '/pricemulti'; -// Crypto compare recommends requesting no more than once every 10s: https://www.cryptocompare.com/api/?javascript#requests -const CRYPTO_COMPARE_UPDATE_INTERVAL_MS = 10 * 1000; export class Wallet extends React.Component { private _isUnmounted: boolean; - private _cryptoCompareLastFetchTimestampMs?: number; constructor(props: WalletProps) { super(props); this._isUnmounted = false; @@ -467,18 +461,7 @@ export class Wallet extends React.Component { ); balanceAndAllowanceTupleByAddress[tokenAddress] = balanceAndAllowanceTuple; } - // if we are allowed to fetch prices do so, if not, keep the old price state - const canFetchPrices = this._canGetPrice(); - let priceByAddress: ItemByAddress = {}; - if (canFetchPrices) { - priceByAddress = await this._getPricesByAddressAsync(tokenAddresses); - } else { - const cachedPricesByAddress = _.mapValues( - this.state.trackedTokenStateByAddress, - tokenState => tokenState.price, - ); - priceByAddress = cachedPricesByAddress; - } + const priceByAddress = await this._getPriceByAddressAsync(tokenAddresses); const trackedTokenStateByAddress = _.reduce( tokenAddresses, (acc, address) => { @@ -504,7 +487,7 @@ export class Wallet extends React.Component { private async _refetchTokenStateAsync(tokenAddress: string) { await this._fetchBalancesAndAllowancesAsync([tokenAddress]); } - private async _getPricesByAddressAsync(tokenAddresses: string[]): Promise> { + private async _getPriceByAddressAsync(tokenAddresses: string[]): Promise> { if (_.isEmpty(tokenAddresses)) { return {}; } @@ -520,23 +503,13 @@ export class Wallet extends React.Component { tokenAddressBySymbol[key] = address; } }); - const joinedTokenSymbols = _.keys(tokenAddressBySymbol).join(','); - const queryParams = { - fsyms: joinedTokenSymbols, - tsyms: configs.FIAT_QUOTE_CURRENCY_SYMBOL, - }; + const tokenSymbols = _.keys(tokenAddressBySymbol); try { - this._cryptoCompareLastFetchTimestampMs = Date.now(); - const priceInfoBySymbol = await fetchUtils.requestAsync( - configs.CRYPTO_COMPARE_BASE_URL, - CRYPTO_COMPARE_MULTI_ENDPOINT, - queryParams, - ); - const priceInfoByAddress = _.mapKeys(priceInfoBySymbol, (value, symbol) => + const priceBySymbol = await backendClient.getPriceInfoAsync(tokenSymbols); + const priceByAddress = _.mapKeys(priceBySymbol, (value, symbol) => _.get(tokenAddressBySymbol, symbol), ); - const result = _.mapValues(priceInfoByAddress, priceInfo => { - const price = _.get(priceInfo, configs.FIAT_QUOTE_CURRENCY_SYMBOL); + const result = _.mapValues(priceByAddress, price => { const priceBigNumber = new BigNumber(price); return priceBigNumber; }); @@ -545,13 +518,6 @@ export class Wallet extends React.Component { return {}; } } - private _canGetPrice() { - const currentTimeStamp = Date.now(); - const result = - _.isUndefined(this._cryptoCompareLastFetchTimestampMs) || - this._cryptoCompareLastFetchTimestampMs + CRYPTO_COMPARE_UPDATE_INTERVAL_MS < currentTimeStamp; - return result; - } private _openWrappedEtherActionRow(wrappedEtherDirection: Side) { this.setState({ wrappedEtherDirection, -- cgit v1.2.3 From 3a1f9d01e8cdb40fbb293de10046fa654434dde4 Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Mon, 30 Apr 2018 16:49:47 -0700 Subject: Remove WETH special case, website backend handles this now --- packages/website/ts/components/wallet/wallet.tsx | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'packages/website/ts/components') diff --git a/packages/website/ts/components/wallet/wallet.tsx b/packages/website/ts/components/wallet/wallet.tsx index 9022eb1c9..057c712e5 100644 --- a/packages/website/ts/components/wallet/wallet.tsx +++ b/packages/website/ts/components/wallet/wallet.tsx @@ -498,17 +498,13 @@ export class Wallet extends React.Component { const tokenIfExists = _.get(this.props.tokenByAddress, address); if (!_.isUndefined(tokenIfExists)) { const symbol = tokenIfExists.symbol; - // the crypto compare api doesn't understand 'WETH' so we need to replace it with 'ETH' - const key = symbol === ETHER_TOKEN_SYMBOL ? ETHER_SYMBOL : symbol; - tokenAddressBySymbol[key] = address; + tokenAddressBySymbol[symbol] = address; } }); const tokenSymbols = _.keys(tokenAddressBySymbol); try { const priceBySymbol = await backendClient.getPriceInfoAsync(tokenSymbols); - const priceByAddress = _.mapKeys(priceBySymbol, (value, symbol) => - _.get(tokenAddressBySymbol, symbol), - ); + const priceByAddress = _.mapKeys(priceBySymbol, (value, symbol) => _.get(tokenAddressBySymbol, symbol)); const result = _.mapValues(priceByAddress, price => { const priceBigNumber = new BigNumber(price); return priceBigNumber; -- cgit v1.2.3 From 5e3576ed695ce0aaff7d7b59d77380f68e334df1 Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Wed, 2 May 2018 17:03:36 -0700 Subject: Remove id property from WebsiteBackendRelayerInfo --- packages/website/ts/components/relayer_index/relayer_index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'packages/website/ts/components') diff --git a/packages/website/ts/components/relayer_index/relayer_index.tsx b/packages/website/ts/components/relayer_index/relayer_index.tsx index 50760c32d..c1ab4227a 100644 --- a/packages/website/ts/components/relayer_index/relayer_index.tsx +++ b/packages/website/ts/components/relayer_index/relayer_index.tsx @@ -66,7 +66,7 @@ export class RelayerIndex extends React.Component {this.state.relayerInfos.map((relayerInfo: WebsiteBackendRelayerInfo) => ( -- cgit v1.2.3 From cf9555debc445f6645cfdf4e9835247abc084638 Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Thu, 3 May 2018 12:35:21 +0200 Subject: Fix logo left padding on mobile --- packages/website/ts/components/top_bar/top_bar.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'packages/website/ts/components') diff --git a/packages/website/ts/components/top_bar/top_bar.tsx b/packages/website/ts/components/top_bar/top_bar.tsx index 0c32f4c62..95e6276bf 100644 --- a/packages/website/ts/components/top_bar/top_bar.tsx +++ b/packages/website/ts/components/top_bar/top_bar.tsx @@ -193,7 +193,7 @@ export class TopBar extends React.Component { return (
-
+
-- cgit v1.2.3 From fe0f4ae25759eb6b6cad8c6608ebff526366c059 Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Wed, 2 May 2018 20:42:17 -0700 Subject: Add header images to relayer grid tiles --- .../website/ts/components/relayer_index/relayer_grid_tile.tsx | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'packages/website/ts/components') 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 0c4b2841c..7d0551581 100644 --- a/packages/website/ts/components/relayer_index/relayer_grid_tile.tsx +++ b/packages/website/ts/components/relayer_index/relayer_grid_tile.tsx @@ -12,8 +12,7 @@ export interface RelayerGridTileProps { networkId: number; } -// TODO: Get top tokens and headerurl from remote -const headerUrl = '/images/og_image.png'; +// TODO: Get top tokens from remote const topTokens = [ { address: '0x1dad4783cf3fe3085c1426157ab175a6119a04ba', @@ -68,6 +67,9 @@ const styles: Styles = { borderBottomLeftRadius: 4, borderTopRightRadius: 4, borderTopLeftRadius: 4, + borderWidth: 1, + borderStyle: 'solid', + borderColor: colors.walletBorder, }, body: { paddingLeft: 6, @@ -95,7 +97,7 @@ export const RelayerGridTile: React.StatelessComponent = ( return (
- +
{props.relayerInfo.name} -- cgit v1.2.3 From 6b92ef733c6f1cfd1772433abfdc9fd82227fa8b Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Thu, 3 May 2018 13:06:39 -0700 Subject: Open relayer app when clicking on grid tile --- .../components/relayer_index/relayer_grid_tile.tsx | 35 ++++++++++++---------- 1 file changed, 19 insertions(+), 16 deletions(-) (limited to 'packages/website/ts/components') 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 7d0551581..0b9b8165e 100644 --- a/packages/website/ts/components/relayer_index/relayer_grid_tile.tsx +++ b/packages/website/ts/components/relayer_index/relayer_grid_tile.tsx @@ -94,24 +94,27 @@ const styles: Styles = { }; export const RelayerGridTile: React.StatelessComponent = (props: RelayerGridTileProps) => { + const link = props.relayerInfo.appUrl || props.relayerInfo.url; return ( - -
- -
-
- {props.relayerInfo.name} -
-
{props.relayerInfo.dailyTxnVolume}
-
- Daily Trade Volume -
- - - + + ); }; -- cgit v1.2.3 From 01dd84dced8d885f6b164cab714ecfde4d0a363e Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Fri, 4 May 2018 11:57:34 +0200 Subject: Add order utils docs to the menu --- packages/website/ts/components/top_bar/top_bar.tsx | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'packages/website/ts/components') diff --git a/packages/website/ts/components/top_bar/top_bar.tsx b/packages/website/ts/components/top_bar/top_bar.tsx index 95e6276bf..8bea58b0a 100644 --- a/packages/website/ts/components/top_bar/top_bar.tsx +++ b/packages/website/ts/components/top_bar/top_bar.tsx @@ -139,6 +139,12 @@ export class TopBar extends React.Component { primaryText={this.props.translate.get(Key.Web3Wrapper, Deco.CapWords)} /> , + + + , Date: Mon, 23 Apr 2018 21:07:48 -0700 Subject: Lay out wallet and relayers --- packages/website/ts/components/portal/portal.tsx | 214 +++++++++++++++++++++++ 1 file changed, 214 insertions(+) create mode 100644 packages/website/ts/components/portal/portal.tsx (limited to 'packages/website/ts/components') diff --git a/packages/website/ts/components/portal/portal.tsx b/packages/website/ts/components/portal/portal.tsx new file mode 100644 index 000000000..8a9e89a72 --- /dev/null +++ b/packages/website/ts/components/portal/portal.tsx @@ -0,0 +1,214 @@ +import { colors, Styles } from '@0xproject/react-shared'; +import { BigNumber } from '@0xproject/utils'; +import * as _ from 'lodash'; +import * as React from 'react'; +import * as DocumentTitle from 'react-document-title'; + +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 { RelayerIndex } from 'ts/components/relayer_index/relayer_index'; +import { TopBar } from 'ts/components/top_bar/top_bar'; +import { FlashMessage } from 'ts/components/ui/flash_message'; +import { Wallet } from 'ts/components/wallet/wallet'; +import { localStorage } from 'ts/local_storage/local_storage'; +import { Dispatcher } from 'ts/redux/dispatcher'; +import { BlockchainErrs, HashData, Order, ProviderType, ScreenWidths, TokenByAddress } from 'ts/types'; +import { constants } from 'ts/utils/constants'; +import { Translate } from 'ts/utils/translate'; +import { utils } from 'ts/utils/utils'; + +export interface PortalProps { + 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 PortalState { + prevNetworkId: number; + prevNodeVersion: string; + prevUserAddress: string; + prevPathname: string; + isDisclaimerDialogOpen: boolean; + isLedgerDialogOpen: boolean; +} + +const THROTTLE_TIMEOUT = 100; +const TOP_BAR_HEIGHT = 60; + +const styles: Styles = { + root: { + width: '100%', + height: '100%', + backgroundColor: colors.lightestGrey, + }, + body: { + height: `calc(100vh - ${TOP_BAR_HEIGHT}px)`, + }, +}; + +export class Portal extends React.Component { + private _blockchain: Blockchain; + private _throttledScreenWidthUpdate: () => void; + constructor(props: PortalProps) { + super(props); + this._throttledScreenWidthUpdate = _.throttle(this._updateScreenWidth.bind(this), THROTTLE_TIMEOUT); + 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, + isLedgerDialogOpen: false, + }; + } + public componentDidMount() { + window.addEventListener('resize', this._throttledScreenWidthUpdate); + window.scrollTo(0, 0); + } + public componentWillMount() { + this._blockchain = new Blockchain(this.props.dispatcher); + } + public componentWillUnmount() { + 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: PortalProps) { + 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) { + this.setState({ + prevPathname: nextProps.location.pathname, + }); + } + } + public render() { + const updateShouldBlockchainErrDialogBeOpen = this.props.dispatcher.updateShouldBlockchainErrDialogBeOpen.bind( + this.props.dispatcher, + ); + const allTokens = _.values(this.props.tokenByAddress); + const trackedTokens = _.filter(allTokens, t => t.isTracked); + return ( +
+ + +
+
+
+ +
+
+ +
+
+ + + + {this.props.blockchainIsLoaded && ( + + )} +
+
+ ); + } + private _onToggleLedgerDialog() { + this.setState({ + isLedgerDialogOpen: !this.state.isLedgerDialogOpen, + }); + } + private _onPortalDisclaimerAccepted() { + localStorage.setItem(constants.LOCAL_STORAGE_KEY_ACCEPT_DISCLAIMER, 'set'); + this.setState({ + isDisclaimerDialogOpen: false, + }); + } + private _updateScreenWidth() { + const newScreenWidth = utils.getScreenWidth(); + this.props.dispatcher.updateScreenWidth(newScreenWidth); + } +} -- cgit v1.2.3 From 14b29172b1713610c80ccf5b7390f7b445b0eb75 Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Mon, 23 Apr 2018 21:45:05 -0700 Subject: Add scrolling to relayer index --- packages/website/ts/components/portal/portal.tsx | 8 +++++++- packages/website/ts/components/relayer_index/relayer_index.tsx | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) (limited to 'packages/website/ts/components') diff --git a/packages/website/ts/components/portal/portal.tsx b/packages/website/ts/components/portal/portal.tsx index 8a9e89a72..6939d8905 100644 --- a/packages/website/ts/components/portal/portal.tsx +++ b/packages/website/ts/components/portal/portal.tsx @@ -62,6 +62,12 @@ const styles: Styles = { body: { height: `calc(100vh - ${TOP_BAR_HEIGHT}px)`, }, + scrollContainer: { + overflowZ: 'hidden', + height: `calc(100vh - ${TOP_BAR_HEIGHT}px)`, + WebkitOverflowScrolling: 'touch', + overflow: 'auto', + }, }; export class Portal extends React.Component { @@ -165,7 +171,7 @@ export class Portal extends React.Component { onToggleLedgerDialog={this._onToggleLedgerDialog.bind(this)} />
-
+
diff --git a/packages/website/ts/components/relayer_index/relayer_index.tsx b/packages/website/ts/components/relayer_index/relayer_index.tsx index c1ab4227a..e8775e1a5 100644 --- a/packages/website/ts/components/relayer_index/relayer_index.tsx +++ b/packages/website/ts/components/relayer_index/relayer_index.tsx @@ -57,7 +57,7 @@ export class RelayerIndex extends React.Component +
Date: Mon, 23 Apr 2018 22:17:26 -0700 Subject: Add headers to wallet and relayer index --- packages/website/ts/components/portal/portal.tsx | 12 +++++++++++- .../website/ts/components/relayer_index/relayer_index.tsx | 2 +- 2 files changed, 12 insertions(+), 2 deletions(-) (limited to 'packages/website/ts/components') diff --git a/packages/website/ts/components/portal/portal.tsx b/packages/website/ts/components/portal/portal.tsx index 6939d8905..507860ee6 100644 --- a/packages/website/ts/components/portal/portal.tsx +++ b/packages/website/ts/components/portal/portal.tsx @@ -68,6 +68,10 @@ const styles: Styles = { WebkitOverflowScrolling: 'touch', overflow: 'auto', }, + title: { + fontWeight: 'bold', + fontSize: 20, + }, }; export class Portal extends React.Component { @@ -154,7 +158,10 @@ export class Portal extends React.Component { />
-
+
+
+ Your Account +
{ />
+
+ Explore 0x Ecosystem +
diff --git a/packages/website/ts/components/relayer_index/relayer_index.tsx b/packages/website/ts/components/relayer_index/relayer_index.tsx index e8775e1a5..c1ab4227a 100644 --- a/packages/website/ts/components/relayer_index/relayer_index.tsx +++ b/packages/website/ts/components/relayer_index/relayer_index.tsx @@ -57,7 +57,7 @@ export class RelayerIndex extends React.Component +
Date: Sat, 5 May 2018 01:26:02 +0200 Subject: Fix type errors in CSS properties --- packages/website/ts/components/top_bar/top_bar.tsx | 2 +- packages/website/ts/components/ui/input_label.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'packages/website/ts/components') diff --git a/packages/website/ts/components/top_bar/top_bar.tsx b/packages/website/ts/components/top_bar/top_bar.tsx index 8bea58b0a..7fb476ba0 100644 --- a/packages/website/ts/components/top_bar/top_bar.tsx +++ b/packages/website/ts/components/top_bar/top_bar.tsx @@ -56,7 +56,7 @@ const styles: Styles = { width: 70, }, topBar: { - backgroundcolor: colors.white, + backgroundColor: colors.white, height: 59, width: '100%', position: 'relative', diff --git a/packages/website/ts/components/ui/input_label.tsx b/packages/website/ts/components/ui/input_label.tsx index 6a3f26155..8137c0db6 100644 --- a/packages/website/ts/components/ui/input_label.tsx +++ b/packages/website/ts/components/ui/input_label.tsx @@ -17,7 +17,7 @@ const styles = { userSelect: 'none', width: 240, zIndex: 1, - }, + } as React.CSSProperties, }; export const InputLabel = (props: InputLabelProps) => { -- cgit v1.2.3