diff options
Diffstat (limited to 'packages/instant/src/components')
-rw-r--r-- | packages/instant/src/components/buy_button.tsx | 43 | ||||
-rw-r--r-- | packages/instant/src/components/buy_order_state_button.tsx | 13 | ||||
-rw-r--r-- | packages/instant/src/components/instant_heading.tsx | 15 |
3 files changed, 49 insertions, 22 deletions
diff --git a/packages/instant/src/components/buy_button.tsx b/packages/instant/src/components/buy_button.tsx index 9c42f3d87..a70269dde 100644 --- a/packages/instant/src/components/buy_button.tsx +++ b/packages/instant/src/components/buy_button.tsx @@ -1,7 +1,8 @@ -import { AssetBuyer, BuyQuote } from '@0x/asset-buyer'; +import { AssetBuyer, AssetBuyerError, BuyQuote } from '@0x/asset-buyer'; import * as _ from 'lodash'; import * as React from 'react'; +import { WEB_3_WRAPPER_TRANSACTION_FAILED_ERROR_MSG_PREFIX } from '../constants'; import { ColorOption } from '../style/theme'; import { util } from '../util/util'; import { web3Wrapper } from '../util/web3_wrapper'; @@ -11,9 +12,11 @@ import { Button, Text } from './ui'; export interface BuyButtonProps { buyQuote?: BuyQuote; assetBuyer?: AssetBuyer; - onClick: (buyQuote: BuyQuote) => void; - onBuySuccess: (buyQuote: BuyQuote, txnHash: string) => void; - onBuyFailure: (buyQuote: BuyQuote, tnxHash?: string) => void; + onAwaitingSignature: (buyQuote: BuyQuote) => void; + onSignatureDenied: (buyQuote: BuyQuote, preventedError: Error) => void; + onBuyProcessing: (buyQuote: BuyQuote, txHash: string) => void; + onBuySuccess: (buyQuote: BuyQuote, txHash: string) => void; + onBuyFailure: (buyQuote: BuyQuote, txHash: string) => void; } export class BuyButton extends React.Component<BuyButtonProps> { @@ -34,17 +37,33 @@ export class BuyButton extends React.Component<BuyButtonProps> { } private readonly _handleClick = async () => { // The button is disabled when there is no buy quote anyway. - if (_.isUndefined(this.props.buyQuote) || _.isUndefined(this.props.assetBuyer)) { + const { buyQuote, assetBuyer } = this.props; + if (_.isUndefined(buyQuote) || _.isUndefined(assetBuyer)) { return; } - this.props.onClick(this.props.buyQuote); - let txnHash; + + let txHash: string | undefined; + this.props.onAwaitingSignature(buyQuote); + try { + txHash = await assetBuyer.executeBuyQuoteAsync(buyQuote); + } catch (e) { + if (e instanceof Error && e.message === AssetBuyerError.SignatureRequestDenied) { + this.props.onSignatureDenied(buyQuote, e); + return; + } + throw e; + } + + this.props.onBuyProcessing(buyQuote, txHash); try { - txnHash = await this.props.assetBuyer.executeBuyQuoteAsync(this.props.buyQuote); - const txnReceipt = await web3Wrapper.awaitTransactionSuccessAsync(txnHash); - this.props.onBuySuccess(this.props.buyQuote, txnReceipt.transactionHash); - } catch { - this.props.onBuyFailure(this.props.buyQuote, txnHash); + await web3Wrapper.awaitTransactionSuccessAsync(txHash); + } catch (e) { + if (e instanceof Error && e.message.startsWith(WEB_3_WRAPPER_TRANSACTION_FAILED_ERROR_MSG_PREFIX)) { + this.props.onBuyFailure(buyQuote, txHash); + return; + } + throw e; } + this.props.onBuySuccess(buyQuote, txHash); }; } diff --git a/packages/instant/src/components/buy_order_state_button.tsx b/packages/instant/src/components/buy_order_state_button.tsx index 5bc965c7d..44115e5a1 100644 --- a/packages/instant/src/components/buy_order_state_button.tsx +++ b/packages/instant/src/components/buy_order_state_button.tsx @@ -4,18 +4,21 @@ import { PlacingOrderButton } from '../components/placing_order_button'; import { SelectedAssetBuyButton } from '../containers/selected_asset_buy_button'; import { SelectedAssetRetryButton } from '../containers/selected_asset_retry_button'; import { SelectedAssetViewTransactionButton } from '../containers/selected_asset_view_transaction_button'; -import { AsyncProcessState } from '../types'; +import { OrderProcessState } from '../types'; export interface BuyOrderStateButtonProps { - buyOrderProcessingState: AsyncProcessState; + buyOrderProcessingState: OrderProcessState; } export const BuyOrderStateButton: React.StatelessComponent<BuyOrderStateButtonProps> = props => { - if (props.buyOrderProcessingState === AsyncProcessState.FAILURE) { + if (props.buyOrderProcessingState === OrderProcessState.FAILURE) { return <SelectedAssetRetryButton />; - } else if (props.buyOrderProcessingState === AsyncProcessState.SUCCESS) { + } else if ( + props.buyOrderProcessingState === OrderProcessState.SUCCESS || + props.buyOrderProcessingState === OrderProcessState.PROCESSING + ) { return <SelectedAssetViewTransactionButton />; - } else if (props.buyOrderProcessingState === AsyncProcessState.PENDING) { + } else if (props.buyOrderProcessingState === OrderProcessState.AWAITING_SIGNATURE) { return <PlacingOrderButton />; } diff --git a/packages/instant/src/components/instant_heading.tsx b/packages/instant/src/components/instant_heading.tsx index ed753a3bd..17ac65429 100644 --- a/packages/instant/src/components/instant_heading.tsx +++ b/packages/instant/src/components/instant_heading.tsx @@ -4,12 +4,13 @@ import * as React from 'react'; import { SelectedAssetAmountInput } from '../containers/selected_asset_amount_input'; import { ColorOption } from '../style/theme'; -import { AsyncProcessState, OrderState } from '../types'; +import { AsyncProcessState, OrderProcessState, OrderState } from '../types'; import { format } from '../util/format'; import { AmountPlaceholder } from './amount_placeholder'; import { Container, Flex, Text } from './ui'; import { Icon } from './ui/icon'; +import { Spinner } from './ui/spinner'; export interface InstantHeadingProps { selectedAssetAmount?: BigNumber; @@ -68,9 +69,11 @@ export class InstantHeading extends React.Component<InstantHeadingProps, {}> { private _renderIcon(): React.ReactNode { const processState = this.props.buyOrderState.processState; - if (processState === AsyncProcessState.FAILURE) { + if (processState === OrderProcessState.FAILURE) { return <Icon icon={'failed'} width={ICON_WIDTH} height={ICON_HEIGHT} color={ICON_COLOR} />; - } else if (processState === AsyncProcessState.SUCCESS) { + } else if (processState === OrderProcessState.PROCESSING) { + return <Spinner widthPx={ICON_HEIGHT} heightPx={ICON_HEIGHT} />; + } else if (processState === OrderProcessState.SUCCESS) { return <Icon icon={'success'} width={ICON_WIDTH} height={ICON_HEIGHT} color={ICON_COLOR} />; } return undefined; @@ -78,9 +81,11 @@ export class InstantHeading extends React.Component<InstantHeadingProps, {}> { private _renderTopText(): React.ReactNode { const processState = this.props.buyOrderState.processState; - if (processState === AsyncProcessState.FAILURE) { + if (processState === OrderProcessState.FAILURE) { return 'Order failed'; - } else if (processState === AsyncProcessState.SUCCESS) { + } else if (processState === OrderProcessState.PROCESSING) { + return 'Processing Order...'; + } else if (processState === OrderProcessState.SUCCESS) { return 'Tokens received!'; } |