diff options
author | Fabio Berger <me@fabioberger.com> | 2018-01-30 20:26:46 +0800 |
---|---|---|
committer | Fabio Berger <me@fabioberger.com> | 2018-01-30 20:26:46 +0800 |
commit | c6dece6bd1e5f5afa56b290557eb7a6245c76cb6 (patch) | |
tree | ad7a33ffe5d80c0eb41ae10fbc8314f193e52383 /packages/website/ts/components/generate_order | |
parent | 93a5b3f457c1211676296840c285759007a55500 (diff) | |
download | dexon-sol-tools-c6dece6bd1e5f5afa56b290557eb7a6245c76cb6.tar dexon-sol-tools-c6dece6bd1e5f5afa56b290557eb7a6245c76cb6.tar.gz dexon-sol-tools-c6dece6bd1e5f5afa56b290557eb7a6245c76cb6.tar.bz2 dexon-sol-tools-c6dece6bd1e5f5afa56b290557eb7a6245c76cb6.tar.lz dexon-sol-tools-c6dece6bd1e5f5afa56b290557eb7a6245c76cb6.tar.xz dexon-sol-tools-c6dece6bd1e5f5afa56b290557eb7a6245c76cb6.tar.zst dexon-sol-tools-c6dece6bd1e5f5afa56b290557eb7a6245c76cb6.zip |
Add config file specifically in prettier command and fix files
Diffstat (limited to 'packages/website/ts/components/generate_order')
3 files changed, 768 insertions, 768 deletions
diff --git a/packages/website/ts/components/generate_order/asset_picker.tsx b/packages/website/ts/components/generate_order/asset_picker.tsx index 5eed2fabf..df7d87cfd 100644 --- a/packages/website/ts/components/generate_order/asset_picker.tsx +++ b/packages/website/ts/components/generate_order/asset_picker.tsx @@ -13,264 +13,264 @@ import { DialogConfigs, Token, TokenByAddress, TokenState, TokenVisibility } fro const TOKEN_ICON_DIMENSION = 100; const TILE_DIMENSION = 146; enum AssetViews { - ASSET_PICKER = 'ASSET_PICKER', - NEW_TOKEN_FORM = 'NEW_TOKEN_FORM', - CONFIRM_TRACK_TOKEN = 'CONFIRM_TRACK_TOKEN', + ASSET_PICKER = 'ASSET_PICKER', + NEW_TOKEN_FORM = 'NEW_TOKEN_FORM', + CONFIRM_TRACK_TOKEN = 'CONFIRM_TRACK_TOKEN', } interface AssetPickerProps { - userAddress: string; - blockchain: Blockchain; - dispatcher: Dispatcher; - networkId: number; - isOpen: boolean; - currentTokenAddress: string; - onTokenChosen: (tokenAddress: string) => void; - tokenByAddress: TokenByAddress; - tokenVisibility?: TokenVisibility; + userAddress: string; + blockchain: Blockchain; + dispatcher: Dispatcher; + networkId: number; + isOpen: boolean; + currentTokenAddress: string; + onTokenChosen: (tokenAddress: string) => void; + tokenByAddress: TokenByAddress; + tokenVisibility?: TokenVisibility; } interface AssetPickerState { - assetView: AssetViews; - hoveredAddress: string | undefined; - chosenTrackTokenAddress: string; - isAddingTokenToTracked: boolean; + assetView: AssetViews; + hoveredAddress: string | undefined; + chosenTrackTokenAddress: string; + isAddingTokenToTracked: boolean; } export class AssetPicker extends React.Component<AssetPickerProps, AssetPickerState> { - public static defaultProps: Partial<AssetPickerProps> = { - tokenVisibility: TokenVisibility.ALL, - }; - private _dialogConfigsByAssetView: { [assetView: string]: DialogConfigs }; - constructor(props: AssetPickerProps) { - super(props); - this.state = { - assetView: AssetViews.ASSET_PICKER, - hoveredAddress: undefined, - chosenTrackTokenAddress: undefined, - isAddingTokenToTracked: false, - }; - this._dialogConfigsByAssetView = { - [AssetViews.ASSET_PICKER]: { - title: 'Select token', - isModal: false, - actions: [], - }, - [AssetViews.NEW_TOKEN_FORM]: { - title: 'Add an ERC20 token', - isModal: false, - actions: [], - }, - [AssetViews.CONFIRM_TRACK_TOKEN]: { - title: 'Tracking confirmation', - isModal: true, - actions: [ - <FlatButton - key="noTracking" - label="No" - onTouchTap={this._onTrackConfirmationRespondedAsync.bind(this, false)} - />, - <FlatButton - key="yesTrack" - label="Yes" - onTouchTap={this._onTrackConfirmationRespondedAsync.bind(this, true)} - />, - ], - }, - }; - } - public render() { - const dialogConfigs: DialogConfigs = this._dialogConfigsByAssetView[this.state.assetView]; - return ( - <Dialog - title={dialogConfigs.title} - titleStyle={{ fontWeight: 100 }} - modal={dialogConfigs.isModal} - open={this.props.isOpen} - actions={dialogConfigs.actions} - onRequestClose={this._onCloseDialog.bind(this)} - > - {this.state.assetView === AssetViews.ASSET_PICKER && this._renderAssetPicker()} - {this.state.assetView === AssetViews.NEW_TOKEN_FORM && ( - <NewTokenForm - blockchain={this.props.blockchain} - onNewTokenSubmitted={this._onNewTokenSubmitted.bind(this)} - tokenByAddress={this.props.tokenByAddress} - /> - )} - {this.state.assetView === AssetViews.CONFIRM_TRACK_TOKEN && this._renderConfirmTrackToken()} - </Dialog> - ); - } - private _renderConfirmTrackToken() { - const token = this.props.tokenByAddress[this.state.chosenTrackTokenAddress]; - return ( - <TrackTokenConfirmation - tokens={[token]} - tokenByAddress={this.props.tokenByAddress} - networkId={this.props.networkId} - isAddingTokenToTracked={this.state.isAddingTokenToTracked} - /> - ); - } - private _renderAssetPicker() { - return ( - <div - className="clearfix flex flex-wrap" - style={{ - overflowY: 'auto', - maxWidth: 720, - maxHeight: 356, - marginBottom: 10, - }} - > - {this._renderGridTiles()} - </div> - ); - } - private _renderGridTiles() { - let isHovered; - let tileStyles; - const gridTiles = _.map(this.props.tokenByAddress, (token: Token, address: string) => { - if ( - (this.props.tokenVisibility === TokenVisibility.TRACKED && !token.isTracked) || - (this.props.tokenVisibility === TokenVisibility.UNTRACKED && token.isTracked) - ) { - return null; // Skip - } - isHovered = this.state.hoveredAddress === address; - tileStyles = { - cursor: 'pointer', - opacity: isHovered ? 0.6 : 1, - }; - return ( - <div - key={address} - style={{ - width: TILE_DIMENSION, - height: TILE_DIMENSION, - ...tileStyles, - }} - className="p2 mx-auto" - onClick={this._onChooseToken.bind(this, address)} - onMouseEnter={this._onToggleHover.bind(this, address, true)} - onMouseLeave={this._onToggleHover.bind(this, address, false)} - > - <div className="p1 center"> - <TokenIcon token={token} diameter={TOKEN_ICON_DIMENSION} /> - </div> - <div className="center">{token.name}</div> - </div> - ); - }); - const otherTokenKey = 'otherToken'; - isHovered = this.state.hoveredAddress === otherTokenKey; - tileStyles = { - cursor: 'pointer', - opacity: isHovered ? 0.6 : 1, - }; - if (this.props.tokenVisibility !== TokenVisibility.TRACKED) { - gridTiles.push( - <div - key={otherTokenKey} - style={{ - width: TILE_DIMENSION, - height: TILE_DIMENSION, - ...tileStyles, - }} - className="p2 mx-auto" - onClick={this._onCustomAssetChosen.bind(this)} - onMouseEnter={this._onToggleHover.bind(this, otherTokenKey, true)} - onMouseLeave={this._onToggleHover.bind(this, otherTokenKey, false)} - > - <div className="p1 center"> - <i - style={{ fontSize: 105, paddingLeft: 1, paddingRight: 1 }} - className="zmdi zmdi-plus-circle" - /> - </div> - <div className="center">Other ERC20 Token</div> - </div>, - ); - } - return gridTiles; - } - private _onToggleHover(address: string, isHovered: boolean) { - const hoveredAddress = isHovered ? address : undefined; - this.setState({ - hoveredAddress, - }); - } - private _onCloseDialog() { - this.setState({ - assetView: AssetViews.ASSET_PICKER, - }); - this.props.onTokenChosen(this.props.currentTokenAddress); - } - private _onChooseToken(tokenAddress: string) { - const token = this.props.tokenByAddress[tokenAddress]; - if (token.isTracked) { - this.props.onTokenChosen(tokenAddress); - } else { - this.setState({ - assetView: AssetViews.CONFIRM_TRACK_TOKEN, - chosenTrackTokenAddress: tokenAddress, - }); - } - } - private _onCustomAssetChosen() { - this.setState({ - assetView: AssetViews.NEW_TOKEN_FORM, - }); - } - private _onNewTokenSubmitted(newToken: Token, newTokenState: TokenState) { - this.props.dispatcher.updateTokenStateByAddress({ - [newToken.address]: newTokenState, - }); - trackedTokenStorage.addTrackedTokenToUser(this.props.userAddress, this.props.networkId, newToken); - this.props.dispatcher.addTokenToTokenByAddress(newToken); - this.setState({ - assetView: AssetViews.ASSET_PICKER, - }); - this.props.onTokenChosen(newToken.address); - } - private async _onTrackConfirmationRespondedAsync(didUserAcceptTracking: boolean) { - if (!didUserAcceptTracking) { - this.setState({ - isAddingTokenToTracked: false, - assetView: AssetViews.ASSET_PICKER, - chosenTrackTokenAddress: undefined, - }); - this._onCloseDialog(); - return; - } - this.setState({ - isAddingTokenToTracked: true, - }); - const tokenAddress = this.state.chosenTrackTokenAddress; - const token = this.props.tokenByAddress[tokenAddress]; - const newTokenEntry = { - ...token, - }; + public static defaultProps: Partial<AssetPickerProps> = { + tokenVisibility: TokenVisibility.ALL, + }; + private _dialogConfigsByAssetView: { [assetView: string]: DialogConfigs }; + constructor(props: AssetPickerProps) { + super(props); + this.state = { + assetView: AssetViews.ASSET_PICKER, + hoveredAddress: undefined, + chosenTrackTokenAddress: undefined, + isAddingTokenToTracked: false, + }; + this._dialogConfigsByAssetView = { + [AssetViews.ASSET_PICKER]: { + title: 'Select token', + isModal: false, + actions: [], + }, + [AssetViews.NEW_TOKEN_FORM]: { + title: 'Add an ERC20 token', + isModal: false, + actions: [], + }, + [AssetViews.CONFIRM_TRACK_TOKEN]: { + title: 'Tracking confirmation', + isModal: true, + actions: [ + <FlatButton + key="noTracking" + label="No" + onTouchTap={this._onTrackConfirmationRespondedAsync.bind(this, false)} + />, + <FlatButton + key="yesTrack" + label="Yes" + onTouchTap={this._onTrackConfirmationRespondedAsync.bind(this, true)} + />, + ], + }, + }; + } + public render() { + const dialogConfigs: DialogConfigs = this._dialogConfigsByAssetView[this.state.assetView]; + return ( + <Dialog + title={dialogConfigs.title} + titleStyle={{ fontWeight: 100 }} + modal={dialogConfigs.isModal} + open={this.props.isOpen} + actions={dialogConfigs.actions} + onRequestClose={this._onCloseDialog.bind(this)} + > + {this.state.assetView === AssetViews.ASSET_PICKER && this._renderAssetPicker()} + {this.state.assetView === AssetViews.NEW_TOKEN_FORM && ( + <NewTokenForm + blockchain={this.props.blockchain} + onNewTokenSubmitted={this._onNewTokenSubmitted.bind(this)} + tokenByAddress={this.props.tokenByAddress} + /> + )} + {this.state.assetView === AssetViews.CONFIRM_TRACK_TOKEN && this._renderConfirmTrackToken()} + </Dialog> + ); + } + private _renderConfirmTrackToken() { + const token = this.props.tokenByAddress[this.state.chosenTrackTokenAddress]; + return ( + <TrackTokenConfirmation + tokens={[token]} + tokenByAddress={this.props.tokenByAddress} + networkId={this.props.networkId} + isAddingTokenToTracked={this.state.isAddingTokenToTracked} + /> + ); + } + private _renderAssetPicker() { + return ( + <div + className="clearfix flex flex-wrap" + style={{ + overflowY: 'auto', + maxWidth: 720, + maxHeight: 356, + marginBottom: 10, + }} + > + {this._renderGridTiles()} + </div> + ); + } + private _renderGridTiles() { + let isHovered; + let tileStyles; + const gridTiles = _.map(this.props.tokenByAddress, (token: Token, address: string) => { + if ( + (this.props.tokenVisibility === TokenVisibility.TRACKED && !token.isTracked) || + (this.props.tokenVisibility === TokenVisibility.UNTRACKED && token.isTracked) + ) { + return null; // Skip + } + isHovered = this.state.hoveredAddress === address; + tileStyles = { + cursor: 'pointer', + opacity: isHovered ? 0.6 : 1, + }; + return ( + <div + key={address} + style={{ + width: TILE_DIMENSION, + height: TILE_DIMENSION, + ...tileStyles, + }} + className="p2 mx-auto" + onClick={this._onChooseToken.bind(this, address)} + onMouseEnter={this._onToggleHover.bind(this, address, true)} + onMouseLeave={this._onToggleHover.bind(this, address, false)} + > + <div className="p1 center"> + <TokenIcon token={token} diameter={TOKEN_ICON_DIMENSION} /> + </div> + <div className="center">{token.name}</div> + </div> + ); + }); + const otherTokenKey = 'otherToken'; + isHovered = this.state.hoveredAddress === otherTokenKey; + tileStyles = { + cursor: 'pointer', + opacity: isHovered ? 0.6 : 1, + }; + if (this.props.tokenVisibility !== TokenVisibility.TRACKED) { + gridTiles.push( + <div + key={otherTokenKey} + style={{ + width: TILE_DIMENSION, + height: TILE_DIMENSION, + ...tileStyles, + }} + className="p2 mx-auto" + onClick={this._onCustomAssetChosen.bind(this)} + onMouseEnter={this._onToggleHover.bind(this, otherTokenKey, true)} + onMouseLeave={this._onToggleHover.bind(this, otherTokenKey, false)} + > + <div className="p1 center"> + <i + style={{ fontSize: 105, paddingLeft: 1, paddingRight: 1 }} + className="zmdi zmdi-plus-circle" + /> + </div> + <div className="center">Other ERC20 Token</div> + </div>, + ); + } + return gridTiles; + } + private _onToggleHover(address: string, isHovered: boolean) { + const hoveredAddress = isHovered ? address : undefined; + this.setState({ + hoveredAddress, + }); + } + private _onCloseDialog() { + this.setState({ + assetView: AssetViews.ASSET_PICKER, + }); + this.props.onTokenChosen(this.props.currentTokenAddress); + } + private _onChooseToken(tokenAddress: string) { + const token = this.props.tokenByAddress[tokenAddress]; + if (token.isTracked) { + this.props.onTokenChosen(tokenAddress); + } else { + this.setState({ + assetView: AssetViews.CONFIRM_TRACK_TOKEN, + chosenTrackTokenAddress: tokenAddress, + }); + } + } + private _onCustomAssetChosen() { + this.setState({ + assetView: AssetViews.NEW_TOKEN_FORM, + }); + } + private _onNewTokenSubmitted(newToken: Token, newTokenState: TokenState) { + this.props.dispatcher.updateTokenStateByAddress({ + [newToken.address]: newTokenState, + }); + trackedTokenStorage.addTrackedTokenToUser(this.props.userAddress, this.props.networkId, newToken); + this.props.dispatcher.addTokenToTokenByAddress(newToken); + this.setState({ + assetView: AssetViews.ASSET_PICKER, + }); + this.props.onTokenChosen(newToken.address); + } + private async _onTrackConfirmationRespondedAsync(didUserAcceptTracking: boolean) { + if (!didUserAcceptTracking) { + this.setState({ + isAddingTokenToTracked: false, + assetView: AssetViews.ASSET_PICKER, + chosenTrackTokenAddress: undefined, + }); + this._onCloseDialog(); + return; + } + this.setState({ + isAddingTokenToTracked: true, + }); + const tokenAddress = this.state.chosenTrackTokenAddress; + const token = this.props.tokenByAddress[tokenAddress]; + const newTokenEntry = { + ...token, + }; - newTokenEntry.isTracked = true; - trackedTokenStorage.addTrackedTokenToUser(this.props.userAddress, this.props.networkId, newTokenEntry); + newTokenEntry.isTracked = true; + trackedTokenStorage.addTrackedTokenToUser(this.props.userAddress, this.props.networkId, newTokenEntry); - const [balance, allowance] = await this.props.blockchain.getCurrentUserTokenBalanceAndAllowanceAsync( - token.address, - ); - this.props.dispatcher.updateTokenStateByAddress({ - [token.address]: { - balance, - allowance, - }, - }); - this.props.dispatcher.updateTokenByAddress([newTokenEntry]); - this.setState({ - isAddingTokenToTracked: false, - assetView: AssetViews.ASSET_PICKER, - chosenTrackTokenAddress: undefined, - }); - this.props.onTokenChosen(tokenAddress); - } + const [balance, allowance] = await this.props.blockchain.getCurrentUserTokenBalanceAndAllowanceAsync( + token.address, + ); + this.props.dispatcher.updateTokenStateByAddress({ + [token.address]: { + balance, + allowance, + }, + }); + this.props.dispatcher.updateTokenByAddress([newTokenEntry]); + this.setState({ + isAddingTokenToTracked: false, + assetView: AssetViews.ASSET_PICKER, + chosenTrackTokenAddress: undefined, + }); + this.props.onTokenChosen(tokenAddress); + } } diff --git a/packages/website/ts/components/generate_order/generate_order_form.tsx b/packages/website/ts/components/generate_order/generate_order_form.tsx index b10b2d609..3ae0d48a7 100644 --- a/packages/website/ts/components/generate_order/generate_order_form.tsx +++ b/packages/website/ts/components/generate_order/generate_order_form.tsx @@ -19,335 +19,335 @@ import { Dispatcher } from 'ts/redux/dispatcher'; import { orderSchema } from 'ts/schemas/order_schema'; import { SchemaValidator } from 'ts/schemas/validator'; import { - AlertTypes, - BlockchainErrs, - HashData, - Side, - SideToAssetToken, - SignatureData, - Token, - TokenByAddress, - TokenStateByAddress, + AlertTypes, + BlockchainErrs, + HashData, + Side, + SideToAssetToken, + SignatureData, + Token, + TokenByAddress, + TokenStateByAddress, } from 'ts/types'; import { colors } from 'ts/utils/colors'; import { errorReporter } from 'ts/utils/error_reporter'; import { utils } from 'ts/utils/utils'; enum SigningState { - UNSIGNED, - SIGNING, - SIGNED, + UNSIGNED, + SIGNING, + SIGNED, } interface GenerateOrderFormProps { - blockchain: Blockchain; - blockchainErr: BlockchainErrs; - blockchainIsLoaded: boolean; - dispatcher: Dispatcher; - hashData: HashData; - orderExpiryTimestamp: BigNumber; - networkId: number; - userAddress: string; - orderSignatureData: SignatureData; - orderTakerAddress: string; - orderSalt: BigNumber; - sideToAssetToken: SideToAssetToken; - tokenByAddress: TokenByAddress; - tokenStateByAddress: TokenStateByAddress; + blockchain: Blockchain; + blockchainErr: BlockchainErrs; + blockchainIsLoaded: boolean; + dispatcher: Dispatcher; + hashData: HashData; + orderExpiryTimestamp: BigNumber; + networkId: number; + userAddress: string; + orderSignatureData: SignatureData; + orderTakerAddress: string; + orderSalt: BigNumber; + sideToAssetToken: SideToAssetToken; + tokenByAddress: TokenByAddress; + tokenStateByAddress: TokenStateByAddress; } interface GenerateOrderFormState { - globalErrMsg: string; - shouldShowIncompleteErrs: boolean; - signingState: SigningState; + globalErrMsg: string; + shouldShowIncompleteErrs: boolean; + signingState: SigningState; } export class GenerateOrderForm extends React.Component<GenerateOrderFormProps, GenerateOrderFormState> { - private _validator: SchemaValidator; - constructor(props: GenerateOrderFormProps) { - super(props); - this.state = { - globalErrMsg: '', - shouldShowIncompleteErrs: false, - signingState: SigningState.UNSIGNED, - }; - this._validator = new SchemaValidator(); - } - public componentDidMount() { - window.scrollTo(0, 0); - } - public render() { - const dispatcher = this.props.dispatcher; - const depositTokenAddress = this.props.sideToAssetToken[Side.Deposit].address; - const depositToken = this.props.tokenByAddress[depositTokenAddress]; - const depositTokenState = this.props.tokenStateByAddress[depositTokenAddress]; - const receiveTokenAddress = this.props.sideToAssetToken[Side.Receive].address; - const receiveToken = this.props.tokenByAddress[receiveTokenAddress]; - const receiveTokenState = this.props.tokenStateByAddress[receiveTokenAddress]; - const takerExplanation = - 'If a taker is specified, only they are<br> \ + private _validator: SchemaValidator; + constructor(props: GenerateOrderFormProps) { + super(props); + this.state = { + globalErrMsg: '', + shouldShowIncompleteErrs: false, + signingState: SigningState.UNSIGNED, + }; + this._validator = new SchemaValidator(); + } + public componentDidMount() { + window.scrollTo(0, 0); + } + public render() { + const dispatcher = this.props.dispatcher; + const depositTokenAddress = this.props.sideToAssetToken[Side.Deposit].address; + const depositToken = this.props.tokenByAddress[depositTokenAddress]; + const depositTokenState = this.props.tokenStateByAddress[depositTokenAddress]; + const receiveTokenAddress = this.props.sideToAssetToken[Side.Receive].address; + const receiveToken = this.props.tokenByAddress[receiveTokenAddress]; + const receiveTokenState = this.props.tokenStateByAddress[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(); - return ( - <div className="clearfix mb2 lg-px4 md-px4 sm-px2"> - <h3>Generate an order</h3> - <Divider /> - <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 - label="Sell amount" - token={depositToken} - tokenState={depositTokenState} - 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 - label="Receive amount" - token={receiveToken} - tokenState={receiveTokenState} - 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={this.props.orderTakerAddress} - 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} - orderSignatureData={this.props.orderSignatureData} - 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} - networkId={this.props.networkId} - sideToAssetToken={this.props.sideToAssetToken} - tokenByAddress={this.props.tokenByAddress} - /> - </Dialog> - </div> - ); - } - private _onTokenAmountChange(token: Token, side: Side, isValid: boolean, amount?: BigNumber) { - this.props.dispatcher.updateChosenAssetToken(side, { - address: token.address, - amount, - }); - } - private _onCloseOrderJSONDialog() { - // 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(ZeroEx.generatePseudoRandomSalt()); - this.setState({ - signingState: SigningState.UNSIGNED, - }); - } - private async _onSignClickedAsync(): Promise<boolean> { - if (this.props.blockchainErr !== BlockchainErrs.NoError) { - this.props.dispatcher.updateShouldBlockchainErrDialogBeOpen(true); - return false; - } + const exchangeContractIfExists = this.props.blockchain.getExchangeContractAddressIfExists(); + return ( + <div className="clearfix mb2 lg-px4 md-px4 sm-px2"> + <h3>Generate an order</h3> + <Divider /> + <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 + label="Sell amount" + token={depositToken} + tokenState={depositTokenState} + 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 + label="Receive amount" + token={receiveToken} + tokenState={receiveTokenState} + 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={this.props.orderTakerAddress} + 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} + orderSignatureData={this.props.orderSignatureData} + 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} + networkId={this.props.networkId} + sideToAssetToken={this.props.sideToAssetToken} + tokenByAddress={this.props.tokenByAddress} + /> + </Dialog> + </div> + ); + } + private _onTokenAmountChange(token: Token, side: Side, isValid: boolean, amount?: BigNumber) { + this.props.dispatcher.updateChosenAssetToken(side, { + address: token.address, + amount, + }); + } + private _onCloseOrderJSONDialog() { + // 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(ZeroEx.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 debitBalance = this.props.tokenStateByAddress[debitToken.address].balance; - const debitAllowance = this.props.tokenStateByAddress[debitToken.address].allowance; - const receiveAmount = this.props.sideToAssetToken[Side.Receive].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 didSignSuccessfully = await this._signTransactionAsync(); - if (didSignSuccessfully) { - this.setState({ - globalErrMsg: '', - shouldShowIncompleteErrs: false, - }); - } - return didSignSuccessfully; - } 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); - } - this.setState({ - globalErrMsg, - shouldShowIncompleteErrs: true, - }); - return false; - } - } - private async _signTransactionAsync(): Promise<boolean> { - this.setState({ - signingState: SigningState.SIGNING, - }); - const exchangeContractAddr = this.props.blockchain.getExchangeContractAddressIfExists(); - if (_.isUndefined(exchangeContractAddr)) { - this.props.dispatcher.updateShouldBlockchainErrDialogBeOpen(true); - this.setState({ - signingState: SigningState.UNSIGNED, - }); - return false; - } - const hashData = this.props.hashData; + // Check if all required inputs were supplied + const debitToken = this.props.sideToAssetToken[Side.Deposit]; + const debitBalance = this.props.tokenStateByAddress[debitToken.address].balance; + const debitAllowance = this.props.tokenStateByAddress[debitToken.address].allowance; + const receiveAmount = this.props.sideToAssetToken[Side.Receive].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 didSignSuccessfully = await this._signTransactionAsync(); + if (didSignSuccessfully) { + this.setState({ + globalErrMsg: '', + shouldShowIncompleteErrs: false, + }); + } + return didSignSuccessfully; + } 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); + } + this.setState({ + globalErrMsg, + shouldShowIncompleteErrs: true, + }); + return false; + } + } + private async _signTransactionAsync(): Promise<boolean> { + this.setState({ + signingState: SigningState.SIGNING, + }); + const exchangeContractAddr = this.props.blockchain.getExchangeContractAddressIfExists(); + if (_.isUndefined(exchangeContractAddr)) { + this.props.dispatcher.updateShouldBlockchainErrDialogBeOpen(true); + this.setState({ + signingState: SigningState.UNSIGNED, + }); + return false; + } + const hashData = this.props.hashData; - const zeroExOrder: Order = { - exchangeContractAddress: exchangeContractAddr, - expirationUnixTimestampSec: hashData.orderExpiryTimestamp, - feeRecipient: hashData.feeRecipientAddress, - maker: hashData.orderMakerAddress, - makerFee: hashData.makerFee, - makerTokenAddress: hashData.depositTokenContractAddr, - makerTokenAmount: hashData.depositAmount, - salt: hashData.orderSalt, - taker: hashData.orderTakerAddress, - takerFee: hashData.takerFee, - takerTokenAddress: hashData.receiveTokenContractAddr, - takerTokenAmount: hashData.receiveAmount, - }; - const orderHash = ZeroEx.getOrderHashHex(zeroExOrder); + const zeroExOrder: Order = { + exchangeContractAddress: exchangeContractAddr, + expirationUnixTimestampSec: hashData.orderExpiryTimestamp, + feeRecipient: hashData.feeRecipientAddress, + maker: hashData.orderMakerAddress, + makerFee: hashData.makerFee, + makerTokenAddress: hashData.depositTokenContractAddr, + makerTokenAmount: hashData.depositAmount, + salt: hashData.orderSalt, + taker: hashData.orderTakerAddress, + takerFee: hashData.takerFee, + takerTokenAddress: hashData.receiveTokenContractAddr, + takerTokenAmount: hashData.receiveAmount, + }; + const orderHash = ZeroEx.getOrderHashHex(zeroExOrder); - let globalErrMsg = ''; - try { - const signatureData = await this.props.blockchain.signOrderHashAsync(orderHash); - const order = utils.generateOrder( - this.props.networkId, - exchangeContractAddr, - this.props.sideToAssetToken, - hashData.orderExpiryTimestamp, - this.props.orderTakerAddress, - this.props.userAddress, - hashData.makerFee, - hashData.takerFee, - hashData.feeRecipientAddress, - signatureData, - this.props.tokenByAddress, - hashData.orderSalt, - ); - const validationResult = this._validator.validate(order, orderSchema); - if (validationResult.errors.length > 0) { - globalErrMsg = 'Order signing failed. Please refresh and try again'; - utils.consoleLog(`Unexpected error occured: Order validation failed: + let globalErrMsg = ''; + try { + const signatureData = await this.props.blockchain.signOrderHashAsync(orderHash); + const order = utils.generateOrder( + this.props.networkId, + exchangeContractAddr, + this.props.sideToAssetToken, + hashData.orderExpiryTimestamp, + this.props.orderTakerAddress, + this.props.userAddress, + hashData.makerFee, + hashData.takerFee, + hashData.feeRecipientAddress, + signatureData, + this.props.tokenByAddress, + hashData.orderSalt, + ); + const validationResult = this._validator.validate(order, orderSchema); + if (validationResult.errors.length > 0) { + globalErrMsg = 'Order signing failed. Please refresh and try again'; + utils.consoleLog(`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'; - utils.consoleLog(`Unexpected error occured: ${err}`); - utils.consoleLog(err.stack); - await errorReporter.reportAsync(err); - } - } - this.setState({ - signingState: globalErrMsg === '' ? SigningState.SIGNED : SigningState.UNSIGNED, - globalErrMsg, - }); - return globalErrMsg === ''; - } - private _updateOrderAddress(address?: string): void { - if (!_.isUndefined(address)) { - this.props.dispatcher.updateOrderTakerAddress(address); - } - } + } + } 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'; + utils.consoleLog(`Unexpected error occured: ${err}`); + utils.consoleLog(err.stack); + await errorReporter.reportAsync(err); + } + } + this.setState({ + signingState: globalErrMsg === '' ? SigningState.SIGNED : SigningState.UNSIGNED, + globalErrMsg, + }); + return globalErrMsg === ''; + } + private _updateOrderAddress(address?: string): void { + if (!_.isUndefined(address)) { + this.props.dispatcher.updateOrderTakerAddress(address); + } + } } diff --git a/packages/website/ts/components/generate_order/new_token_form.tsx b/packages/website/ts/components/generate_order/new_token_form.tsx index d61aac92a..63645be9a 100644 --- a/packages/website/ts/components/generate_order/new_token_form.tsx +++ b/packages/website/ts/components/generate_order/new_token_form.tsx @@ -11,227 +11,227 @@ import { AlertTypes, Token, TokenByAddress, TokenState } from 'ts/types'; import { colors } from 'ts/utils/colors'; interface NewTokenFormProps { - blockchain: Blockchain; - tokenByAddress: TokenByAddress; - onNewTokenSubmitted: (token: Token, tokenState: TokenState) => void; + blockchain: Blockchain; + tokenByAddress: TokenByAddress; + onNewTokenSubmitted: (token: Token, tokenState: TokenState) => void; } interface NewTokenFormState { - globalErrMsg: string; - name: string; - nameErrText: string; - symbol: string; - symbolErrText: string; - address: string; - shouldShowAddressIncompleteErr: boolean; - decimals: string; - decimalsErrText: string; + globalErrMsg: string; + name: string; + nameErrText: string; + symbol: string; + symbolErrText: string; + address: string; + shouldShowAddressIncompleteErr: boolean; + decimals: string; + decimalsErrText: string; } export class NewTokenForm extends React.Component<NewTokenFormProps, NewTokenFormState> { - constructor(props: NewTokenFormProps) { - super(props); - this.state = { - address: '', - globalErrMsg: '', - name: '', - nameErrText: '', - shouldShowAddressIncompleteErr: false, - symbol: '', - symbolErrText: '', - decimals: '18', - decimalsErrText: '', - }; - } - public render() { - return ( - <div className="mx-auto pb2" style={{ width: 256 }}> - <div> - <TextField - floatingLabelFixed={true} - floatingLabelStyle={{ color: colors.grey }} - floatingLabelText={<RequiredLabel label="Name" />} - value={this.state.name} - errorText={this.state.nameErrText} - onChange={this._onTokenNameChanged.bind(this)} - /> - </div> - <div> - <TextField - floatingLabelFixed={true} - floatingLabelStyle={{ color: colors.grey }} - floatingLabelText={<RequiredLabel label="Symbol" />} - value={this.state.symbol} - errorText={this.state.symbolErrText} - onChange={this._onTokenSymbolChanged.bind(this)} - /> - </div> - <div> - <AddressInput - isRequired={true} - label="Contract address" - initialAddress="" - shouldShowIncompleteErrs={this.state.shouldShowAddressIncompleteErr} - updateAddress={this._onTokenAddressChanged.bind(this)} - /> - </div> - <div> - <TextField - floatingLabelFixed={true} - floatingLabelStyle={{ color: colors.grey }} - floatingLabelText={<RequiredLabel label="Decimals" />} - value={this.state.decimals} - errorText={this.state.decimalsErrText} - onChange={this._onTokenDecimalsChanged.bind(this)} - /> - </div> - <div className="pt2 mx-auto" style={{ width: 120 }}> - <LifeCycleRaisedButton - labelReady="Add" - labelLoading="Adding..." - labelComplete="Added!" - onClickAsyncFn={this._onAddNewTokenClickAsync.bind(this)} - /> - </div> - {this.state.globalErrMsg !== '' && <Alert type={AlertTypes.ERROR} message={this.state.globalErrMsg} />} - </div> - ); - } - private async _onAddNewTokenClickAsync() { - // Trigger validation of name and symbol - this._onTokenNameChanged(undefined, this.state.name); - this._onTokenSymbolChanged(undefined, this.state.symbol); - this._onTokenDecimalsChanged(undefined, this.state.decimals); + constructor(props: NewTokenFormProps) { + super(props); + this.state = { + address: '', + globalErrMsg: '', + name: '', + nameErrText: '', + shouldShowAddressIncompleteErr: false, + symbol: '', + symbolErrText: '', + decimals: '18', + decimalsErrText: '', + }; + } + public render() { + return ( + <div className="mx-auto pb2" style={{ width: 256 }}> + <div> + <TextField + floatingLabelFixed={true} + floatingLabelStyle={{ color: colors.grey }} + floatingLabelText={<RequiredLabel label="Name" />} + value={this.state.name} + errorText={this.state.nameErrText} + onChange={this._onTokenNameChanged.bind(this)} + /> + </div> + <div> + <TextField + floatingLabelFixed={true} + floatingLabelStyle={{ color: colors.grey }} + floatingLabelText={<RequiredLabel label="Symbol" />} + value={this.state.symbol} + errorText={this.state.symbolErrText} + onChange={this._onTokenSymbolChanged.bind(this)} + /> + </div> + <div> + <AddressInput + isRequired={true} + label="Contract address" + initialAddress="" + shouldShowIncompleteErrs={this.state.shouldShowAddressIncompleteErr} + updateAddress={this._onTokenAddressChanged.bind(this)} + /> + </div> + <div> + <TextField + floatingLabelFixed={true} + floatingLabelStyle={{ color: colors.grey }} + floatingLabelText={<RequiredLabel label="Decimals" />} + value={this.state.decimals} + errorText={this.state.decimalsErrText} + onChange={this._onTokenDecimalsChanged.bind(this)} + /> + </div> + <div className="pt2 mx-auto" style={{ width: 120 }}> + <LifeCycleRaisedButton + labelReady="Add" + labelLoading="Adding..." + labelComplete="Added!" + onClickAsyncFn={this._onAddNewTokenClickAsync.bind(this)} + /> + </div> + {this.state.globalErrMsg !== '' && <Alert type={AlertTypes.ERROR} message={this.state.globalErrMsg} />} + </div> + ); + } + private async _onAddNewTokenClickAsync() { + // Trigger validation of name and symbol + this._onTokenNameChanged(undefined, this.state.name); + this._onTokenSymbolChanged(undefined, this.state.symbol); + this._onTokenDecimalsChanged(undefined, this.state.decimals); - const isAddressIncomplete = this.state.address === ''; - let doesContractExist = false; - if (!isAddressIncomplete) { - doesContractExist = await this.props.blockchain.doesContractExistAtAddressAsync(this.state.address); - } + const isAddressIncomplete = this.state.address === ''; + let doesContractExist = false; + if (!isAddressIncomplete) { + doesContractExist = await this.props.blockchain.doesContractExistAtAddressAsync(this.state.address); + } - let hasBalanceAllowanceErr = false; - let balance = new BigNumber(0); - let allowance = new BigNumber(0); - if (doesContractExist) { - try { - [balance, allowance] = await this.props.blockchain.getCurrentUserTokenBalanceAndAllowanceAsync( - this.state.address, - ); - } catch (err) { - hasBalanceAllowanceErr = true; - } - } + let hasBalanceAllowanceErr = false; + let balance = new BigNumber(0); + let allowance = new BigNumber(0); + if (doesContractExist) { + try { + [balance, allowance] = await this.props.blockchain.getCurrentUserTokenBalanceAndAllowanceAsync( + this.state.address, + ); + } catch (err) { + hasBalanceAllowanceErr = true; + } + } - let globalErrMsg = ''; - if ( - this.state.nameErrText !== '' || - this.state.symbolErrText !== '' || - this.state.decimalsErrText !== '' || - isAddressIncomplete - ) { - globalErrMsg = 'Please fix the above issues'; - } else if (!doesContractExist) { - globalErrMsg = 'No contract found at supplied address'; - } else if (hasBalanceAllowanceErr) { - globalErrMsg = 'Unsuccessful call to `balanceOf` and/or `allowance` on supplied contract address'; - } else if (!isAddressIncomplete && !_.isUndefined(this.props.tokenByAddress[this.state.address])) { - globalErrMsg = 'A token already exists with this address'; - } + let globalErrMsg = ''; + if ( + this.state.nameErrText !== '' || + this.state.symbolErrText !== '' || + this.state.decimalsErrText !== '' || + isAddressIncomplete + ) { + globalErrMsg = 'Please fix the above issues'; + } else if (!doesContractExist) { + globalErrMsg = 'No contract found at supplied address'; + } else if (hasBalanceAllowanceErr) { + globalErrMsg = 'Unsuccessful call to `balanceOf` and/or `allowance` on supplied contract address'; + } else if (!isAddressIncomplete && !_.isUndefined(this.props.tokenByAddress[this.state.address])) { + globalErrMsg = 'A token already exists with this address'; + } - if (globalErrMsg !== '') { - this.setState({ - globalErrMsg, - shouldShowAddressIncompleteErr: isAddressIncomplete, - }); - return; - } + if (globalErrMsg !== '') { + this.setState({ + globalErrMsg, + shouldShowAddressIncompleteErr: isAddressIncomplete, + }); + return; + } - const newToken: Token = { - address: this.state.address, - decimals: _.parseInt(this.state.decimals), - iconUrl: undefined, - name: this.state.name, - symbol: this.state.symbol.toUpperCase(), - isTracked: true, - isRegistered: false, - }; - const newTokenState: TokenState = { - balance, - allowance, - }; - this.props.onNewTokenSubmitted(newToken, newTokenState); - } - private _onTokenNameChanged(e: any, name: string) { - let nameErrText = ''; - const maxLength = 30; - const tokens = _.values(this.props.tokenByAddress); - const tokenWithNameIfExists = _.find(tokens, { name }); - const tokenWithNameExists = !_.isUndefined(tokenWithNameIfExists); - if (name === '') { - nameErrText = 'Name is required'; - } else if (!this._isValidName(name)) { - nameErrText = 'Name should only contain letters, digits and spaces'; - } else if (name.length > maxLength) { - nameErrText = `Max length is ${maxLength}`; - } else if (tokenWithNameExists) { - nameErrText = 'Token with this name already exists'; - } + const newToken: Token = { + address: this.state.address, + decimals: _.parseInt(this.state.decimals), + iconUrl: undefined, + name: this.state.name, + symbol: this.state.symbol.toUpperCase(), + isTracked: true, + isRegistered: false, + }; + const newTokenState: TokenState = { + balance, + allowance, + }; + this.props.onNewTokenSubmitted(newToken, newTokenState); + } + private _onTokenNameChanged(e: any, name: string) { + let nameErrText = ''; + const maxLength = 30; + const tokens = _.values(this.props.tokenByAddress); + const tokenWithNameIfExists = _.find(tokens, { name }); + const tokenWithNameExists = !_.isUndefined(tokenWithNameIfExists); + if (name === '') { + nameErrText = 'Name is required'; + } else if (!this._isValidName(name)) { + nameErrText = 'Name should only contain letters, digits and spaces'; + } else if (name.length > maxLength) { + nameErrText = `Max length is ${maxLength}`; + } else if (tokenWithNameExists) { + nameErrText = 'Token with this name already exists'; + } - this.setState({ - name, - nameErrText, - }); - } - private _onTokenSymbolChanged(e: any, symbol: string) { - let symbolErrText = ''; - const maxLength = 5; - const tokens = _.values(this.props.tokenByAddress); - const tokenWithSymbolExists = !_.isUndefined(_.find(tokens, { symbol })); - if (symbol === '') { - symbolErrText = 'Symbol is required'; - } else if (!this._isAlphanumeric(symbol)) { - symbolErrText = 'Can only include alphanumeric characters'; - } else if (symbol.length > maxLength) { - symbolErrText = `Max length is ${maxLength}`; - } else if (tokenWithSymbolExists) { - symbolErrText = 'Token with symbol already exists'; - } + this.setState({ + name, + nameErrText, + }); + } + private _onTokenSymbolChanged(e: any, symbol: string) { + let symbolErrText = ''; + const maxLength = 5; + const tokens = _.values(this.props.tokenByAddress); + const tokenWithSymbolExists = !_.isUndefined(_.find(tokens, { symbol })); + if (symbol === '') { + symbolErrText = 'Symbol is required'; + } else if (!this._isAlphanumeric(symbol)) { + symbolErrText = 'Can only include alphanumeric characters'; + } else if (symbol.length > maxLength) { + symbolErrText = `Max length is ${maxLength}`; + } else if (tokenWithSymbolExists) { + symbolErrText = 'Token with symbol already exists'; + } - this.setState({ - symbol, - symbolErrText, - }); - } - private _onTokenDecimalsChanged(e: any, decimals: string) { - let decimalsErrText = ''; - const maxLength = 2; - if (decimals === '') { - decimalsErrText = 'Decimals is required'; - } else if (!this._isInteger(decimals)) { - decimalsErrText = 'Must be an integer'; - } else if (decimals.length > maxLength) { - decimalsErrText = `Max length is ${maxLength}`; - } + this.setState({ + symbol, + symbolErrText, + }); + } + private _onTokenDecimalsChanged(e: any, decimals: string) { + let decimalsErrText = ''; + const maxLength = 2; + if (decimals === '') { + decimalsErrText = 'Decimals is required'; + } else if (!this._isInteger(decimals)) { + decimalsErrText = 'Must be an integer'; + } else if (decimals.length > maxLength) { + decimalsErrText = `Max length is ${maxLength}`; + } - this.setState({ - decimals, - decimalsErrText, - }); - } - private _onTokenAddressChanged(address?: string) { - if (!_.isUndefined(address)) { - this.setState({ - address, - }); - } - } - private _isValidName(input: string) { - return /^[a-z0-9 ]+$/i.test(input); - } - private _isInteger(input: string) { - return /^[0-9]+$/i.test(input); - } - private _isAlphanumeric(input: string) { - return /^[a-zA-Z0-9]+$/i.test(input); - } + this.setState({ + decimals, + decimalsErrText, + }); + } + private _onTokenAddressChanged(address?: string) { + if (!_.isUndefined(address)) { + this.setState({ + address, + }); + } + } + private _isValidName(input: string) { + return /^[a-z0-9 ]+$/i.test(input); + } + private _isInteger(input: string) { + return /^[0-9]+$/i.test(input); + } + private _isAlphanumeric(input: string) { + return /^[a-zA-Z0-9]+$/i.test(input); + } } |