aboutsummaryrefslogtreecommitdiffstats
path: root/packages/instant
diff options
context:
space:
mode:
authorFabio Berger <me@fabioberger.com>2019-01-08 21:30:38 +0800
committerFabio Berger <me@fabioberger.com>2019-01-08 21:30:38 +0800
commit1631031fa74894143cb6835030b7dcd44d7c3c6b (patch)
tree06dea01cc64fb42905a5f95c95f4b3e16ecfe744 /packages/instant
parent0bcb81d3a918fbcf71d68f42fa661d884d5d74cf (diff)
parent0ac36cef288deecd36caa601c53d13517eef5ca8 (diff)
downloaddexon-sol-tools-1631031fa74894143cb6835030b7dcd44d7c3c6b.tar
dexon-sol-tools-1631031fa74894143cb6835030b7dcd44d7c3c6b.tar.gz
dexon-sol-tools-1631031fa74894143cb6835030b7dcd44d7c3c6b.tar.bz2
dexon-sol-tools-1631031fa74894143cb6835030b7dcd44d7c3c6b.tar.lz
dexon-sol-tools-1631031fa74894143cb6835030b7dcd44d7c3c6b.tar.xz
dexon-sol-tools-1631031fa74894143cb6835030b7dcd44d7c3c6b.tar.zst
dexon-sol-tools-1631031fa74894143cb6835030b7dcd44d7c3c6b.zip
Merge branch 'development' into feature/order-watcher/dockerize
* development: (898 commits) Fixed merge conflict from development Ran prettier Doc generation working for changes by dutch auction wrapper added changelog entry for monorepo-scripts Hide dutch auction wrapper from docs -- hopefully this will prevent the "must export Web3Wrapper" error from doc generation relaxed version on contract-extension dependencies Added NetworkID 50 address for dutch auction wrapper removed manual updte of package.json version export dutch auction wrapper types from 0x.js Export dutch auction wrapper in 0x.js ran prettier Minor documentation updates to dutch auction wrapper `afterAuctionDetails` -> `auctionDetails` Added @todo for including dutch auction addresses once deployed Ran prettier & linter Removed redundant assignment removed needless newline on contract-wrappers changelog removed timestamp from changelog for abi-gen-wrappers added dutch auction address for testnets removed .only ...
Diffstat (limited to 'packages/instant')
-rw-r--r--packages/instant/.production.discharge.json2
-rw-r--r--packages/instant/src/components/amount_placeholder.tsx2
-rw-r--r--packages/instant/src/components/animations/slide_animation.tsx10
-rw-r--r--packages/instant/src/components/buy_button.tsx16
-rw-r--r--packages/instant/src/components/buy_order_progress.tsx2
-rw-r--r--packages/instant/src/components/buy_order_state_buttons.tsx2
-rw-r--r--packages/instant/src/components/erc20_asset_amount_input.tsx2
-rw-r--r--packages/instant/src/components/erc20_token_selector.tsx77
-rw-r--r--packages/instant/src/components/install_wallet_panel_content.tsx2
-rw-r--r--packages/instant/src/components/instant_heading.tsx2
-rw-r--r--packages/instant/src/components/order_details.tsx4
-rw-r--r--packages/instant/src/components/payment_method.tsx2
-rw-r--r--packages/instant/src/components/payment_method_dropdown.tsx2
-rw-r--r--packages/instant/src/components/placing_order_button.tsx2
-rw-r--r--packages/instant/src/components/scaling_amount_input.tsx2
-rw-r--r--packages/instant/src/components/scaling_input.tsx2
-rw-r--r--packages/instant/src/components/secondary_button.tsx1
-rw-r--r--packages/instant/src/components/section_header.tsx1
-rw-r--r--packages/instant/src/components/sliding_error.tsx4
-rw-r--r--packages/instant/src/components/sliding_panel.tsx74
-rw-r--r--packages/instant/src/components/standard_panel_content.tsx2
-rw-r--r--packages/instant/src/components/standard_sliding_panel.tsx2
-rw-r--r--packages/instant/src/components/time_counter.tsx2
-rw-r--r--packages/instant/src/components/timed_progress_bar.tsx2
-rw-r--r--packages/instant/src/components/ui/container.tsx2
-rw-r--r--packages/instant/src/components/ui/dropdown.tsx43
-rw-r--r--packages/instant/src/components/wallet_prompt.tsx2
-rw-r--r--packages/instant/src/components/zero_ex_instant.tsx2
-rw-r--r--packages/instant/src/components/zero_ex_instant_container.tsx13
-rw-r--r--packages/instant/src/components/zero_ex_instant_overlay.tsx2
-rw-r--r--packages/instant/src/components/zero_ex_instant_provider.tsx2
-rw-r--r--packages/instant/src/constants.ts1
-rw-r--r--packages/instant/src/containers/latest_error.tsx4
-rw-r--r--packages/instant/src/containers/selected_asset_buy_order_state_buttons.ts3
-rw-r--r--packages/instant/src/types.ts2
-rw-r--r--packages/instant/src/util/analytics.ts6
-rw-r--r--packages/instant/src/util/env.ts2
37 files changed, 202 insertions, 101 deletions
diff --git a/packages/instant/.production.discharge.json b/packages/instant/.production.discharge.json
index 1ce39fdd8..c87f8b187 100644
--- a/packages/instant/.production.discharge.json
+++ b/packages/instant/.production.discharge.json
@@ -1,5 +1,5 @@
{
- "domain": "instant.0xproject.com",
+ "domain": "instant.0x.org",
"build_command": "dotenv yarn build -- --env.discharge_target=production",
"upload_directory": "umd",
"index_key": "instant.js",
diff --git a/packages/instant/src/components/amount_placeholder.tsx b/packages/instant/src/components/amount_placeholder.tsx
index 29ce8fafb..290e34a07 100644
--- a/packages/instant/src/components/amount_placeholder.tsx
+++ b/packages/instant/src/components/amount_placeholder.tsx
@@ -30,3 +30,5 @@ export const AmountPlaceholder: React.StatelessComponent<AmountPlaceholderProps>
return <PlainPlaceholder color={props.color} />;
}
};
+
+AmountPlaceholder.displayName = 'AmountPlaceholder';
diff --git a/packages/instant/src/components/animations/slide_animation.tsx b/packages/instant/src/components/animations/slide_animation.tsx
index 5992bcba7..6ac47e9a6 100644
--- a/packages/instant/src/components/animations/slide_animation.tsx
+++ b/packages/instant/src/components/animations/slide_animation.tsx
@@ -11,6 +11,7 @@ export interface SlideAnimationProps {
slideOutSettings: OptionallyScreenSpecific<PositionAnimationSettings>;
zIndex?: OptionallyScreenSpecific<number>;
height?: string;
+ onAnimationEnd?: () => void;
}
export const SlideAnimation: React.StatelessComponent<SlideAnimationProps> = props => {
@@ -19,8 +20,15 @@ export const SlideAnimation: React.StatelessComponent<SlideAnimationProps> = pro
}
const positionSettings = props.animationState === 'slidIn' ? props.slideInSettings : props.slideOutSettings;
return (
- <PositionAnimation height={props.height} positionSettings={positionSettings} zIndex={props.zIndex}>
+ <PositionAnimation
+ onAnimationEnd={props.onAnimationEnd}
+ height={props.height}
+ positionSettings={positionSettings}
+ zIndex={props.zIndex}
+ >
{props.children}
</PositionAnimation>
);
};
+
+SlideAnimation.displayName = 'SlideAnimation';
diff --git a/packages/instant/src/components/buy_button.tsx b/packages/instant/src/components/buy_button.tsx
index 1489b94d4..551e857a5 100644
--- a/packages/instant/src/components/buy_button.tsx
+++ b/packages/instant/src/components/buy_button.tsx
@@ -10,6 +10,7 @@ import { WEB_3_WRAPPER_TRANSACTION_FAILED_ERROR_MSG_PREFIX } from '../constants'
import { ColorOption } from '../style/theme';
import { AffiliateInfo, Asset, ZeroExInstantError } from '../types';
import { analytics } from '../util/analytics';
+import { errorReporter } from '../util/error_reporter';
import { gasPriceEstimator } from '../util/gas_price_estimator';
import { util } from '../util/util';
@@ -31,7 +32,7 @@ export interface BuyButtonProps {
onBuyFailure: (buyQuote: BuyQuote, txHash: string) => void;
}
-export class BuyButton extends React.Component<BuyButtonProps> {
+export class BuyButton extends React.PureComponent<BuyButtonProps> {
public static defaultProps = {
onClick: util.boundNoop,
onBuySuccess: util.boundNoop,
@@ -82,13 +83,18 @@ export class BuyButton extends React.Component<BuyButtonProps> {
});
} catch (e) {
if (e instanceof Error) {
- if (e.message === AssetBuyerError.SignatureRequestDenied) {
+ if (e.message === AssetBuyerError.TransactionValueTooLow) {
+ analytics.trackBuySimulationFailed(buyQuote);
+ this.props.onValidationFail(buyQuote, AssetBuyerError.TransactionValueTooLow);
+ return;
+ } else if (e.message === AssetBuyerError.SignatureRequestDenied) {
analytics.trackBuySignatureDenied(buyQuote);
this.props.onSignatureDenied(buyQuote);
return;
- } else if (e.message === AssetBuyerError.TransactionValueTooLow) {
- analytics.trackBuySimulationFailed(buyQuote);
- this.props.onValidationFail(buyQuote, AssetBuyerError.TransactionValueTooLow);
+ } else {
+ errorReporter.report(e);
+ analytics.trackBuyUnknownError(buyQuote, e.message);
+ this.props.onValidationFail(buyQuote, ZeroExInstantError.CouldNotSubmitTransaction);
return;
}
}
diff --git a/packages/instant/src/components/buy_order_progress.tsx b/packages/instant/src/components/buy_order_progress.tsx
index a19f5a4d0..11ac5d5e0 100644
--- a/packages/instant/src/components/buy_order_progress.tsx
+++ b/packages/instant/src/components/buy_order_progress.tsx
@@ -31,3 +31,5 @@ export const BuyOrderProgress: React.StatelessComponent<BuyOrderProgressProps> =
}
return null;
};
+
+BuyOrderProgress.displayName = 'BuyOrderProgress';
diff --git a/packages/instant/src/components/buy_order_state_buttons.tsx b/packages/instant/src/components/buy_order_state_buttons.tsx
index 833818900..1214559d1 100644
--- a/packages/instant/src/components/buy_order_state_buttons.tsx
+++ b/packages/instant/src/components/buy_order_state_buttons.tsx
@@ -71,3 +71,5 @@ export const BuyOrderStateButtons: React.StatelessComponent<BuyOrderStateButtonP
/>
);
};
+
+BuyOrderStateButtons.displayName = 'BuyOrderStateButtons';
diff --git a/packages/instant/src/components/erc20_asset_amount_input.tsx b/packages/instant/src/components/erc20_asset_amount_input.tsx
index 4da82eb73..0418f9165 100644
--- a/packages/instant/src/components/erc20_asset_amount_input.tsx
+++ b/packages/instant/src/components/erc20_asset_amount_input.tsx
@@ -31,7 +31,7 @@ export interface ERC20AssetAmountInputState {
currentFontSizePx: number;
}
-export class ERC20AssetAmountInput extends React.Component<ERC20AssetAmountInputProps, ERC20AssetAmountInputState> {
+export class ERC20AssetAmountInput extends React.PureComponent<ERC20AssetAmountInputProps, ERC20AssetAmountInputState> {
public static defaultProps = {
onChange: util.boundNoop,
isDisabled: false,
diff --git a/packages/instant/src/components/erc20_token_selector.tsx b/packages/instant/src/components/erc20_token_selector.tsx
index cb8a8c797..a26fb5cf5 100644
--- a/packages/instant/src/components/erc20_token_selector.tsx
+++ b/packages/instant/src/components/erc20_token_selector.tsx
@@ -21,12 +21,12 @@ export interface ERC20TokenSelectorState {
searchQuery: string;
}
-export class ERC20TokenSelector extends React.Component<ERC20TokenSelectorProps> {
+export class ERC20TokenSelector extends React.PureComponent<ERC20TokenSelectorProps> {
public state: ERC20TokenSelectorState = {
searchQuery: '',
};
public render(): React.ReactNode {
- const { tokens, onTokenSelect } = this.props;
+ const { tokens } = this.props;
return (
<Container height="100%">
<Container marginBottom="10px">
@@ -42,12 +42,11 @@ export class ERC20TokenSelector extends React.Component<ERC20TokenSelectorProps>
tabIndex={-1}
/>
<Container overflow="scroll" height="calc(100% - 90px)" marginTop="10px">
- {_.map(tokens, token => {
- if (!this._isTokenQueryMatch(token)) {
- return null;
- }
- return <TokenSelectorRow key={token.assetData} token={token} onClick={onTokenSelect} />;
- })}
+ <TokenRowFilter
+ tokens={tokens}
+ onClick={this._handleTokenClick}
+ searchQuery={this.state.searchQuery}
+ />
</Container>
</Container>
);
@@ -59,8 +58,32 @@ export class ERC20TokenSelector extends React.Component<ERC20TokenSelectorProps>
});
analytics.trackTokenSelectorSearched(searchQuery);
};
+ private readonly _handleTokenClick = (token: ERC20Asset): void => {
+ this.props.onTokenSelect(token);
+ };
+}
+
+interface TokenRowFilterProps {
+ tokens: ERC20Asset[];
+ onClick: (token: ERC20Asset) => void;
+ searchQuery: string;
+}
+
+class TokenRowFilter extends React.Component<TokenRowFilterProps> {
+ public render(): React.ReactNode {
+ return _.map(this.props.tokens, token => {
+ if (!this._isTokenQueryMatch(token)) {
+ return null;
+ }
+ return <TokenSelectorRow key={token.assetData} token={token} onClick={this.props.onClick} />;
+ });
+ }
+ public shouldComponentUpdate(nextProps: TokenRowFilterProps): boolean {
+ const arePropsDeeplyEqual = _.isEqual(nextProps, this.props);
+ return !arePropsDeeplyEqual;
+ }
private readonly _isTokenQueryMatch = (token: ERC20Asset): boolean => {
- const { searchQuery } = this.state;
+ const { searchQuery } = this.props;
const searchQueryLowerCase = searchQuery.toLowerCase().trim();
if (searchQueryLowerCase === '') {
return true;
@@ -76,7 +99,7 @@ interface TokenSelectorRowProps {
onClick: (token: ERC20Asset) => void;
}
-class TokenSelectorRow extends React.Component<TokenSelectorRowProps> {
+class TokenSelectorRow extends React.PureComponent<TokenSelectorRowProps> {
public render(): React.ReactNode {
const { token } = this.props;
const circleColor = token.metaData.primaryColor || 'black';
@@ -131,21 +154,23 @@ const getTokenIcon = (symbol: string): React.StatelessComponent | undefined => {
}
};
-const TokenSelectorRowIcon: React.StatelessComponent<TokenSelectorRowIconProps> = props => {
- const { token } = props;
- const iconUrlIfExists = token.metaData.iconUrl;
+class TokenSelectorRowIcon extends React.PureComponent<TokenSelectorRowIconProps> {
+ public render(): React.ReactNode {
+ const { token } = this.props;
+ const iconUrlIfExists = token.metaData.iconUrl;
- const TokenIcon = getTokenIcon(token.metaData.symbol);
- const displaySymbol = assetUtils.bestNameForAsset(token);
- if (!_.isUndefined(iconUrlIfExists)) {
- return <img src={iconUrlIfExists} />;
- } else if (!_.isUndefined(TokenIcon)) {
- return <TokenIcon />;
- } else {
- return (
- <Text fontColor={ColorOption.white} fontSize="8px">
- {displaySymbol}
- </Text>
- );
+ const TokenIcon = getTokenIcon(token.metaData.symbol);
+ const displaySymbol = assetUtils.bestNameForAsset(token);
+ if (!_.isUndefined(iconUrlIfExists)) {
+ return <img src={iconUrlIfExists} />;
+ } else if (!_.isUndefined(TokenIcon)) {
+ return <TokenIcon />;
+ } else {
+ return (
+ <Text fontColor={ColorOption.white} fontSize="8px">
+ {displaySymbol}
+ </Text>
+ );
+ }
}
-};
+}
diff --git a/packages/instant/src/components/install_wallet_panel_content.tsx b/packages/instant/src/components/install_wallet_panel_content.tsx
index 481d82da0..1af3dafbb 100644
--- a/packages/instant/src/components/install_wallet_panel_content.tsx
+++ b/packages/instant/src/components/install_wallet_panel_content.tsx
@@ -18,7 +18,7 @@ import { Button } from './ui/button';
export interface InstallWalletPanelContentProps {}
-export class InstallWalletPanelContent extends React.Component<InstallWalletPanelContentProps> {
+export class InstallWalletPanelContent extends React.PureComponent<InstallWalletPanelContentProps> {
public render(): React.ReactNode {
const panelProps = this._getStandardPanelContentProps();
return <StandardPanelContent {...panelProps} />;
diff --git a/packages/instant/src/components/instant_heading.tsx b/packages/instant/src/components/instant_heading.tsx
index 5b1f9592d..e943f68d7 100644
--- a/packages/instant/src/components/instant_heading.tsx
+++ b/packages/instant/src/components/instant_heading.tsx
@@ -28,7 +28,7 @@ const ICON_WIDTH = 34;
const ICON_HEIGHT = 34;
const ICON_COLOR = ColorOption.white;
-export class InstantHeading extends React.Component<InstantHeadingProps, {}> {
+export class InstantHeading extends React.PureComponent<InstantHeadingProps, {}> {
public render(): React.ReactNode {
const iconOrAmounts = this._renderIcon() || this._renderAmountsSection();
return (
diff --git a/packages/instant/src/components/order_details.tsx b/packages/instant/src/components/order_details.tsx
index 9c10ef9e6..4db20b13e 100644
--- a/packages/instant/src/components/order_details.tsx
+++ b/packages/instant/src/components/order_details.tsx
@@ -26,7 +26,7 @@ export interface OrderDetailsProps {
onBaseCurrencySwitchEth: () => void;
onBaseCurrencySwitchUsd: () => void;
}
-export class OrderDetails extends React.Component<OrderDetailsProps> {
+export class OrderDetails extends React.PureComponent<OrderDetailsProps> {
public render(): React.ReactNode {
const shouldShowUsdError = this.props.baseCurrency === BaseCurrency.USD && this._hadErrorFetchingUsdPrice();
return (
@@ -200,7 +200,7 @@ export interface OrderDetailsRowProps {
primaryValue: React.ReactNode;
secondaryValue?: React.ReactNode;
}
-export class OrderDetailsRow extends React.Component<OrderDetailsRowProps, {}> {
+export class OrderDetailsRow extends React.PureComponent<OrderDetailsRowProps, {}> {
public render(): React.ReactNode {
return (
<Container padding="10px 0px" borderTop="1px dashed" borderColor={ColorOption.feintGrey}>
diff --git a/packages/instant/src/components/payment_method.tsx b/packages/instant/src/components/payment_method.tsx
index abadf4bd6..ada9f7bab 100644
--- a/packages/instant/src/components/payment_method.tsx
+++ b/packages/instant/src/components/payment_method.tsx
@@ -24,7 +24,7 @@ export interface PaymentMethodProps {
onUnlockWalletClick: () => void;
}
-export class PaymentMethod extends React.Component<PaymentMethodProps> {
+export class PaymentMethod extends React.PureComponent<PaymentMethodProps> {
public render(): React.ReactNode {
return (
<Container width="100%" height="120px" padding="20px 20px 0px 20px">
diff --git a/packages/instant/src/components/payment_method_dropdown.tsx b/packages/instant/src/components/payment_method_dropdown.tsx
index 872ac0831..e463e3eae 100644
--- a/packages/instant/src/components/payment_method_dropdown.tsx
+++ b/packages/instant/src/components/payment_method_dropdown.tsx
@@ -16,7 +16,7 @@ export interface PaymentMethodDropdownProps {
network: Network;
}
-export class PaymentMethodDropdown extends React.Component<PaymentMethodDropdownProps> {
+export class PaymentMethodDropdown extends React.PureComponent<PaymentMethodDropdownProps> {
public render(): React.ReactNode {
const { accountAddress, accountEthBalanceInWei } = this.props;
const value = format.ethAddress(accountAddress);
diff --git a/packages/instant/src/components/placing_order_button.tsx b/packages/instant/src/components/placing_order_button.tsx
index 2516b90b1..528a305dc 100644
--- a/packages/instant/src/components/placing_order_button.tsx
+++ b/packages/instant/src/components/placing_order_button.tsx
@@ -14,3 +14,5 @@ export const PlacingOrderButton: React.StatelessComponent<{}> = props => (
Placing Order&hellip;
</Button>
);
+
+PlacingOrderButton.displayName = 'PlacingOrderButton';
diff --git a/packages/instant/src/components/scaling_amount_input.tsx b/packages/instant/src/components/scaling_amount_input.tsx
index 4feb0502d..7dc1fdc0c 100644
--- a/packages/instant/src/components/scaling_amount_input.tsx
+++ b/packages/instant/src/components/scaling_amount_input.tsx
@@ -26,7 +26,7 @@ interface ScalingAmountInputState {
}
const { stringToMaybeBigNumber, areMaybeBigNumbersEqual } = maybeBigNumberUtil;
-export class ScalingAmountInput extends React.Component<ScalingAmountInputProps, ScalingAmountInputState> {
+export class ScalingAmountInput extends React.PureComponent<ScalingAmountInputProps, ScalingAmountInputState> {
public static defaultProps = {
onAmountChange: util.boundNoop,
onFontSizeChange: util.boundNoop,
diff --git a/packages/instant/src/components/scaling_input.tsx b/packages/instant/src/components/scaling_input.tsx
index 00aea37da..c31de1fb5 100644
--- a/packages/instant/src/components/scaling_input.tsx
+++ b/packages/instant/src/components/scaling_input.tsx
@@ -51,7 +51,7 @@ const defaultScalingSettings: ScalingSettings = {
additionalInputSpaceInCh: 0.4,
};
-export class ScalingInput extends React.Component<ScalingInputProps> {
+export class ScalingInput extends React.PureComponent<ScalingInputProps> {
public static defaultProps = {
onChange: util.boundNoop,
onFontSizeChange: util.boundNoop,
diff --git a/packages/instant/src/components/secondary_button.tsx b/packages/instant/src/components/secondary_button.tsx
index 705390e28..0714ce287 100644
--- a/packages/instant/src/components/secondary_button.tsx
+++ b/packages/instant/src/components/secondary_button.tsx
@@ -24,3 +24,4 @@ export const SecondaryButton: React.StatelessComponent<SecondaryButtonProps> = p
SecondaryButton.defaultProps = {
width: '100%',
};
+SecondaryButton.displayName = 'SecondaryButton';
diff --git a/packages/instant/src/components/section_header.tsx b/packages/instant/src/components/section_header.tsx
index d0974ebdc..2185b67ba 100644
--- a/packages/instant/src/components/section_header.tsx
+++ b/packages/instant/src/components/section_header.tsx
@@ -18,3 +18,4 @@ export const SectionHeader: React.StatelessComponent<SectionHeaderProps> = props
</Text>
);
};
+SectionHeader.displayName = 'SectionHeader';
diff --git a/packages/instant/src/components/sliding_error.tsx b/packages/instant/src/components/sliding_error.tsx
index b59e2a905..c7c6732cf 100644
--- a/packages/instant/src/components/sliding_error.tsx
+++ b/packages/instant/src/components/sliding_error.tsx
@@ -38,6 +38,8 @@ export const Error: React.StatelessComponent<ErrorProps> = props => (
</Container>
);
+Error.displayName = 'Error';
+
export interface SlidingErrorProps extends ErrorProps {
animationState: SlideAnimationState;
}
@@ -94,3 +96,5 @@ export const SlidingError: React.StatelessComponent<SlidingErrorProps> = props =
</SlideAnimation>
);
};
+
+SlidingError.displayName = 'SlidingError';
diff --git a/packages/instant/src/components/sliding_panel.tsx b/packages/instant/src/components/sliding_panel.tsx
index 7f9037049..9b09a0d80 100644
--- a/packages/instant/src/components/sliding_panel.tsx
+++ b/packages/instant/src/components/sliding_panel.tsx
@@ -26,42 +26,48 @@ export const Panel: React.StatelessComponent<PanelProps> = ({ children, onClose
</Container>
);
+Panel.displayName = 'Panel';
+
export interface SlidingPanelProps extends PanelProps {
animationState: SlideAnimationState;
+ onAnimationEnd?: () => void;
}
-export const SlidingPanel: React.StatelessComponent<SlidingPanelProps> = props => {
- if (props.animationState === 'none') {
- return null;
+export class SlidingPanel extends React.PureComponent<SlidingPanelProps> {
+ public render(): React.ReactNode {
+ if (this.props.animationState === 'none') {
+ return null;
+ }
+ const { animationState, onAnimationEnd, ...rest } = this.props;
+ const slideAmount = '100%';
+ const slideUpSettings: PositionAnimationSettings = {
+ duration: '0.3s',
+ timingFunction: 'ease-in-out',
+ top: {
+ from: slideAmount,
+ to: '0px',
+ },
+ position: 'absolute',
+ };
+ const slideDownSettings: PositionAnimationSettings = {
+ duration: '0.3s',
+ timingFunction: 'ease-out',
+ top: {
+ from: '0px',
+ to: slideAmount,
+ },
+ position: 'absolute',
+ };
+ return (
+ <SlideAnimation
+ slideInSettings={slideUpSettings}
+ slideOutSettings={slideDownSettings}
+ animationState={animationState}
+ height="100%"
+ onAnimationEnd={onAnimationEnd}
+ >
+ <Panel {...rest} />
+ </SlideAnimation>
+ );
}
- const { animationState, ...rest } = props;
- const slideAmount = '100%';
- const slideUpSettings: PositionAnimationSettings = {
- duration: '0.3s',
- timingFunction: 'ease-in-out',
- top: {
- from: slideAmount,
- to: '0px',
- },
- position: 'absolute',
- };
- const slideDownSettings: PositionAnimationSettings = {
- duration: '0.3s',
- timingFunction: 'ease-out',
- top: {
- from: '0px',
- to: slideAmount,
- },
- position: 'absolute',
- };
- return (
- <SlideAnimation
- slideInSettings={slideUpSettings}
- slideOutSettings={slideDownSettings}
- animationState={animationState}
- height="100%"
- >
- <Panel {...rest} />
- </SlideAnimation>
- );
-};
+}
diff --git a/packages/instant/src/components/standard_panel_content.tsx b/packages/instant/src/components/standard_panel_content.tsx
index 79b7bff24..f2987df82 100644
--- a/packages/instant/src/components/standard_panel_content.tsx
+++ b/packages/instant/src/components/standard_panel_content.tsx
@@ -71,3 +71,5 @@ export const StandardPanelContent: React.StatelessComponent<StandardPanelContent
<Container>{action}</Container>
</Container>
);
+
+StandardPanelContent.displayName = 'StandardPanelContent';
diff --git a/packages/instant/src/components/standard_sliding_panel.tsx b/packages/instant/src/components/standard_sliding_panel.tsx
index 9f517d273..bcc9d3dce 100644
--- a/packages/instant/src/components/standard_sliding_panel.tsx
+++ b/packages/instant/src/components/standard_sliding_panel.tsx
@@ -9,7 +9,7 @@ export interface StandardSlidingPanelProps extends StandardSlidingPanelSettings
onClose: () => void;
}
-export class StandardSlidingPanel extends React.Component<StandardSlidingPanelProps> {
+export class StandardSlidingPanel extends React.PureComponent<StandardSlidingPanelProps> {
public render(): React.ReactNode {
const { animationState, content, onClose } = this.props;
return (
diff --git a/packages/instant/src/components/time_counter.tsx b/packages/instant/src/components/time_counter.tsx
index f9b68163c..93dc497d5 100644
--- a/packages/instant/src/components/time_counter.tsx
+++ b/packages/instant/src/components/time_counter.tsx
@@ -16,7 +16,7 @@ interface TimeCounterState {
elapsedSeconds: number;
}
-export class TimeCounter extends React.Component<TimeCounterProps, TimeCounterState> {
+export class TimeCounter extends React.PureComponent<TimeCounterProps, TimeCounterState> {
public state = {
elapsedSeconds: 0,
};
diff --git a/packages/instant/src/components/timed_progress_bar.tsx b/packages/instant/src/components/timed_progress_bar.tsx
index fb3927088..b1644b871 100644
--- a/packages/instant/src/components/timed_progress_bar.tsx
+++ b/packages/instant/src/components/timed_progress_bar.tsx
@@ -17,7 +17,7 @@ export interface TimedProgressBarProps {
* Goes from 0% -> PROGRESS_STALL_AT_WIDTH over time of expectedTimeMs
* When hasEnded set to true, goes to 100% through animation of PROGRESS_FINISH_ANIMATION_TIME_MS length of time
*/
-export class TimedProgressBar extends React.Component<TimedProgressBarProps, {}> {
+export class TimedProgressBar extends React.PureComponent<TimedProgressBarProps, {}> {
private readonly _barRef = React.createRef<HTMLDivElement>();
public render(): React.ReactNode {
diff --git a/packages/instant/src/components/ui/container.tsx b/packages/instant/src/components/ui/container.tsx
index 636eb8fc9..58d7d5871 100644
--- a/packages/instant/src/components/ui/container.tsx
+++ b/packages/instant/src/components/ui/container.tsx
@@ -36,6 +36,7 @@ export interface ContainerProps {
cursor?: string;
overflow?: string;
darkenOnHover?: boolean;
+ rawHoverColor?: string;
boxShadowOnHover?: boolean;
flexGrow?: string | number;
}
@@ -87,6 +88,7 @@ export const Container =
background-color: ${props => getBackgroundColor(props.theme, props.backgroundColor, props.rawBackgroundColor)};
border-color: ${props => (props.borderColor ? props.theme[props.borderColor] : 'none')};
&:hover {
+ ${props => (props.rawHoverColor ? `background-color: ${props.rawHoverColor}` : '')}
${props =>
props.darkenOnHover
? `background-color: ${
diff --git a/packages/instant/src/components/ui/dropdown.tsx b/packages/instant/src/components/ui/dropdown.tsx
index 02e87d639..8788d3d59 100644
--- a/packages/instant/src/components/ui/dropdown.tsx
+++ b/packages/instant/src/components/ui/dropdown.tsx
@@ -1,7 +1,8 @@
import * as _ from 'lodash';
+import { transparentize } from 'polished';
import * as React from 'react';
-import { ColorOption, completelyTransparent } from '../../style/theme';
+import { ColorOption, completelyTransparent, ThemeConsumer } from '../../style/theme';
import { zIndex } from '../../style/z_index';
import { Container } from './container';
@@ -26,7 +27,7 @@ export interface DropdownState {
isOpen: boolean;
}
-export class Dropdown extends React.Component<DropdownProps, DropdownState> {
+export class Dropdown extends React.PureComponent<DropdownProps, DropdownState> {
public static defaultProps = {
items: [],
};
@@ -121,20 +122,26 @@ export interface DropdownItemProps extends DropdownItemConfig {
}
export const DropdownItem: React.StatelessComponent<DropdownItemProps> = ({ text, onClick, isLast }) => (
- <Container
- onClick={onClick}
- cursor="pointer"
- darkenOnHover={true}
- backgroundColor={ColorOption.white}
- padding="0.8em"
- borderTop="0"
- border="1px solid"
- borderRadius={isLast ? '0px 0px 4px 4px' : undefined}
- width="100%"
- borderColor={ColorOption.feintGrey}
- >
- <Text fontSize="14px" fontColor={ColorOption.darkGrey}>
- {text}
- </Text>
- </Container>
+ <ThemeConsumer>
+ {theme => (
+ <Container
+ onClick={onClick}
+ cursor="pointer"
+ rawHoverColor={transparentize(0.9, theme[ColorOption.primaryColor])}
+ backgroundColor={ColorOption.white}
+ padding="0.8em"
+ borderTop="0"
+ border="1px solid"
+ borderRadius={isLast ? '0px 0px 4px 4px' : undefined}
+ width="100%"
+ borderColor={ColorOption.feintGrey}
+ >
+ <Text fontSize="14px" fontColor={ColorOption.darkGrey}>
+ {text}
+ </Text>
+ </Container>
+ )}
+ </ThemeConsumer>
);
+
+DropdownItem.displayName = 'DropdownItem';
diff --git a/packages/instant/src/components/wallet_prompt.tsx b/packages/instant/src/components/wallet_prompt.tsx
index c07cfe7b5..10433767f 100644
--- a/packages/instant/src/components/wallet_prompt.tsx
+++ b/packages/instant/src/components/wallet_prompt.tsx
@@ -45,3 +45,5 @@ WalletPrompt.defaultProps = {
primaryColor: ColorOption.darkOrange,
secondaryColor: ColorOption.lightOrange,
};
+
+WalletPrompt.displayName = 'WalletPrompt';
diff --git a/packages/instant/src/components/zero_ex_instant.tsx b/packages/instant/src/components/zero_ex_instant.tsx
index 2267b4dbf..e9cb48e61 100644
--- a/packages/instant/src/components/zero_ex_instant.tsx
+++ b/packages/instant/src/components/zero_ex_instant.tsx
@@ -17,3 +17,5 @@ export const ZeroExInstant: React.StatelessComponent<ZeroExInstantProps> = props
</div>
);
};
+
+ZeroExInstant.displayName = 'ZeroExInstant';
diff --git a/packages/instant/src/components/zero_ex_instant_container.tsx b/packages/instant/src/components/zero_ex_instant_container.tsx
index 0337c7714..e8c64d5d1 100644
--- a/packages/instant/src/components/zero_ex_instant_container.tsx
+++ b/packages/instant/src/components/zero_ex_instant_container.tsx
@@ -24,7 +24,10 @@ export interface ZeroExInstantContainerState {
tokenSelectionPanelAnimationState: SlideAnimationState;
}
-export class ZeroExInstantContainer extends React.Component<ZeroExInstantContainerProps, ZeroExInstantContainerState> {
+export class ZeroExInstantContainer extends React.PureComponent<
+ ZeroExInstantContainerProps,
+ ZeroExInstantContainerState
+> {
public state = {
tokenSelectionPanelAnimationState: 'none' as SlideAnimationState,
};
@@ -60,6 +63,7 @@ export class ZeroExInstantContainer extends React.Component<ZeroExInstantContain
<SlidingPanel
animationState={this.state.tokenSelectionPanelAnimationState}
onClose={this._handlePanelCloseClickedX}
+ onAnimationEnd={this._handleSlidingPanelAnimationEnd}
>
<AvailableERC20TokenSelector onTokenSelect={this._handlePanelCloseAfterChose} />
</SlidingPanel>
@@ -98,4 +102,11 @@ export class ZeroExInstantContainer extends React.Component<ZeroExInstantContain
tokenSelectionPanelAnimationState: 'slidOut',
});
};
+ private readonly _handleSlidingPanelAnimationEnd = (): void => {
+ if (this.state.tokenSelectionPanelAnimationState === 'slidOut') {
+ // When the slidOut animation completes, don't keep the panel mounted.
+ // Performance optimization
+ this.setState({ tokenSelectionPanelAnimationState: 'none' });
+ }
+ };
}
diff --git a/packages/instant/src/components/zero_ex_instant_overlay.tsx b/packages/instant/src/components/zero_ex_instant_overlay.tsx
index 96e560691..38a716091 100644
--- a/packages/instant/src/components/zero_ex_instant_overlay.tsx
+++ b/packages/instant/src/components/zero_ex_instant_overlay.tsx
@@ -49,3 +49,5 @@ export const ZeroExInstantOverlay: React.StatelessComponent<ZeroExInstantOverlay
</ZeroExInstantProvider>
);
};
+
+ZeroExInstantOverlay.displayName = 'ZeroExInstantOverlay';
diff --git a/packages/instant/src/components/zero_ex_instant_provider.tsx b/packages/instant/src/components/zero_ex_instant_provider.tsx
index 2de327cd7..ec8e82ee3 100644
--- a/packages/instant/src/components/zero_ex_instant_provider.tsx
+++ b/packages/instant/src/components/zero_ex_instant_provider.tsx
@@ -21,7 +21,7 @@ import { providerStateFactory } from '../util/provider_state_factory';
export type ZeroExInstantProviderProps = ZeroExInstantBaseConfig;
-export class ZeroExInstantProvider extends React.Component<ZeroExInstantProviderProps> {
+export class ZeroExInstantProvider extends React.PureComponent<ZeroExInstantProviderProps> {
private readonly _store: Store;
private _accountUpdateHeartbeat?: Heartbeater;
private _buyQuoteHeartbeat?: Heartbeater;
diff --git a/packages/instant/src/constants.ts b/packages/instant/src/constants.ts
index 975dfcbea..22f0cb6a4 100644
--- a/packages/instant/src/constants.ts
+++ b/packages/instant/src/constants.ts
@@ -72,5 +72,6 @@ export const PROVIDER_TYPE_TO_NAME: { [key in ProviderType]: string } = {
[ProviderType.Mist]: 'Mist',
[ProviderType.CoinbaseWallet]: 'Coinbase Wallet',
[ProviderType.Parity]: 'Parity',
+ [ProviderType.TrustWallet]: 'Trust Wallet',
[ProviderType.Fallback]: 'Fallback',
};
diff --git a/packages/instant/src/containers/latest_error.tsx b/packages/instant/src/containers/latest_error.tsx
index 0d4349124..6da4558ef 100644
--- a/packages/instant/src/containers/latest_error.tsx
+++ b/packages/instant/src/containers/latest_error.tsx
@@ -14,7 +14,7 @@ import { zIndex } from '../style/z_index';
import { Asset, DisplayStatus, Omit, SlideAnimationState } from '../types';
import { errorFlasher } from '../util/error_flasher';
-export interface LatestErrorComponentProps {
+interface LatestErrorComponentProps {
asset?: Asset;
latestErrorMessage?: string;
animationState: SlideAnimationState;
@@ -22,7 +22,7 @@ export interface LatestErrorComponentProps {
onOverlayClick: () => void;
}
-export const LatestErrorComponent: React.StatelessComponent<LatestErrorComponentProps> = props => {
+const LatestErrorComponent: React.StatelessComponent<LatestErrorComponentProps> = props => {
if (!props.latestErrorMessage) {
// Render a hidden SlidingError such that instant does not move when a real error is rendered.
return (
diff --git a/packages/instant/src/containers/selected_asset_buy_order_state_buttons.ts b/packages/instant/src/containers/selected_asset_buy_order_state_buttons.ts
index 80943a96f..4da99cf04 100644
--- a/packages/instant/src/containers/selected_asset_buy_order_state_buttons.ts
+++ b/packages/instant/src/containers/selected_asset_buy_order_state_buttons.ts
@@ -95,6 +95,9 @@ const mapDispatchToProps = (
if (error === ZeroExInstantError.InsufficientETH) {
const errorMessage = "You don't have enough ETH";
errorFlasher.flashNewErrorMessage(dispatch, errorMessage);
+ } else if (error === ZeroExInstantError.CouldNotSubmitTransaction) {
+ const errorMessage = 'Could not submit transaction';
+ errorFlasher.flashNewErrorMessage(dispatch, errorMessage);
} else {
errorFlasher.flashNewErrorMessage(dispatch);
}
diff --git a/packages/instant/src/types.ts b/packages/instant/src/types.ts
index e7c920f36..ae672c919 100644
--- a/packages/instant/src/types.ts
+++ b/packages/instant/src/types.ts
@@ -96,6 +96,7 @@ export enum Network {
export enum ZeroExInstantError {
AssetMetaDataNotAvailable = 'ASSET_META_DATA_NOT_AVAILABLE',
InsufficientETH = 'INSUFFICIENT_ETH',
+ CouldNotSubmitTransaction = 'COULD_NOT_SUBMIT_TRANSACTION',
}
export type SimpleHandler = () => void;
@@ -181,6 +182,7 @@ export enum ProviderType {
Mist = 'MIST',
CoinbaseWallet = 'COINBASE_WALLET',
Cipher = 'CIPHER',
+ TrustWallet = 'TRUST_WALLET',
Fallback = 'FALLBACK',
}
diff --git a/packages/instant/src/util/analytics.ts b/packages/instant/src/util/analytics.ts
index 6c63907dc..4faeaaf5a 100644
--- a/packages/instant/src/util/analytics.ts
+++ b/packages/instant/src/util/analytics.ts
@@ -46,6 +46,7 @@ enum EventNames {
BUY_STARTED = 'Buy - Started',
BUY_SIGNATURE_DENIED = 'Buy - Signature Denied',
BUY_SIMULATION_FAILED = 'Buy - Simulation Failed',
+ BUY_UNKNOWN_ERROR = 'Buy - Unknown Error',
BUY_TX_SUBMITTED = 'Buy - Tx Submitted',
BUY_TX_SUCCEEDED = 'Buy - Tx Succeeded',
BUY_TX_FAILED = 'Buy - Tx Failed',
@@ -189,6 +190,11 @@ export const analytics = {
trackingEventFnWithPayload(EventNames.BUY_SIGNATURE_DENIED)(buyQuoteEventProperties(buyQuote)),
trackBuySimulationFailed: (buyQuote: BuyQuote) =>
trackingEventFnWithPayload(EventNames.BUY_SIMULATION_FAILED)(buyQuoteEventProperties(buyQuote)),
+ trackBuyUnknownError: (buyQuote: BuyQuote, errorMessage: string) =>
+ trackingEventFnWithPayload(EventNames.BUY_UNKNOWN_ERROR)({
+ ...buyQuoteEventProperties(buyQuote),
+ errorMessage,
+ }),
trackBuyTxSubmitted: (buyQuote: BuyQuote, txHash: string, startTimeUnix: number, expectedEndTimeUnix: number) =>
trackingEventFnWithPayload(EventNames.BUY_TX_SUBMITTED)({
...buyQuoteEventProperties(buyQuote),
diff --git a/packages/instant/src/util/env.ts b/packages/instant/src/util/env.ts
index 0fda0cc0e..aedf4f5d6 100644
--- a/packages/instant/src/util/env.ts
+++ b/packages/instant/src/util/env.ts
@@ -44,6 +44,8 @@ export const envUtil = {
getProviderType(provider: Provider): ProviderType | undefined {
if (provider.constructor.name === 'EthereumProvider') {
return ProviderType.Mist;
+ } else if ((provider as any).isTrust) {
+ return ProviderType.TrustWallet;
} else if ((provider as any).isParity) {
return ProviderType.Parity;
} else if ((provider as any).isMetaMask) {