diff options
author | fragosti <francesco.agosti93@gmail.com> | 2018-11-14 09:31:54 +0800 |
---|---|---|
committer | fragosti <francesco.agosti93@gmail.com> | 2018-11-14 09:31:54 +0800 |
commit | 84215f75e046597eb34f9d5409bd45410a0819e6 (patch) | |
tree | e6c57cdd7bc5064bdd6752d99c35779f3c1200c7 /packages | |
parent | 35bfd493e87b5d6c76f5bb2176b0992891a4a555 (diff) | |
parent | 4fc457b78b30e761164eac26fe5f1ebcddd11f7d (diff) | |
download | dexon-sol-tools-84215f75e046597eb34f9d5409bd45410a0819e6.tar dexon-sol-tools-84215f75e046597eb34f9d5409bd45410a0819e6.tar.gz dexon-sol-tools-84215f75e046597eb34f9d5409bd45410a0819e6.tar.bz2 dexon-sol-tools-84215f75e046597eb34f9d5409bd45410a0819e6.tar.lz dexon-sol-tools-84215f75e046597eb34f9d5409bd45410a0819e6.tar.xz dexon-sol-tools-84215f75e046597eb34f9d5409bd45410a0819e6.tar.zst dexon-sol-tools-84215f75e046597eb34f9d5409bd45410a0819e6.zip |
Merge branch 'development' of https://github.com/0xProject/0x-monorepo into feature/instant/different-install-wallet-copy-for-mobile
Diffstat (limited to 'packages')
24 files changed, 179 insertions, 130 deletions
diff --git a/packages/asset-buyer/CHANGELOG.json b/packages/asset-buyer/CHANGELOG.json index 26b3e65d4..826b6150d 100644 --- a/packages/asset-buyer/CHANGELOG.json +++ b/packages/asset-buyer/CHANGELOG.json @@ -1,5 +1,14 @@ [ { + "version": "3.0.0", + "changes": [ + { + "note": "update `getBuyQuoteAsync` to return eth spent on assets instead of per unit amount", + "pr": 1252 + } + ] + }, + { "timestamp": 1542134075, "version": "2.2.2", "changes": [ diff --git a/packages/asset-buyer/src/types.ts b/packages/asset-buyer/src/types.ts index 3f1e6ff21..3b573edca 100644 --- a/packages/asset-buyer/src/types.ts +++ b/packages/asset-buyer/src/types.ts @@ -54,12 +54,12 @@ export interface BuyQuote { } /** - * ethPerAssetPrice: The price of one unit of the desired asset in ETH + * assetEthAmount: The amount of eth required to pay for the requested asset. * feeEthAmount: The amount of eth required to pay the affiliate fee. - * totalEthAmount: the total amount of eth required to complete the buy. (Filling orders, feeOrders, and paying affiliate fee) + * totalEthAmount: The total amount of eth required to complete the buy (filling orders, feeOrders, and paying affiliate fee). */ export interface BuyQuoteInfo { - ethPerAssetPrice: BigNumber; + assetEthAmount: BigNumber; feeEthAmount: BigNumber; totalEthAmount: BigNumber; } diff --git a/packages/asset-buyer/src/utils/assert.ts b/packages/asset-buyer/src/utils/assert.ts index 2466f53a4..fcf9b0d0e 100644 --- a/packages/asset-buyer/src/utils/assert.ts +++ b/packages/asset-buyer/src/utils/assert.ts @@ -18,7 +18,7 @@ export const assert = { } }, isValidBuyQuoteInfo(variableName: string, buyQuoteInfo: BuyQuoteInfo): void { - sharedAssert.isBigNumber(`${variableName}.ethPerAssetPrice`, buyQuoteInfo.ethPerAssetPrice); + sharedAssert.isBigNumber(`${variableName}.assetEthAmount`, buyQuoteInfo.assetEthAmount); sharedAssert.isBigNumber(`${variableName}.feeEthAmount`, buyQuoteInfo.feeEthAmount); sharedAssert.isBigNumber(`${variableName}.totalEthAmount`, buyQuoteInfo.totalEthAmount); }, diff --git a/packages/asset-buyer/src/utils/buy_quote_calculator.ts b/packages/asset-buyer/src/utils/buy_quote_calculator.ts index 6a67ed1ed..b15b880c2 100644 --- a/packages/asset-buyer/src/utils/buy_quote_calculator.ts +++ b/packages/asset-buyer/src/utils/buy_quote_calculator.ts @@ -106,28 +106,28 @@ function calculateQuoteInfo( isMakerAssetZrxToken: boolean, ): BuyQuoteInfo { // find the total eth and zrx needed to buy assetAmount from the resultOrders from left to right - let ethAmountToBuyAsset = constants.ZERO_AMOUNT; - let ethAmountToBuyZrx = constants.ZERO_AMOUNT; + let assetEthAmount = constants.ZERO_AMOUNT; + let zrxEthAmount = constants.ZERO_AMOUNT; if (isMakerAssetZrxToken) { - ethAmountToBuyAsset = findEthAmountNeededToBuyZrx(ordersAndFillableAmounts, assetBuyAmount); + assetEthAmount = findEthAmountNeededToBuyZrx(ordersAndFillableAmounts, assetBuyAmount); } else { // find eth and zrx amounts needed to buy const ethAndZrxAmountToBuyAsset = findEthAndZrxAmountNeededToBuyAsset(ordersAndFillableAmounts, assetBuyAmount); - ethAmountToBuyAsset = ethAndZrxAmountToBuyAsset[0]; + assetEthAmount = ethAndZrxAmountToBuyAsset[0]; const zrxAmountToBuyAsset = ethAndZrxAmountToBuyAsset[1]; // find eth amount needed to buy zrx - ethAmountToBuyZrx = findEthAmountNeededToBuyZrx(feeOrdersAndFillableAmounts, zrxAmountToBuyAsset); + zrxEthAmount = findEthAmountNeededToBuyZrx(feeOrdersAndFillableAmounts, zrxAmountToBuyAsset); } - /// find the eth amount needed to buy the affiliate fee - const ethAmountToBuyAffiliateFee = ethAmountToBuyAsset.mul(feePercentage).ceil(); - const totalEthAmountWithoutAffiliateFee = ethAmountToBuyAsset.plus(ethAmountToBuyZrx); - const ethAmountTotal = totalEthAmountWithoutAffiliateFee.plus(ethAmountToBuyAffiliateFee); - // divide into the assetBuyAmount in order to find rate of makerAsset / WETH - const ethPerAssetPrice = totalEthAmountWithoutAffiliateFee.div(assetBuyAmount); + // eth amount needed to buy the affiliate fee + const affiliateFeeEthAmount = assetEthAmount.mul(feePercentage).ceil(); + // eth amount needed for fees is the sum of affiliate fee and zrx fee + const feeEthAmount = affiliateFeeEthAmount.plus(zrxEthAmount); + // eth amount needed in total is the sum of the amount needed for the asset and the amount needed for fees + const totalEthAmount = assetEthAmount.plus(feeEthAmount); return { - totalEthAmount: ethAmountTotal, - feeEthAmount: ethAmountToBuyAffiliateFee, - ethPerAssetPrice, + assetEthAmount, + feeEthAmount, + totalEthAmount, }; } diff --git a/packages/asset-buyer/test/buy_quote_calculator_test.ts b/packages/asset-buyer/test/buy_quote_calculator_test.ts index 0ea371982..a30017b72 100644 --- a/packages/asset-buyer/test/buy_quote_calculator_test.ts +++ b/packages/asset-buyer/test/buy_quote_calculator_test.ts @@ -108,17 +108,17 @@ describe('buyQuoteCalculator', () => { // 50 eth to fill the first order + 100 eth for fees const expectedEthAmountForAsset = new BigNumber(50); const expectedEthAmountForZrxFees = new BigNumber(100); - const expectedFillEthAmount = expectedEthAmountForAsset.plus(expectedEthAmountForZrxFees); - const expectedFeeEthAmount = expectedEthAmountForAsset.mul(feePercentage); + const expectedFillEthAmount = expectedEthAmountForAsset; + const expectedAffiliateFeeEthAmount = expectedEthAmountForAsset.mul(feePercentage); + const expectedFeeEthAmount = expectedAffiliateFeeEthAmount.plus(expectedEthAmountForZrxFees); const expectedTotalEthAmount = expectedFillEthAmount.plus(expectedFeeEthAmount); - const expectedEthPerAssetPrice = expectedFillEthAmount.div(assetBuyAmount); + expect(buyQuote.bestCaseQuoteInfo.assetEthAmount).to.bignumber.equal(expectedFillEthAmount); expect(buyQuote.bestCaseQuoteInfo.feeEthAmount).to.bignumber.equal(expectedFeeEthAmount); expect(buyQuote.bestCaseQuoteInfo.totalEthAmount).to.bignumber.equal(expectedTotalEthAmount); - expect(buyQuote.bestCaseQuoteInfo.ethPerAssetPrice).to.bignumber.equal(expectedEthPerAssetPrice); // because we have no slippage protection, minRate is equal to maxRate + expect(buyQuote.worstCaseQuoteInfo.assetEthAmount).to.bignumber.equal(expectedFillEthAmount); expect(buyQuote.worstCaseQuoteInfo.feeEthAmount).to.bignumber.equal(expectedFeeEthAmount); expect(buyQuote.worstCaseQuoteInfo.totalEthAmount).to.bignumber.equal(expectedTotalEthAmount); - expect(buyQuote.worstCaseQuoteInfo.ethPerAssetPrice).to.bignumber.equal(expectedEthPerAssetPrice); // test if feePercentage gets passed through expect(buyQuote.feePercentage).to.equal(feePercentage); }); @@ -146,23 +146,23 @@ describe('buyQuoteCalculator', () => { // 50 eth to fill the first order + 100 eth for fees const expectedEthAmountForAsset = new BigNumber(50); const expectedEthAmountForZrxFees = new BigNumber(100); - const expectedFillEthAmount = expectedEthAmountForAsset.plus(expectedEthAmountForZrxFees); - const expectedFeeEthAmount = expectedEthAmountForAsset.mul(feePercentage); + const expectedFillEthAmount = expectedEthAmountForAsset; + const expectedAffiliateFeeEthAmount = expectedEthAmountForAsset.mul(feePercentage); + const expectedFeeEthAmount = expectedAffiliateFeeEthAmount.plus(expectedEthAmountForZrxFees); const expectedTotalEthAmount = expectedFillEthAmount.plus(expectedFeeEthAmount); - const expectedEthPerAssetPrice = expectedFillEthAmount.div(assetBuyAmount); + expect(buyQuote.bestCaseQuoteInfo.assetEthAmount).to.bignumber.equal(expectedFillEthAmount); expect(buyQuote.bestCaseQuoteInfo.feeEthAmount).to.bignumber.equal(expectedFeeEthAmount); expect(buyQuote.bestCaseQuoteInfo.totalEthAmount).to.bignumber.equal(expectedTotalEthAmount); - expect(buyQuote.bestCaseQuoteInfo.ethPerAssetPrice).to.bignumber.equal(expectedEthPerAssetPrice); // 100 eth to fill the first order + 208 eth for fees const expectedWorstEthAmountForAsset = new BigNumber(100); const expectedWorstEthAmountForZrxFees = new BigNumber(208); - const expectedWorstFillEthAmount = expectedWorstEthAmountForAsset.plus(expectedWorstEthAmountForZrxFees); - const expectedWorstFeeEthAmount = expectedWorstEthAmountForAsset.mul(feePercentage); + const expectedWorstFillEthAmount = expectedWorstEthAmountForAsset; + const expectedWorstAffiliateFeeEthAmount = expectedWorstEthAmountForAsset.mul(feePercentage); + const expectedWorstFeeEthAmount = expectedWorstAffiliateFeeEthAmount.plus(expectedWorstEthAmountForZrxFees); const expectedWorstTotalEthAmount = expectedWorstFillEthAmount.plus(expectedWorstFeeEthAmount); - const expectedWorstEthPerAssetPrice = expectedWorstFillEthAmount.div(assetBuyAmount); + expect(buyQuote.worstCaseQuoteInfo.assetEthAmount).to.bignumber.equal(expectedWorstFillEthAmount); expect(buyQuote.worstCaseQuoteInfo.feeEthAmount).to.bignumber.equal(expectedWorstFeeEthAmount); expect(buyQuote.worstCaseQuoteInfo.totalEthAmount).to.bignumber.equal(expectedWorstTotalEthAmount); - expect(buyQuote.worstCaseQuoteInfo.ethPerAssetPrice).to.bignumber.equal(expectedWorstEthPerAssetPrice); // test if feePercentage gets passed through expect(buyQuote.feePercentage).to.equal(feePercentage); }); diff --git a/packages/instant/src/components/instant_heading.tsx b/packages/instant/src/components/instant_heading.tsx index b07776b2c..7f9567454 100644 --- a/packages/instant/src/components/instant_heading.tsx +++ b/packages/instant/src/components/instant_heading.tsx @@ -15,8 +15,8 @@ import { Spinner } from './ui/spinner'; import { Text } from './ui/text'; export interface InstantHeadingProps { - selectedAssetAmount?: BigNumber; - totalEthBaseAmount?: BigNumber; + selectedAssetUnitAmount?: BigNumber; + totalEthBaseUnitAmount?: BigNumber; ethUsdPrice?: BigNumber; quoteRequestState: AsyncProcessState; buyOrderState: OrderState; @@ -104,7 +104,7 @@ export class InstantHeading extends React.Component<InstantHeadingProps, {}> { if (this.props.quoteRequestState === AsyncProcessState.Pending) { return <AmountPlaceholder isPulsating={true} color={PLACEHOLDER_COLOR} />; } - if (_.isUndefined(this.props.selectedAssetAmount)) { + if (_.isUndefined(this.props.selectedAssetUnitAmount)) { return <AmountPlaceholder isPulsating={false} color={PLACEHOLDER_COLOR} />; } return amountFunction(); @@ -113,8 +113,8 @@ export class InstantHeading extends React.Component<InstantHeadingProps, {}> { private readonly _renderEthAmount = (): React.ReactNode => { return ( <Text fontSize="16px" fontColor={ColorOption.white} fontWeight={500}> - {format.ethBaseAmount( - this.props.totalEthBaseAmount, + {format.ethBaseUnitAmount( + this.props.totalEthBaseUnitAmount, 4, <AmountPlaceholder isPulsating={false} color={PLACEHOLDER_COLOR} />, )} @@ -125,8 +125,8 @@ export class InstantHeading extends React.Component<InstantHeadingProps, {}> { private readonly _renderDollarAmount = (): React.ReactNode => { return ( <Text fontSize="16px" fontColor={ColorOption.white}> - {format.ethBaseAmountInUsd( - this.props.totalEthBaseAmount, + {format.ethBaseUnitAmountInUsd( + this.props.totalEthBaseUnitAmount, this.props.ethUsdPrice, 2, <AmountPlaceholder isPulsating={false} color={ColorOption.white} />, diff --git a/packages/instant/src/components/order_details.tsx b/packages/instant/src/components/order_details.tsx index 9abd7137e..5fc956e1c 100644 --- a/packages/instant/src/components/order_details.tsx +++ b/packages/instant/src/components/order_details.tsx @@ -4,6 +4,7 @@ import * as _ from 'lodash'; import * as React from 'react'; import { oc } from 'ts-optchain'; +import { BIG_NUMBER_ZERO } from '../constants'; import { ColorOption } from '../style/theme'; import { format } from '../util/format'; @@ -15,16 +16,23 @@ import { Text } from './ui/text'; export interface OrderDetailsProps { buyQuoteInfo?: BuyQuoteInfo; + selectedAssetUnitAmount?: BigNumber; ethUsdPrice?: BigNumber; isLoading: boolean; } export class OrderDetails extends React.Component<OrderDetailsProps> { public render(): React.ReactNode { - const { buyQuoteInfo, ethUsdPrice } = this.props; + const { buyQuoteInfo, ethUsdPrice, selectedAssetUnitAmount } = this.props; const buyQuoteAccessor = oc(buyQuoteInfo); - const ethAssetPrice = buyQuoteAccessor.ethPerAssetPrice(); - const ethTokenFee = buyQuoteAccessor.feeEthAmount(); - const totalEthAmount = buyQuoteAccessor.totalEthAmount(); + const assetEthBaseUnitAmount = buyQuoteAccessor.assetEthAmount(); + const feeEthBaseUnitAmount = buyQuoteAccessor.feeEthAmount(); + const totalEthBaseUnitAmount = buyQuoteAccessor.totalEthAmount(); + const pricePerTokenEth = + !_.isUndefined(assetEthBaseUnitAmount) && + !_.isUndefined(selectedAssetUnitAmount) && + !selectedAssetUnitAmount.eq(BIG_NUMBER_ZERO) + ? assetEthBaseUnitAmount.div(selectedAssetUnitAmount).ceil() + : undefined; return ( <Container padding="20px" width="100%" flexGrow={1}> <Container marginBottom="10px"> @@ -40,20 +48,19 @@ export class OrderDetails extends React.Component<OrderDetailsProps> { </Container> <EthAmountRow rowLabel="Token Price" - ethAmount={ethAssetPrice} + ethAmount={pricePerTokenEth} ethUsdPrice={ethUsdPrice} - isEthAmountInBaseUnits={false} isLoading={this.props.isLoading} /> <EthAmountRow rowLabel="Fee" - ethAmount={ethTokenFee} + ethAmount={feeEthBaseUnitAmount} ethUsdPrice={ethUsdPrice} isLoading={this.props.isLoading} /> <EthAmountRow rowLabel="Total Cost" - ethAmount={totalEthAmount} + ethAmount={totalEthBaseUnitAmount} ethUsdPrice={ethUsdPrice} shouldEmphasize={true} isLoading={this.props.isLoading} @@ -81,7 +88,7 @@ export class EthAmountRow extends React.Component<EthAmountRowProps> { const { rowLabel, ethAmount, isEthAmountInBaseUnits, shouldEmphasize, isLoading } = this.props; const fontWeight = shouldEmphasize ? 700 : 400; - const ethFormatter = isEthAmountInBaseUnits ? format.ethBaseAmount : format.ethUnitAmount; + const ethFormatter = isEthAmountInBaseUnits ? format.ethBaseUnitAmount : format.ethUnitAmount; return ( <Container padding="10px 0px" borderTop="1px dashed" borderColor={ColorOption.feintGrey}> <Flex justify="space-between"> @@ -105,7 +112,9 @@ export class EthAmountRow extends React.Component<EthAmountRowProps> { ); } private _renderUsdSection(): React.ReactNode { - const usdFormatter = this.props.isEthAmountInBaseUnits ? format.ethBaseAmountInUsd : format.ethUnitAmountInUsd; + const usdFormatter = this.props.isEthAmountInBaseUnits + ? format.ethBaseUnitAmountInUsd + : format.ethUnitAmountInUsd; const shouldHideUsdPriceSection = _.isUndefined(this.props.ethUsdPrice) || _.isUndefined(this.props.ethAmount); return shouldHideUsdPriceSection ? null : ( <Container marginRight="3px" display="inline-block"> diff --git a/packages/instant/src/components/payment_method_dropdown.tsx b/packages/instant/src/components/payment_method_dropdown.tsx index bdce2a49d..58f1cc044 100644 --- a/packages/instant/src/components/payment_method_dropdown.tsx +++ b/packages/instant/src/components/payment_method_dropdown.tsx @@ -18,7 +18,7 @@ export class PaymentMethodDropdown extends React.Component<PaymentMethodDropdown public render(): React.ReactNode { const { accountAddress, accountEthBalanceInWei } = this.props; const value = format.ethAddress(accountAddress); - const label = format.ethBaseAmount(accountEthBalanceInWei, 4, '') as string; + const label = format.ethBaseUnitAmount(accountEthBalanceInWei, 4, '') as string; return <Dropdown value={value} label={label} items={this._getDropdownItemConfigs()} />; } private readonly _getDropdownItemConfigs = (): DropdownItemConfig[] => { diff --git a/packages/instant/src/components/zero_ex_instant.tsx b/packages/instant/src/components/zero_ex_instant.tsx index f6ee28dba..2267b4dbf 100644 --- a/packages/instant/src/components/zero_ex_instant.tsx +++ b/packages/instant/src/components/zero_ex_instant.tsx @@ -1,7 +1,8 @@ import * as React from 'react'; +import { ZeroExInstantContainer } from '../components/zero_ex_instant_container'; + import { INJECTED_DIV_CLASS } from '../constants'; -import { ConnectedZeroExInstantContainer } from '../containers/connected_zero_ex_instant_container'; import { ZeroExInstantProvider, ZeroExInstantProviderProps } from './zero_ex_instant_provider'; @@ -11,7 +12,7 @@ export const ZeroExInstant: React.StatelessComponent<ZeroExInstantProps> = props return ( <div className={INJECTED_DIV_CLASS}> <ZeroExInstantProvider {...props}> - <ConnectedZeroExInstantContainer /> + <ZeroExInstantContainer /> </ZeroExInstantProvider> </div> ); diff --git a/packages/instant/src/components/zero_ex_instant_container.tsx b/packages/instant/src/components/zero_ex_instant_container.tsx index 60f80e8d1..c0a197590 100644 --- a/packages/instant/src/components/zero_ex_instant_container.tsx +++ b/packages/instant/src/components/zero_ex_instant_container.tsx @@ -1,11 +1,10 @@ import * as React from 'react'; import { AvailableERC20TokenSelector } from '../containers/available_erc20_token_selector'; -import { ConnectedAccountPaymentMethod } from '../containers/connected_account_payment_method'; +import { ConnectedBuyOrderProgressOrPaymentMethod } from '../containers/connected_buy_order_progress_or_payment_method'; import { CurrentStandardSlidingPanel } from '../containers/current_standard_sliding_panel'; import { LatestBuyQuoteOrderDetails } from '../containers/latest_buy_quote_order_details'; import { LatestError } from '../containers/latest_error'; -import { SelectedAssetBuyOrderProgress } from '../containers/selected_asset_buy_order_progress'; import { SelectedAssetBuyOrderStateButtons } from '../containers/selected_asset_buy_order_state_buttons'; import { SelectedAssetInstantHeading } from '../containers/selected_asset_instant_heading'; import { ColorOption } from '../style/theme'; @@ -24,7 +23,7 @@ export interface ZeroExInstantContainerState { tokenSelectionPanelAnimationState: SlideAnimationState; } -export class ZeroExInstantContainer extends React.Component<ZeroExInstantContainerProps, ZeroExInstantContainerState> { +export class ZeroExInstantContainer extends React.Component<{}, ZeroExInstantContainerState> { public state = { tokenSelectionPanelAnimationState: 'none' as SlideAnimationState, }; @@ -51,7 +50,7 @@ export class ZeroExInstantContainer extends React.Component<ZeroExInstantContain > <Flex direction="column" justify="flex-start" height="100%"> <SelectedAssetInstantHeading onSelectAssetClick={this._handleSymbolClick} /> - {this._renderPaymentMethodOrBuyOrderProgress()} + <ConnectedBuyOrderProgressOrPaymentMethod /> <LatestBuyQuoteOrderDetails /> <Container padding="20px" width="100%"> <SelectedAssetBuyOrderStateButtons /> @@ -79,16 +78,4 @@ export class ZeroExInstantContainer extends React.Component<ZeroExInstantContain tokenSelectionPanelAnimationState: 'slidOut', }); }; - private readonly _renderPaymentMethodOrBuyOrderProgress = (): React.ReactNode => { - const { orderProcessState } = this.props; - if ( - orderProcessState === OrderProcessState.Processing || - orderProcessState === OrderProcessState.Success || - orderProcessState === OrderProcessState.Failure - ) { - return <SelectedAssetBuyOrderProgress />; - } else { - return <ConnectedAccountPaymentMethod />; - } - }; } diff --git a/packages/instant/src/components/zero_ex_instant_overlay.tsx b/packages/instant/src/components/zero_ex_instant_overlay.tsx index a7e1bd65a..2856ea3e3 100644 --- a/packages/instant/src/components/zero_ex_instant_overlay.tsx +++ b/packages/instant/src/components/zero_ex_instant_overlay.tsx @@ -1,6 +1,6 @@ import * as React from 'react'; -import { ConnectedZeroExInstantContainer } from '../containers/connected_zero_ex_instant_container'; +import { ZeroExInstantContainer } from '../components/zero_ex_instant_container'; import { ColorOption } from '../style/theme'; import { Container } from './ui/container'; @@ -31,7 +31,7 @@ export const ZeroExInstantOverlay: React.StatelessComponent<ZeroExInstantOverlay /> </Container> <Container width={{ default: 'auto', sm: '100%' }} height={{ default: 'auto', sm: '100%' }}> - <ConnectedZeroExInstantContainer /> + <ZeroExInstantContainer /> </Container> </Flex> </Overlay> diff --git a/packages/instant/src/components/zero_ex_instant_provider.tsx b/packages/instant/src/components/zero_ex_instant_provider.tsx index 863bc99b7..18e71edb6 100644 --- a/packages/instant/src/components/zero_ex_instant_provider.tsx +++ b/packages/instant/src/components/zero_ex_instant_provider.tsx @@ -73,7 +73,7 @@ export class ZeroExInstantProvider extends React.Component<ZeroExInstantProvider completeAssetMetaDataMap, networkId, ), - selectedAssetAmount: _.isUndefined(props.defaultAssetBuyAmount) + selectedAssetUnitAmount: _.isUndefined(props.defaultAssetBuyAmount) ? undefined : new BigNumber(props.defaultAssetBuyAmount), availableAssets: _.isUndefined(props.availableAssetDatas) diff --git a/packages/instant/src/containers/connected_buy_order_progress_or_payment_method.tsx b/packages/instant/src/containers/connected_buy_order_progress_or_payment_method.tsx new file mode 100644 index 000000000..05071c8c3 --- /dev/null +++ b/packages/instant/src/containers/connected_buy_order_progress_or_payment_method.tsx @@ -0,0 +1,36 @@ +import * as React from 'react'; +import { connect } from 'react-redux'; + +import { State } from '../redux/reducer'; +import { OrderProcessState } from '../types'; + +import { ConnectedAccountPaymentMethod } from './connected_account_payment_method'; +import { SelectedAssetBuyOrderProgress } from './selected_asset_buy_order_progress'; + +interface BuyOrderProgressOrPaymentMethodProps { + orderProcessState: OrderProcessState; +} +export const BuyOrderProgressOrPaymentMethod = (props: BuyOrderProgressOrPaymentMethodProps) => { + const { orderProcessState } = props; + if ( + orderProcessState === OrderProcessState.Processing || + orderProcessState === OrderProcessState.Success || + orderProcessState === OrderProcessState.Failure + ) { + return <SelectedAssetBuyOrderProgress />; + } + if (orderProcessState === OrderProcessState.None) { + return <ConnectedAccountPaymentMethod />; + } + return null; +}; + +interface ConnectedState extends BuyOrderProgressOrPaymentMethodProps {} + +export interface ConnectedBuyOrderProgressOrPaymentMethodProps {} +const mapStateToProps = (state: State, _ownProps: ConnectedBuyOrderProgressOrPaymentMethodProps): ConnectedState => ({ + orderProcessState: state.buyOrderState.processState, +}); +export const ConnectedBuyOrderProgressOrPaymentMethod: React.ComponentClass< + ConnectedBuyOrderProgressOrPaymentMethodProps +> = connect(mapStateToProps)(BuyOrderProgressOrPaymentMethod); diff --git a/packages/instant/src/containers/connected_zero_ex_instant_container.ts b/packages/instant/src/containers/connected_zero_ex_instant_container.ts deleted file mode 100644 index 9606d18c2..000000000 --- a/packages/instant/src/containers/connected_zero_ex_instant_container.ts +++ /dev/null @@ -1,21 +0,0 @@ -import * as React from 'react'; -import { connect } from 'react-redux'; - -import { State } from '../redux/reducer'; -import { OrderProcessState } from '../types'; - -import { ZeroExInstantContainer } from '../components/zero_ex_instant_container'; - -export interface ConnectedZeroExInstantContainerProps {} - -interface ConnectedState { - orderProcessState: OrderProcessState; -} - -const mapStateToProps = (state: State, _ownProps: ConnectedZeroExInstantContainerProps): ConnectedState => ({ - orderProcessState: state.buyOrderState.processState, -}); - -export const ConnectedZeroExInstantContainer: React.ComponentClass<ConnectedZeroExInstantContainerProps> = connect( - mapStateToProps, -)(ZeroExInstantContainer); diff --git a/packages/instant/src/containers/latest_buy_quote_order_details.ts b/packages/instant/src/containers/latest_buy_quote_order_details.ts index 2b59ed3ae..5dfe535e7 100644 --- a/packages/instant/src/containers/latest_buy_quote_order_details.ts +++ b/packages/instant/src/containers/latest_buy_quote_order_details.ts @@ -14,6 +14,7 @@ export interface LatestBuyQuoteOrderDetailsProps {} interface ConnectedState { buyQuoteInfo?: BuyQuoteInfo; + selectedAssetUnitAmount?: BigNumber; ethUsdPrice?: BigNumber; isLoading: boolean; } @@ -21,6 +22,7 @@ interface ConnectedState { const mapStateToProps = (state: State, _ownProps: LatestBuyQuoteOrderDetailsProps): ConnectedState => ({ // use the worst case quote info buyQuoteInfo: oc(state).latestBuyQuote.worstCaseQuoteInfo(), + selectedAssetUnitAmount: state.selectedAssetUnitAmount, ethUsdPrice: state.ethUsdPrice, isLoading: state.quoteRequestState === AsyncProcessState.Pending, }); diff --git a/packages/instant/src/containers/selected_asset_instant_heading.ts b/packages/instant/src/containers/selected_asset_instant_heading.ts index a407279e6..8dc127e1d 100644 --- a/packages/instant/src/containers/selected_asset_instant_heading.ts +++ b/packages/instant/src/containers/selected_asset_instant_heading.ts @@ -14,16 +14,16 @@ export interface InstantHeadingProps { } interface ConnectedState { - selectedAssetAmount?: BigNumber; - totalEthBaseAmount?: BigNumber; + selectedAssetUnitAmount?: BigNumber; + totalEthBaseUnitAmount?: BigNumber; ethUsdPrice?: BigNumber; quoteRequestState: AsyncProcessState; buyOrderState: OrderState; } const mapStateToProps = (state: State, _ownProps: InstantHeadingProps): ConnectedState => ({ - selectedAssetAmount: state.selectedAssetAmount, - totalEthBaseAmount: oc(state).latestBuyQuote.worstCaseQuoteInfo.totalEthAmount(), + selectedAssetUnitAmount: state.selectedAssetUnitAmount, + totalEthBaseUnitAmount: oc(state).latestBuyQuote.worstCaseQuoteInfo.totalEthAmount(), ethUsdPrice: state.ethUsdPrice, quoteRequestState: state.quoteRequestState, buyOrderState: state.buyOrderState, diff --git a/packages/instant/src/containers/selected_erc20_asset_amount_input.ts b/packages/instant/src/containers/selected_erc20_asset_amount_input.ts index 30eb900e6..8b0070228 100644 --- a/packages/instant/src/containers/selected_erc20_asset_amount_input.ts +++ b/packages/instant/src/containers/selected_erc20_asset_amount_input.ts @@ -53,7 +53,7 @@ const mapStateToProps = (state: State, _ownProps: SelectedERC20AssetAmountInputP const assetBuyer = state.providerState.assetBuyer; return { assetBuyer, - value: state.selectedAssetAmount, + value: state.selectedAssetUnitAmount, asset: selectedAsset, isDisabled, numberOfAssetsAvailable, diff --git a/packages/instant/src/redux/actions.ts b/packages/instant/src/redux/actions.ts index 0891170b4..77e3dec12 100644 --- a/packages/instant/src/redux/actions.ts +++ b/packages/instant/src/redux/actions.ts @@ -26,7 +26,7 @@ export enum ActionTypes { SET_ACCOUNT_STATE_READY = 'SET_ACCOUNT_STATE_READY', UPDATE_ACCOUNT_ETH_BALANCE = 'UPDATE_ACCOUNT_ETH_BALANCE', UPDATE_ETH_USD_PRICE = 'UPDATE_ETH_USD_PRICE', - UPDATE_SELECTED_ASSET_AMOUNT = 'UPDATE_SELECTED_ASSET_AMOUNT', + UPDATE_SELECTED_ASSET_UNIT_AMOUNT = 'UPDATE_SELECTED_ASSET_UNIT_AMOUNT', SET_BUY_ORDER_STATE_NONE = 'SET_BUY_ORDER_STATE_NONE', SET_BUY_ORDER_STATE_VALIDATING = 'SET_BUY_ORDER_STATE_VALIDATING', SET_BUY_ORDER_STATE_PROCESSING = 'SET_BUY_ORDER_STATE_PROCESSING', @@ -52,7 +52,8 @@ export const actions = { updateAccountEthBalance: (addressAndBalance: AddressAndEthBalanceInWei) => createAction(ActionTypes.UPDATE_ACCOUNT_ETH_BALANCE, addressAndBalance), updateEthUsdPrice: (price?: BigNumber) => createAction(ActionTypes.UPDATE_ETH_USD_PRICE, price), - updateSelectedAssetAmount: (amount?: BigNumber) => createAction(ActionTypes.UPDATE_SELECTED_ASSET_AMOUNT, amount), + updateSelectedAssetAmount: (amount?: BigNumber) => + createAction(ActionTypes.UPDATE_SELECTED_ASSET_UNIT_AMOUNT, amount), setBuyOrderStateNone: () => createAction(ActionTypes.SET_BUY_ORDER_STATE_NONE), setBuyOrderStateValidating: () => createAction(ActionTypes.SET_BUY_ORDER_STATE_VALIDATING), setBuyOrderStateProcessing: (txHash: string, startTimeUnix: number, expectedEndTimeUnix: number) => diff --git a/packages/instant/src/redux/async_data.ts b/packages/instant/src/redux/async_data.ts index 15ac31a5a..a1952e429 100644 --- a/packages/instant/src/redux/async_data.ts +++ b/packages/instant/src/redux/async_data.ts @@ -84,10 +84,10 @@ export const asyncData = { dispatch: Dispatch, shouldSetPending: boolean = false, ) => { - const { buyOrderState, providerState, selectedAsset, selectedAssetAmount, affiliateInfo } = state; + const { buyOrderState, providerState, selectedAsset, selectedAssetUnitAmount, affiliateInfo } = state; const assetBuyer = providerState.assetBuyer; if ( - !_.isUndefined(selectedAssetAmount) && + !_.isUndefined(selectedAssetUnitAmount) && !_.isUndefined(selectedAsset) && buyOrderState.processState === OrderProcessState.None && selectedAsset.metaData.assetProxyId === AssetProxyId.ERC20 @@ -96,7 +96,7 @@ export const asyncData = { assetBuyer, dispatch, selectedAsset as ERC20Asset, - selectedAssetAmount, + selectedAssetUnitAmount, shouldSetPending, affiliateInfo, ); diff --git a/packages/instant/src/redux/reducer.ts b/packages/instant/src/redux/reducer.ts index 3d7c3f483..dfc2b89f3 100644 --- a/packages/instant/src/redux/reducer.ts +++ b/packages/instant/src/redux/reducer.ts @@ -44,7 +44,7 @@ interface PropsDerivedState { interface OptionalState { selectedAsset: Asset; availableAssets: Asset[]; - selectedAssetAmount: BigNumber; + selectedAssetUnitAmount: BigNumber; ethUsdPrice: BigNumber; latestBuyQuote: BuyQuote; latestErrorMessage: string; @@ -105,10 +105,10 @@ export const createReducer = (initialState: State) => { ...state, ethUsdPrice: action.data, }; - case ActionTypes.UPDATE_SELECTED_ASSET_AMOUNT: + case ActionTypes.UPDATE_SELECTED_ASSET_UNIT_AMOUNT: return { ...state, - selectedAssetAmount: action.data, + selectedAssetUnitAmount: action.data, }; case ActionTypes.UPDATE_LATEST_BUY_QUOTE: const newBuyQuoteIfExists = action.data; @@ -219,7 +219,7 @@ export const createReducer = (initialState: State) => { latestBuyQuote: undefined, quoteRequestState: AsyncProcessState.None, buyOrderState: { processState: OrderProcessState.None }, - selectedAssetAmount: undefined, + selectedAssetUnitAmount: undefined, }; case ActionTypes.SET_AVAILABLE_ASSETS: return { @@ -263,9 +263,9 @@ const reduceStateWithAccount = (state: State, account: Account) => { const doesBuyQuoteMatchState = (buyQuote: BuyQuote, state: State): boolean => { const selectedAssetIfExists = state.selectedAsset; - const selectedAssetAmountIfExists = state.selectedAssetAmount; + const selectedAssetUnitAmountIfExists = state.selectedAssetUnitAmount; // if no selectedAsset or selectedAssetAmount exists on the current state, return false - if (_.isUndefined(selectedAssetIfExists) || _.isUndefined(selectedAssetAmountIfExists)) { + if (_.isUndefined(selectedAssetIfExists) || _.isUndefined(selectedAssetUnitAmountIfExists)) { return false; } // if buyQuote's assetData does not match that of the current selected asset, return false @@ -277,7 +277,7 @@ const doesBuyQuoteMatchState = (buyQuote: BuyQuote, state: State): boolean => { const selectedAssetMetaData = selectedAssetIfExists.metaData; if (selectedAssetMetaData.assetProxyId === AssetProxyId.ERC20) { const selectedAssetAmountBaseUnits = Web3Wrapper.toBaseUnitAmount( - selectedAssetAmountIfExists, + selectedAssetUnitAmountIfExists, selectedAssetMetaData.decimals, ); const doesAssetAmountMatch = selectedAssetAmountBaseUnits.eq(buyQuote.assetBuyAmount); diff --git a/packages/instant/src/util/buy_quote_updater.ts b/packages/instant/src/util/buy_quote_updater.ts index c33e28f1c..fcdded0a9 100644 --- a/packages/instant/src/util/buy_quote_updater.ts +++ b/packages/instant/src/util/buy_quote_updater.ts @@ -15,12 +15,12 @@ export const buyQuoteUpdater = { assetBuyer: AssetBuyer, dispatch: Dispatch<Action>, asset: ERC20Asset, - assetAmount: BigNumber, + assetUnitAmount: BigNumber, setPending = true, affiliateInfo?: AffiliateInfo, ): Promise<void> => { // get a new buy quote. - const baseUnitValue = Web3Wrapper.toBaseUnitAmount(assetAmount, asset.metaData.decimals); + const baseUnitValue = Web3Wrapper.toBaseUnitAmount(assetUnitAmount, asset.metaData.decimals); if (setPending) { // mark quote as pending dispatch(actions.setQuoteRequestStatePending()); diff --git a/packages/instant/src/util/format.ts b/packages/instant/src/util/format.ts index 44661d697..e9c432b2f 100644 --- a/packages/instant/src/util/format.ts +++ b/packages/instant/src/util/format.ts @@ -5,15 +5,15 @@ import * as _ from 'lodash'; import { ETH_DECIMALS } from '../constants'; export const format = { - ethBaseAmount: ( - ethBaseAmount?: BigNumber, + ethBaseUnitAmount: ( + ethBaseUnitAmount?: BigNumber, decimalPlaces: number = 4, defaultText: React.ReactNode = '0 ETH', ): React.ReactNode => { - if (_.isUndefined(ethBaseAmount)) { + if (_.isUndefined(ethBaseUnitAmount)) { return defaultText; } - const ethUnitAmount = Web3Wrapper.toUnitAmount(ethBaseAmount, ETH_DECIMALS); + const ethUnitAmount = Web3Wrapper.toUnitAmount(ethBaseUnitAmount, ETH_DECIMALS); return format.ethUnitAmount(ethUnitAmount, decimalPlaces); }, ethUnitAmount: ( @@ -27,16 +27,16 @@ export const format = { const roundedAmount = ethUnitAmount.round(decimalPlaces).toDigits(decimalPlaces); return `${roundedAmount} ETH`; }, - ethBaseAmountInUsd: ( - ethBaseAmount?: BigNumber, + ethBaseUnitAmountInUsd: ( + ethBaseUnitAmount?: BigNumber, ethUsdPrice?: BigNumber, decimalPlaces: number = 2, defaultText: React.ReactNode = '$0.00', ): React.ReactNode => { - if (_.isUndefined(ethBaseAmount) || _.isUndefined(ethUsdPrice)) { + if (_.isUndefined(ethBaseUnitAmount) || _.isUndefined(ethUsdPrice)) { return defaultText; } - const ethUnitAmount = Web3Wrapper.toUnitAmount(ethBaseAmount, ETH_DECIMALS); + const ethUnitAmount = Web3Wrapper.toUnitAmount(ethBaseUnitAmount, ETH_DECIMALS); return format.ethUnitAmountInUsd(ethUnitAmount, ethUsdPrice, decimalPlaces); }, ethUnitAmountInUsd: ( diff --git a/packages/instant/test/util/format.test.ts b/packages/instant/test/util/format.test.ts index c346b7604..fe0a63e6e 100644 --- a/packages/instant/test/util/format.test.ts +++ b/packages/instant/test/util/format.test.ts @@ -15,20 +15,20 @@ const BIG_NUMBER_FAKE_ETH_USD_PRICE = new BigNumber(2.534); describe('format', () => { describe('ethBaseAmount', () => { it('converts 1 ETH in base units to the string `1 ETH`', () => { - expect(format.ethBaseAmount(ONE_ETH_IN_BASE_UNITS)).toBe('1 ETH'); + expect(format.ethBaseUnitAmount(ONE_ETH_IN_BASE_UNITS)).toBe('1 ETH'); }); it('converts .432414 ETH in base units to the string `.4324 ETH`', () => { - expect(format.ethBaseAmount(DECIMAL_ETH_IN_BASE_UNITS)).toBe('0.4324 ETH'); + expect(format.ethBaseUnitAmount(DECIMAL_ETH_IN_BASE_UNITS)).toBe('0.4324 ETH'); }); it('converts 5.3014059295032 ETH in base units to the string `5.301 ETH`', () => { - expect(format.ethBaseAmount(IRRATIONAL_ETH_IN_BASE_UNITS)).toBe('5.301 ETH'); + expect(format.ethBaseUnitAmount(IRRATIONAL_ETH_IN_BASE_UNITS)).toBe('5.301 ETH'); }); it('returns defaultText param when ethBaseAmount is not defined', () => { const defaultText = 'defaultText'; - expect(format.ethBaseAmount(undefined, 4, defaultText)).toBe(defaultText); + expect(format.ethBaseUnitAmount(undefined, 4, defaultText)).toBe(defaultText); }); it('it allows for configurable decimal places', () => { - expect(format.ethBaseAmount(DECIMAL_ETH_IN_BASE_UNITS, 2)).toBe('0.43 ETH'); + expect(format.ethBaseUnitAmount(DECIMAL_ETH_IN_BASE_UNITS, 2)).toBe('0.43 ETH'); }); }); describe('ethUnitAmount', () => { @@ -52,24 +52,26 @@ describe('format', () => { }); describe('ethBaseAmountInUsd', () => { it('correctly formats 1 ETH to usd according to some price', () => { - expect(format.ethBaseAmountInUsd(ONE_ETH_IN_BASE_UNITS, BIG_NUMBER_FAKE_ETH_USD_PRICE)).toBe('$2.53'); + expect(format.ethBaseUnitAmountInUsd(ONE_ETH_IN_BASE_UNITS, BIG_NUMBER_FAKE_ETH_USD_PRICE)).toBe('$2.53'); }); it('correctly formats .432414 ETH to usd according to some price', () => { - expect(format.ethBaseAmountInUsd(DECIMAL_ETH_IN_BASE_UNITS, BIG_NUMBER_FAKE_ETH_USD_PRICE)).toBe('$1.10'); + expect(format.ethBaseUnitAmountInUsd(DECIMAL_ETH_IN_BASE_UNITS, BIG_NUMBER_FAKE_ETH_USD_PRICE)).toBe( + '$1.10', + ); }); it('correctly formats 5.3014059295032 ETH to usd according to some price', () => { - expect(format.ethBaseAmountInUsd(IRRATIONAL_ETH_IN_BASE_UNITS, BIG_NUMBER_FAKE_ETH_USD_PRICE)).toBe( + expect(format.ethBaseUnitAmountInUsd(IRRATIONAL_ETH_IN_BASE_UNITS, BIG_NUMBER_FAKE_ETH_USD_PRICE)).toBe( '$13.43', ); }); it('returns defaultText param when ethBaseAmountInUsd or ethUsdPrice is not defined', () => { const defaultText = 'defaultText'; - expect(format.ethBaseAmountInUsd(undefined, undefined, 2, defaultText)).toBe(defaultText); - expect(format.ethBaseAmountInUsd(BIG_NUMBER_ONE, undefined, 2, defaultText)).toBe(defaultText); - expect(format.ethBaseAmountInUsd(undefined, BIG_NUMBER_ONE, 2, defaultText)).toBe(defaultText); + expect(format.ethBaseUnitAmountInUsd(undefined, undefined, 2, defaultText)).toBe(defaultText); + expect(format.ethBaseUnitAmountInUsd(BIG_NUMBER_ONE, undefined, 2, defaultText)).toBe(defaultText); + expect(format.ethBaseUnitAmountInUsd(undefined, BIG_NUMBER_ONE, 2, defaultText)).toBe(defaultText); }); it('it allows for configurable decimal places', () => { - expect(format.ethBaseAmountInUsd(DECIMAL_ETH_IN_BASE_UNITS, BIG_NUMBER_FAKE_ETH_USD_PRICE, 4)).toBe( + expect(format.ethBaseUnitAmountInUsd(DECIMAL_ETH_IN_BASE_UNITS, BIG_NUMBER_FAKE_ETH_USD_PRICE, 4)).toBe( '$1.0957', ); }); diff --git a/packages/utils/test/sign_typed_data_utils_test.ts b/packages/utils/test/sign_typed_data_utils_test.ts index dcba08b04..3d2cb2496 100644 --- a/packages/utils/test/sign_typed_data_utils_test.ts +++ b/packages/utils/test/sign_typed_data_utils_test.ts @@ -136,5 +136,28 @@ describe('signTypedDataUtils', () => { const hashHex = `0x${hash}`; expect(hashHex).to.be.eq(orderSignTypedDataHashHex); }); + it('creates a hash of an uninitialized order', () => { + const uninitializedOrder = { + ...orderSignTypedData, + message: { + makerAddress: '0x0000000000000000000000000000000000000000', + takerAddress: '0x0000000000000000000000000000000000000000', + makerAssetAmount: 0, + takerAssetAmount: 0, + expirationTimeSeconds: 0, + makerFee: 0, + takerFee: 0, + feeRecipientAddress: '0x0000000000000000000000000000000000000000', + senderAddress: '0x0000000000000000000000000000000000000000', + salt: 0, + makerAssetData: '0x0000000000000000000000000000000000000000', + takerAssetData: '0x0000000000000000000000000000000000000000', + exchangeAddress: '0x0000000000000000000000000000000000000000', + }, + }; + const hash = signTypedDataUtils.generateTypedDataHash(uninitializedOrder).toString('hex'); + const hashHex = `0x${hash}`; + expect(hashHex).to.be.eq('0xfaa49b35faeb9197e9c3ba7a52075e6dad19739549f153b77dfcf59408a4b422'); + }); }); }); |