diff options
Diffstat (limited to 'packages/website/ts/components/generate_order/generate_order_form.tsx')
-rw-r--r-- | packages/website/ts/components/generate_order/generate_order_form.tsx | 385 |
1 files changed, 0 insertions, 385 deletions
diff --git a/packages/website/ts/components/generate_order/generate_order_form.tsx b/packages/website/ts/components/generate_order/generate_order_form.tsx deleted file mode 100644 index 0f70aa18f..000000000 --- a/packages/website/ts/components/generate_order/generate_order_form.tsx +++ /dev/null @@ -1,385 +0,0 @@ -import { assetDataUtils, generatePseudoRandomSalt, orderHashUtils } from '@0x/order-utils'; -import { colors } from '@0x/react-shared'; -import { Order as ZeroExOrder } from '@0x/types'; -import { BigNumber, logUtils } from '@0x/utils'; -import * as _ from 'lodash'; -import Dialog from 'material-ui/Dialog'; -import Divider from 'material-ui/Divider'; -import * as React from 'react'; -import { Blockchain } from 'ts/blockchain'; -import { ExpirationInput } from 'ts/components/inputs/expiration_input'; -import { HashInput } from 'ts/components/inputs/hash_input'; -import { IdenticonAddressInput } from 'ts/components/inputs/identicon_address_input'; -import { TokenAmountInput } from 'ts/components/inputs/token_amount_input'; -import { TokenInput } from 'ts/components/inputs/token_input'; -import { OrderJSON } from 'ts/components/order_json'; -import { Alert } from 'ts/components/ui/alert'; -import { HelpTooltip } from 'ts/components/ui/help_tooltip'; -import { LifeCycleRaisedButton } from 'ts/components/ui/lifecycle_raised_button'; -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, - PortalOrder, - Side, - SideToAssetToken, - Token, - TokenByAddress, -} from 'ts/types'; -import { analytics } from 'ts/utils/analytics'; -import { constants } from 'ts/utils/constants'; -import { errorReporter } from 'ts/utils/error_reporter'; -import { utils } from 'ts/utils/utils'; - -enum SigningState { - Unsigned, - Signing, - Signed, -} - -interface GenerateOrderFormProps { - blockchain: Blockchain; - blockchainErr: BlockchainErrs; - blockchainIsLoaded: boolean; - dispatcher: Dispatcher; - hashData: HashData; - orderExpiryTimestamp: BigNumber; - networkId: number; - userAddress: string; - orderSignature: string; - orderTakerAddress: string; - orderSalt: BigNumber; - sideToAssetToken: SideToAssetToken; - tokenByAddress: TokenByAddress; - lastForceTokenStateRefetch: number; - isFullWidth?: boolean; - shouldHideHeader?: boolean; -} - -interface GenerateOrderFormState { - globalErrMsg: string; - shouldShowIncompleteErrs: boolean; - signingState: SigningState; -} - -export class GenerateOrderForm extends React.Component<GenerateOrderFormProps, GenerateOrderFormState> { - public static defaultProps: Partial<GenerateOrderFormProps> = { - isFullWidth: false, - shouldHideHeader: false, - }; - constructor(props: GenerateOrderFormProps) { - super(props); - this.state = { - globalErrMsg: '', - shouldShowIncompleteErrs: false, - signingState: SigningState.Unsigned, - }; - } - public componentDidMount(): void { - window.scrollTo(0, 0); - } - public render(): React.ReactNode { - const dispatcher = this.props.dispatcher; - const depositTokenAddress = this.props.sideToAssetToken[Side.Deposit].address; - const depositToken = this.props.tokenByAddress[depositTokenAddress]; - const receiveTokenAddress = this.props.sideToAssetToken[Side.Receive].address; - const receiveToken = this.props.tokenByAddress[receiveTokenAddress]; - const takerExplanation = - 'If a taker is specified, only they are<br> \ - allowed to fill this order. If no taker is<br> \ - specified, anyone is able to fill it.'; - const exchangeContractIfExists = this.props.blockchain.getExchangeContractAddressIfExists(); - const initialTakerAddress = - this.props.orderTakerAddress === constants.NULL_ADDRESS ? '' : this.props.orderTakerAddress; - const rootClassName = this.props.isFullWidth ? 'clearfix mb2' : 'clearfix mb2 lg-px4 md-px4 sm-px2'; - return ( - <div className={rootClassName}> - {!this.props.shouldHideHeader && ( - <div> - <h3>Generate an order</h3> - <Divider /> - </div> - )} - <div className="mx-auto" style={{ maxWidth: 580 }}> - <div className="pt3"> - <div className="mx-auto clearfix"> - <div className="lg-col md-col lg-col-5 md-col-5 sm-col sm-col-5 sm-pb2"> - <TokenInput - userAddress={this.props.userAddress} - blockchain={this.props.blockchain} - blockchainErr={this.props.blockchainErr} - dispatcher={this.props.dispatcher} - label="Selling" - side={Side.Deposit} - networkId={this.props.networkId} - assetToken={this.props.sideToAssetToken[Side.Deposit]} - updateChosenAssetToken={dispatcher.updateChosenAssetToken.bind(dispatcher)} - tokenByAddress={this.props.tokenByAddress} - /> - <TokenAmountInput - lastForceTokenStateRefetch={this.props.lastForceTokenStateRefetch} - blockchain={this.props.blockchain} - userAddress={this.props.userAddress} - networkId={this.props.networkId} - label="Sell amount" - token={depositToken} - amount={this.props.sideToAssetToken[Side.Deposit].amount} - onChange={this._onTokenAmountChange.bind(this, depositToken, Side.Deposit)} - shouldShowIncompleteErrs={this.state.shouldShowIncompleteErrs} - shouldCheckBalance={true} - shouldCheckAllowance={true} - /> - </div> - <div className="lg-col md-col lg-col-2 md-col-2 sm-col sm-col-2 xs-hide"> - <div className="p1"> - <SwapIcon swapTokensFn={dispatcher.swapAssetTokenSymbols.bind(dispatcher)} /> - </div> - </div> - <div className="lg-col md-col lg-col-5 md-col-5 sm-col sm-col-5 sm-pb2"> - <TokenInput - userAddress={this.props.userAddress} - blockchain={this.props.blockchain} - blockchainErr={this.props.blockchainErr} - dispatcher={this.props.dispatcher} - label="Buying" - side={Side.Receive} - networkId={this.props.networkId} - assetToken={this.props.sideToAssetToken[Side.Receive]} - updateChosenAssetToken={dispatcher.updateChosenAssetToken.bind(dispatcher)} - tokenByAddress={this.props.tokenByAddress} - /> - <TokenAmountInput - lastForceTokenStateRefetch={this.props.lastForceTokenStateRefetch} - blockchain={this.props.blockchain} - userAddress={this.props.userAddress} - networkId={this.props.networkId} - label="Receive amount" - token={receiveToken} - amount={this.props.sideToAssetToken[Side.Receive].amount} - onChange={this._onTokenAmountChange.bind(this, receiveToken, Side.Receive)} - shouldShowIncompleteErrs={this.state.shouldShowIncompleteErrs} - shouldCheckBalance={false} - shouldCheckAllowance={false} - /> - </div> - </div> - </div> - <div className="pt1 sm-pb2 lg-px4 md-px4"> - <div className="lg-px3 md-px3"> - <div style={{ fontSize: 12, color: colors.grey }}>Expiration</div> - <ExpirationInput - orderExpiryTimestamp={this.props.orderExpiryTimestamp} - updateOrderExpiry={dispatcher.updateOrderExpiry.bind(dispatcher)} - /> - </div> - </div> - <div className="pt1 flex mx-auto"> - <IdenticonAddressInput - label="Taker" - initialAddress={initialTakerAddress} - updateOrderAddress={this._updateOrderAddress.bind(this)} - /> - <div className="pt3"> - <div className="pl1"> - <HelpTooltip explanation={takerExplanation} /> - </div> - </div> - </div> - <div> - <HashInput - blockchain={this.props.blockchain} - blockchainIsLoaded={this.props.blockchainIsLoaded} - hashData={this.props.hashData} - label="Order Hash" - /> - </div> - <div className="pt2"> - <div className="center"> - <LifeCycleRaisedButton - labelReady="Sign hash" - labelLoading="Signing..." - labelComplete="Hash signed!" - onClickAsyncFn={this._onSignClickedAsync.bind(this)} - /> - </div> - {this.state.globalErrMsg !== '' && ( - <Alert type={AlertTypes.Error} message={this.state.globalErrMsg} /> - )} - </div> - </div> - <Dialog - title="Order JSON" - titleStyle={{ fontWeight: 100 }} - modal={false} - open={this.state.signingState === SigningState.Signed} - onRequestClose={this._onCloseOrderJSONDialog.bind(this)} - > - <OrderJSON - exchangeContractIfExists={exchangeContractIfExists} - orderExpiryTimestamp={this.props.orderExpiryTimestamp} - orderSignature={this.props.orderSignature} - orderTakerAddress={this.props.orderTakerAddress} - orderMakerAddress={this.props.userAddress} - orderSalt={this.props.orderSalt} - orderMakerFee={this.props.hashData.makerFee} - orderTakerFee={this.props.hashData.takerFee} - orderFeeRecipient={this.props.hashData.feeRecipientAddress} - sideToAssetToken={this.props.sideToAssetToken} - tokenByAddress={this.props.tokenByAddress} - /> - </Dialog> - </div> - ); - } - private _onTokenAmountChange(token: Token, side: Side, _isValid: boolean, amount?: BigNumber): void { - this.props.dispatcher.updateChosenAssetToken(side, { - address: token.address, - amount, - }); - } - private _onCloseOrderJSONDialog(): void { - // Upon closing the order JSON dialog, we update the orderSalt stored in the Redux store - // with a new value so that if a user signs the identical order again, the newly signed - // orderHash will not collide with the previously generated orderHash. - this.props.dispatcher.updateOrderSalt(generatePseudoRandomSalt()); - this.setState({ - signingState: SigningState.Unsigned, - }); - } - private async _onSignClickedAsync(): Promise<boolean> { - if (this.props.blockchainErr !== BlockchainErrs.NoError) { - this.props.dispatcher.updateShouldBlockchainErrDialogBeOpen(true); - return false; - } - - // Check if all required inputs were supplied - const debitToken = this.props.sideToAssetToken[Side.Deposit]; - const userAddressIfExists = _.isEmpty(this.props.userAddress) ? undefined : this.props.userAddress; - const [debitBalance, debitAllowance] = await this.props.blockchain.getTokenBalanceAndAllowanceAsync( - userAddressIfExists, - debitToken.address, - ); - const receiveToken = this.props.sideToAssetToken[Side.Receive]; - const receiveAmount = receiveToken.amount; - if ( - !_.isUndefined(debitToken.amount) && - !_.isUndefined(receiveAmount) && - debitToken.amount.gt(0) && - receiveAmount.gt(0) && - this.props.userAddress !== '' && - debitBalance.gte(debitToken.amount) && - debitAllowance.gte(debitToken.amount) - ) { - const signedOrder = await this._signTransactionAsync(); - const doesSignedOrderExist = !_.isUndefined(signedOrder); - if (doesSignedOrderExist) { - analytics.trackOrderEvent('Sign Order Success', signedOrder); - this.setState({ - globalErrMsg: '', - shouldShowIncompleteErrs: false, - }); - } - return doesSignedOrderExist; - } else { - let globalErrMsg = 'You must fix the above errors in order to generate a valid order'; - if (this.props.userAddress === '') { - globalErrMsg = 'You must enable wallet communication'; - this.props.dispatcher.updateShouldBlockchainErrDialogBeOpen(true); - } - analytics.track('Sign Order Failure', { - makerTokenAmount: debitToken.amount.toString(), - makerToken: this.props.tokenByAddress[debitToken.address].symbol, - takerTokenAmount: receiveToken.amount.toString(), - takerToken: this.props.tokenByAddress[receiveToken.address].symbol, - }); - this.setState({ - globalErrMsg, - shouldShowIncompleteErrs: true, - }); - return false; - } - } - private async _signTransactionAsync(): Promise<PortalOrder | undefined> { - this.setState({ - signingState: SigningState.Signing, - }); - const exchangeAddress = this.props.blockchain.getExchangeContractAddressIfExists(); - if (_.isUndefined(exchangeAddress)) { - this.props.dispatcher.updateShouldBlockchainErrDialogBeOpen(true); - this.setState({ - signingState: SigningState.Unsigned, - }); - return undefined; - } - const hashData = this.props.hashData; - - const makerAssetData = assetDataUtils.encodeERC20AssetData(hashData.depositTokenContractAddr); - const takerAssetData = assetDataUtils.encodeERC20AssetData(hashData.receiveTokenContractAddr); - const zeroExOrder: ZeroExOrder = { - senderAddress: constants.NULL_ADDRESS, - exchangeAddress, - expirationTimeSeconds: hashData.orderExpiryTimestamp, - feeRecipientAddress: hashData.feeRecipientAddress, - makerAddress: hashData.orderMakerAddress, - makerFee: hashData.makerFee, - makerAssetData, - makerAssetAmount: hashData.depositAmount, - salt: hashData.orderSalt, - takerAddress: hashData.orderTakerAddress, - takerFee: hashData.takerFee, - takerAssetData, - takerAssetAmount: hashData.receiveAmount, - }; - const orderHash = orderHashUtils.getOrderHashHex(zeroExOrder); - - let globalErrMsg = ''; - let order; - try { - const signature = await this.props.blockchain.signOrderHashAsync(orderHash); - order = utils.generateOrder( - exchangeAddress, - this.props.sideToAssetToken, - hashData.orderExpiryTimestamp, - this.props.orderTakerAddress, - this.props.userAddress, - hashData.makerFee, - hashData.takerFee, - hashData.feeRecipientAddress, - signature, - this.props.tokenByAddress, - hashData.orderSalt, - ); - const validationResult = validator.validate(order, portalOrderSchema); - if (validationResult.errors.length > 0) { - globalErrMsg = 'Order signing failed. Please refresh and try again'; - logUtils.log(`Unexpected error occured: Order validation failed: - ${validationResult.errors}`); - } - } catch (err) { - const errMsg = `${err}`; - if (utils.didUserDenyWeb3Request(errMsg)) { - globalErrMsg = 'User denied sign request'; - } else { - globalErrMsg = 'An unexpected error occured. Please try refreshing the page'; - logUtils.log(`Unexpected error occured: ${err}`); - logUtils.log(err.stack); - errorReporter.report(err); - } - } - this.setState({ - signingState: globalErrMsg === '' ? SigningState.Signed : SigningState.Unsigned, - globalErrMsg, - }); - return order; - } - private _updateOrderAddress(address?: string): void { - if (!_.isUndefined(address)) { - const normalizedAddress = _.isEmpty(address) ? constants.NULL_ADDRESS : address; - this.props.dispatcher.updateOrderTakerAddress(normalizedAddress); - } - } -} |