-
Notifications
You must be signed in to change notification settings - Fork 465
[instant][types][order-utils][asset-buyer] Move over and clean up features from zrx-buyer #1131
Changes from all commits
19f6190
63652df
0edd9b3
1c92ae0
03b235b
09c5ae4
f3391e1
025614a
ccf021b
f395414
e7130af
43f8f2a
fcf3451
ac3bfdf
fa18db8
18667d7
f2e5fd8
875f621
d268e19
dbf5be6
2610868
c328616
6a89935
d2adbc3
009b5b5
8ba6534
eda0b3e
32beeae
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,17 +3,21 @@ import * as _ from 'lodash'; | |
import * as React from 'react'; | ||
|
||
import { ColorOption } from '../style/theme'; | ||
import { util } from '../util/util'; | ||
|
||
import { Container, Input } from './ui'; | ||
|
||
export interface AmountInputProps { | ||
fontColor?: ColorOption; | ||
fontSize?: string; | ||
value?: BigNumber; | ||
onChange?: (value?: BigNumber) => void; | ||
onChange: (value?: BigNumber) => void; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. just curious -- why move this from being optional to being required but having a default no-op? is this a pattern we want to follow for callbacks? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So yea this is a bit confusing. @types/react and ts > 3.0.0 added understanding of So in practice it's not required, has default no-ops, so internally you can assume it's not undefined. And yea I like this pattern :P |
||
} | ||
|
||
export class AmountInput extends React.Component<AmountInputProps> { | ||
public static defaultProps = { | ||
onChange: util.boundNoop, | ||
}; | ||
public render(): React.ReactNode { | ||
const { fontColor, fontSize, value } = this.props; | ||
return ( | ||
|
@@ -24,7 +28,7 @@ export class AmountInput extends React.Component<AmountInputProps> { | |
onChange={this._handleChange} | ||
value={!_.isUndefined(value) ? value.toString() : ''} | ||
placeholder="0.00" | ||
width="2em" | ||
width="2.2em" | ||
/> | ||
</Container> | ||
); | ||
|
@@ -40,8 +44,6 @@ export class AmountInput extends React.Component<AmountInputProps> { | |
return; | ||
} | ||
} | ||
if (!_.isUndefined(this.props.onChange)) { | ||
this.props.onChange(bigNumberValue); | ||
} | ||
this.props.onChange(bigNumberValue); | ||
}; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
import { AssetProxyId } from '@0xproject/types'; | ||
import { BigNumber } from '@0xproject/utils'; | ||
import * as _ from 'lodash'; | ||
import * as React from 'react'; | ||
|
||
import { assetMetaData } from '../data/asset_meta_data'; | ||
import { ColorOption } from '../style/theme'; | ||
import { util } from '../util/util'; | ||
|
||
import { AmountInput, AmountInputProps } from './amount_input'; | ||
import { Container, Text } from './ui'; | ||
|
||
export interface AssetAmountInputProps extends AmountInputProps { | ||
assetData?: string; | ||
onChange: (value?: BigNumber, assetData?: string) => void; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. are we ever going to have a case where we have a value but not an assetData? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In practice no, but those two things can be |
||
} | ||
|
||
export class AssetAmountInput extends React.Component<AssetAmountInputProps> { | ||
public static defaultProps = { | ||
onChange: util.boundNoop, | ||
}; | ||
public render(): React.ReactNode { | ||
const { assetData, onChange, ...rest } = this.props; | ||
return ( | ||
<Container> | ||
<AmountInput {...rest} onChange={this._handleChange} /> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this is a design / polish nit, I think we want the text in this input to be right justified so that if you have typed just '5' then the character '5' is close to the symbol label There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Will do in a future PR (added to my list) |
||
<Container display="inline-block" marginLeft="10px"> | ||
<Text fontSize={rest.fontSize} fontColor={ColorOption.white} textTransform="uppercase"> | ||
{this._getAssetSymbolLabel()} | ||
</Text> | ||
</Container> | ||
</Container> | ||
); | ||
} | ||
private readonly _getAssetSymbolLabel = (): string => { | ||
const unknownLabel = '???'; | ||
if (_.isUndefined(this.props.assetData)) { | ||
return unknownLabel; | ||
} | ||
const metaData = assetMetaData[this.props.assetData]; | ||
if (_.isUndefined(metaData)) { | ||
return unknownLabel; | ||
} | ||
if (metaData.assetProxyId === AssetProxyId.ERC20) { | ||
return metaData.symbol; | ||
} | ||
return unknownLabel; | ||
}; | ||
private readonly _handleChange = (value?: BigNumber): void => { | ||
this.props.onChange(value, this.props.assetData); | ||
}; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,19 +1,53 @@ | ||
import { BuyQuote } from '@0xproject/asset-buyer'; | ||
import * as _ from 'lodash'; | ||
import * as React from 'react'; | ||
|
||
import { ColorOption } from '../style/theme'; | ||
import { assetBuyer } from '../util/asset_buyer'; | ||
import { util } from '../util/util'; | ||
import { web3Wrapper } from '../util/web3_wrapper'; | ||
|
||
import { Button, Container, Text } from './ui'; | ||
|
||
export interface BuyButtonProps {} | ||
export interface BuyButtonProps { | ||
buyQuote?: BuyQuote; | ||
onClick: (buyQuote: BuyQuote) => void; | ||
onBuySuccess: (buyQuote: BuyQuote, txnHash: string) => void; | ||
onBuyFailure: (buyQuote: BuyQuote, tnxHash?: string) => void; | ||
text: string; | ||
} | ||
|
||
export const BuyButton: React.StatelessComponent<BuyButtonProps> = props => ( | ||
<Container padding="20px" width="100%"> | ||
<Button width="100%"> | ||
<Text fontColor={ColorOption.white} fontWeight={600} fontSize="20px"> | ||
Buy | ||
</Text> | ||
</Button> | ||
</Container> | ||
); | ||
|
||
BuyButton.displayName = 'BuyButton'; | ||
export class BuyButton extends React.Component<BuyButtonProps> { | ||
public static defaultProps = { | ||
onClick: util.boundNoop, | ||
onBuySuccess: util.boundNoop, | ||
onBuyFailure: util.boundNoop, | ||
}; | ||
public render(): React.ReactNode { | ||
const shouldDisableButton = _.isUndefined(this.props.buyQuote); | ||
return ( | ||
<Container padding="20px" width="100%"> | ||
<Button width="100%" onClick={this._handleClick} isDisabled={shouldDisableButton}> | ||
<Text fontColor={ColorOption.white} fontWeight={600} fontSize="20px"> | ||
{this.props.text} | ||
</Text> | ||
</Button> | ||
</Container> | ||
); | ||
} | ||
private readonly _handleClick = async () => { | ||
// The button is disabled when there is no buy quote anyway. | ||
if (_.isUndefined(this.props.buyQuote)) { | ||
return; | ||
} | ||
this.props.onClick(this.props.buyQuote); | ||
let txnHash; | ||
try { | ||
txnHash = await assetBuyer.executeBuyQuoteAsync(this.props.buyQuote); | ||
await web3Wrapper.awaitTransactionSuccessAsync(txnHash); | ||
this.props.onBuySuccess(this.props.buyQuote, txnHash); | ||
} catch { | ||
this.props.onBuyFailure(this.props.buyQuote, txnHash); | ||
} | ||
}; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,32 @@ | ||
import { BigNumber } from '@0xproject/utils'; | ||
import * as _ from 'lodash'; | ||
import * as React from 'react'; | ||
|
||
import { SelectedAssetAmountInput } from '../containers/selected_asset_amount_input'; | ||
import { ColorOption } from '../style/theme'; | ||
import { format } from '../util/format'; | ||
|
||
import { Container, Flex, Text } from './ui'; | ||
|
||
export interface InstantHeadingProps {} | ||
export interface InstantHeadingProps { | ||
selectedAssetAmount?: BigNumber; | ||
totalEthBaseAmount?: BigNumber; | ||
ethUsdPrice?: BigNumber; | ||
} | ||
|
||
const displaytotalEthBaseAmount = ({ selectedAssetAmount, totalEthBaseAmount }: InstantHeadingProps): string => { | ||
if (_.isUndefined(selectedAssetAmount)) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. should this logic just live in format? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I see format as just formatting ethereum amounts into strings (including ETH dollar amounts). This case is handling the input not having any value, which seems to specific. |
||
return '0 ETH'; | ||
} | ||
return format.ethBaseAmount(totalEthBaseAmount, 4, '...loading'); | ||
}; | ||
|
||
const displayUsdAmount = ({ totalEthBaseAmount, selectedAssetAmount, ethUsdPrice }: InstantHeadingProps): string => { | ||
if (_.isUndefined(selectedAssetAmount)) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. same as above |
||
return '$0.00'; | ||
} | ||
return format.ethBaseAmountInUsd(totalEthBaseAmount, ethUsdPrice, 2, '...loading'); | ||
}; | ||
|
||
export const InstantHeading: React.StatelessComponent<InstantHeadingProps> = props => ( | ||
<Container backgroundColor={ColorOption.primaryColor} padding="20px" width="100%" borderRadius="3px 3px 0px 0px"> | ||
|
@@ -22,22 +43,15 @@ export const InstantHeading: React.StatelessComponent<InstantHeadingProps> = pro | |
</Text> | ||
</Container> | ||
<Flex direction="row" justify="space-between"> | ||
<Container> | ||
<SelectedAssetAmountInput fontSize="45px" /> | ||
<Container display="inline-block" marginLeft="10px"> | ||
<Text fontSize="45px" fontColor={ColorOption.white} textTransform="uppercase"> | ||
rep | ||
</Text> | ||
</Container> | ||
</Container> | ||
<SelectedAssetAmountInput fontSize="45px" /> | ||
<Flex direction="column" justify="space-between"> | ||
<Container marginBottom="5px"> | ||
<Text fontSize="16px" fontColor={ColorOption.white} fontWeight={500}> | ||
0 ETH | ||
{displaytotalEthBaseAmount(props)} | ||
</Text> | ||
</Container> | ||
<Text fontSize="16px" fontColor={ColorOption.white} opacity={0.7}> | ||
$0.00 | ||
{displayUsdAmount(props)} | ||
</Text> | ||
</Flex> | ||
</Flex> | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is value undefined if the input is empty?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yep! This is what made most sense to me.