diff options
author | fragosti <francesco.agosti93@gmail.com> | 2018-11-14 09:09:58 +0800 |
---|---|---|
committer | fragosti <francesco.agosti93@gmail.com> | 2018-11-14 09:09:58 +0800 |
commit | da9de70bbcecc16fa3a7f6991623f5027628f2b3 (patch) | |
tree | 5ec1cdef371604aa360eeae4ae7cde3190a8783d | |
parent | f03afe6f1b6a6bfa339507ee47b42c62550444a0 (diff) | |
parent | e02dc13805349a770506350c69e9061f596b48b2 (diff) | |
download | dexon-sol-tools-da9de70bbcecc16fa3a7f6991623f5027628f2b3.tar dexon-sol-tools-da9de70bbcecc16fa3a7f6991623f5027628f2b3.tar.gz dexon-sol-tools-da9de70bbcecc16fa3a7f6991623f5027628f2b3.tar.bz2 dexon-sol-tools-da9de70bbcecc16fa3a7f6991623f5027628f2b3.tar.lz dexon-sol-tools-da9de70bbcecc16fa3a7f6991623f5027628f2b3.tar.xz dexon-sol-tools-da9de70bbcecc16fa3a7f6991623f5027628f2b3.tar.zst dexon-sol-tools-da9de70bbcecc16fa3a7f6991623f5027628f2b3.zip |
Merge https://github.com/0xProject/0x-monorepo into feature/instant/metamask-connect-flow
48 files changed, 413 insertions, 184 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_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/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/react-docs/src/components/type.tsx b/packages/react-docs/src/components/type.tsx index 412b99b9d..fa3b658b4 100644 --- a/packages/react-docs/src/components/type.tsx +++ b/packages/react-docs/src/components/type.tsx @@ -1,9 +1,8 @@ -import { colors, constants as sharedConstants, Link, utils as sharedUtils } from '@0x/react-shared'; +import { colors, Link, utils as sharedUtils } from '@0x/react-shared'; import { Type as TypeDef, TypeDefinitionByName, TypeDocTypes } from '@0x/types'; import { errorUtils } from '@0x/utils'; import * as _ from 'lodash'; import * as React from 'react'; -import { Link as ScrollLink } from 'react-scroll'; import * as ReactTooltip from 'react-tooltip'; import { DocsInfo } from '../docs_info'; @@ -224,13 +223,7 @@ export const Type: React.SFC<TypeProps> = (props: TypeProps): any => { {sharedUtils.isUserOnMobile() || props.isInPopover || isExportedClassReference ? ( <span style={{ color: colors.lightBlueA700, cursor: 'pointer' }}>{typeName}</span> ) : ( - <ScrollLink - to={typeDefinitionAnchorId} - offset={0} - hashSpy={true} - duration={sharedConstants.DOCS_SCROLL_DURATION_MS} - containerId={sharedConstants.SCROLL_CONTAINER_ID} - > + <Link to={typeDefinitionAnchorId}> <span data-tip={true} data-for={id} @@ -252,7 +245,7 @@ export const Type: React.SFC<TypeProps> = (props: TypeProps): any => { /> </ReactTooltip> </span> - </ScrollLink> + </Link> )} </span> ); diff --git a/packages/react-docs/src/docs_info.ts b/packages/react-docs/src/docs_info.ts index 54b59ef1f..76f7784ba 100644 --- a/packages/react-docs/src/docs_info.ts +++ b/packages/react-docs/src/docs_info.ts @@ -10,6 +10,7 @@ import { SectionsMap, SupportedDocJson, } from './types'; +import { constants } from './utils/constants'; export class DocsInfo { public id: string; @@ -64,7 +65,7 @@ export class DocsInfo { const docSections = _.keys(this.sections); _.each(docSections, sectionName => { const docSection = docAgnosticFormat[sectionName]; - if (_.isUndefined(docSection)) { + if (_.isUndefined(docSection) || sectionName === constants.EXTERNAL_EXPORTS_SECTION_NAME) { return; // no-op } diff --git a/packages/react-shared/src/components/anchor_title.tsx b/packages/react-shared/src/components/anchor_title.tsx index bd99edcab..a9105e132 100644 --- a/packages/react-shared/src/components/anchor_title.tsx +++ b/packages/react-shared/src/components/anchor_title.tsx @@ -1,15 +1,9 @@ import * as React from 'react'; -import { Link as ScrollLink } from 'react-scroll'; import styled from 'styled-components'; +import { Link } from '../components/link'; import { HeaderSizes, Styles } from '../types'; import { colors } from '../utils/colors'; -import { constants } from '../utils/constants'; - -const headerSizeToScrollOffset: { [headerSize: string]: number } = { - h2: -20, - h3: 0, -}; export interface AnchorTitleProps { title: string | React.ReactNode; @@ -73,15 +67,9 @@ export class AnchorTitle extends React.Component<AnchorTitleProps, AnchorTitleSt {this.props.title} </div> {!this.props.isDisabled && ( - <ScrollLink - to={this.props.id} - hashSpy={true} - offset={headerSizeToScrollOffset[this.props.headerSize]} - duration={constants.DOCS_SCROLL_DURATION_MS} - containerId={constants.SCROLL_CONTAINER_ID} - > + <Link to={this.props.id}> <AnchorIcon className="zmdi zmdi-link" shouldShowAnchor={this.props.shouldShowAnchor} /> - </ScrollLink> + </Link> )} </div> ); 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'); + }); }); }); diff --git a/packages/website/public/images/developers/logo/0x.svg b/packages/website/public/images/developers/logo/0x.svg new file mode 100644 index 000000000..f02903925 --- /dev/null +++ b/packages/website/public/images/developers/logo/0x.svg @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Generator: Adobe Illustrator 23.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> +<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" + viewBox="0 0 263.9 130.3" style="enable-background:new 0 0 263.9 130.3;" xml:space="preserve"> +<title>Asset 1</title> +<g> + <g id="Layer_1-2"> + <path d="M208.4,72.9c0,3.6-0.4,7.2-1.4,10.7c-0.8,2.8-2.2,5.5-4,7.8c-1.7,2.1-3.9,3.7-6.4,4.7c-5.5,2.1-11.6,2.1-17.1,0 + c-2.5-1.1-4.7-2.7-6.5-4.7c-1.9-2.3-3.3-5-4.1-7.8c-1-3.5-1.5-7.1-1.4-10.7v-15c0-3.6,0.4-7.2,1.4-10.7c0.8-2.8,2.2-5.5,4.1-7.8 + c1.7-2.1,3.9-3.7,6.4-4.7c2.7-1.1,5.6-1.7,8.5-1.6c2.9-0.1,5.9,0.5,8.6,1.6c2.5,1.1,4.7,2.7,6.5,4.7c1.9,2.3,3.3,5,4.1,7.8 + c1,3.5,1.5,7.1,1.4,10.7v15H208.4z M177.8,69l20.1-15c-0.2-4.3-1.2-7.5-2.8-9.5c-1.8-2.1-4.4-3.3-7.2-3.1c-3.4,0-5.9,1.2-7.6,3.6 + s-2.5,6.1-2.5,11V69z M198,62.1l-20.1,15c0.5,8.2,3.9,12.4,10.1,12.4c6.7,0,10.1-4.9,10.1-14.7V62.1L198,62.1z"/> + <path d="M240.7,63.9l11.2-15.8h11.5l-16.5,23l17,23.7h-11.5l-11.6-16.4l-11.5,16.4h-11.5l17-23.7l-16.5-23h11.5L240.7,63.9z"/> + <path d="M32.4,121.4c21,12.3,47.2,11.7,67.7-1.4c5.6-3.6,10.6-8,14.9-13.1c-3.5-4.9-7.3-10-11.3-15.2l-3.3-4.2 + C96.2,94.3,90,99.7,82.7,103L71.6,92.1L32.4,121.4z"/> + <path d="M8.6,32.7C3.7,41.4,0.8,51,0.1,60.9c-0.9,13.8,2.6,27.5,10.1,39.2c3.6,5.6,8,10.6,13.1,14.9c4.9-3.5,10-7.3,15.2-11.3 + l4.2-3.3C36,96.1,30.6,89.9,27.2,82.7l11-11.2L8.6,32.7z"/> + <path d="M97.8,8.8c-21-12.3-47.2-11.7-67.7,1.4c-5.6,3.6-10.6,8-14.9,13.1c3.5,4.9,7.3,10,11.3,15.2l3.3,4.2 + c4.3-6.7,10.5-12.1,17.7-15.5l0,0L58,37.4L97.8,8.8z"/> + <path d="M121.7,97.2c12-20.9,11.3-46.8-1.7-67.1c-3.6-5.6-8-10.6-13.1-14.9c-4.9,3.5-10,7.3-15.2,11.3l-4.2,3.3 + c6.8,4.3,12.2,10.4,15.6,17.7l0.1,0.2l-10.6,11L121.7,97.2z"/> + </g> +</g> +</svg> diff --git a/packages/website/public/images/developers/logo/docs.svg b/packages/website/public/images/developers/logo/docs.svg new file mode 100644 index 000000000..d3d14f66e --- /dev/null +++ b/packages/website/public/images/developers/logo/docs.svg @@ -0,0 +1,6 @@ +<svg width="46" height="18" viewBox="0 0 46 18" fill="none" xmlns="http://www.w3.org/2000/svg"> +<path d="M0.0195312 11.0918C0.0195312 9.30859 0.442057 7.8763 1.28711 6.79492C2.13216 5.70638 3.23861 5.16211 4.60645 5.16211C5.96712 5.16211 7.04492 5.6276 7.83984 6.55859V0.5H9.82715V17H8.00098L7.9043 15.7539C7.10938 16.7279 6.00293 17.2148 4.58496 17.2148C3.23861 17.2148 2.13932 16.6634 1.28711 15.5605C0.442057 14.4577 0.0195312 13.0182 0.0195312 11.2422V11.0918ZM2.00684 11.3174C2.00684 12.6351 2.27897 13.6663 2.82324 14.4111C3.36751 15.1559 4.11947 15.5283 5.0791 15.5283C6.33952 15.5283 7.25977 14.9626 7.83984 13.8311V8.49219C7.24544 7.39648 6.33236 6.84863 5.10059 6.84863C4.12663 6.84863 3.36751 7.22461 2.82324 7.97656C2.27897 8.72852 2.00684 9.84212 2.00684 11.3174Z" fill="#888888"/> +<path d="M12.3945 11.0811C12.3945 9.94238 12.6165 8.91829 13.0605 8.00879C13.5117 7.09928 14.1348 6.39746 14.9297 5.90332C15.7318 5.40918 16.6449 5.16211 17.6689 5.16211C19.2516 5.16211 20.5299 5.70996 21.5039 6.80566C22.485 7.90137 22.9756 9.35872 22.9756 11.1777V11.3174C22.9756 12.4489 22.7572 13.4658 22.3203 14.3682C21.8906 15.2633 21.2712 15.9616 20.4619 16.4629C19.6598 16.9642 18.736 17.2148 17.6904 17.2148C16.1149 17.2148 14.8366 16.667 13.8555 15.5713C12.8815 14.4756 12.3945 13.0254 12.3945 11.2207V11.0811ZM14.3926 11.3174C14.3926 12.6064 14.6898 13.6413 15.2842 14.4219C15.8857 15.2025 16.6878 15.5928 17.6904 15.5928C18.7002 15.5928 19.5023 15.1989 20.0967 14.4111C20.6911 13.6162 20.9883 12.5062 20.9883 11.0811C20.9883 9.80632 20.6839 8.77507 20.0752 7.9873C19.4736 7.19238 18.6715 6.79492 17.6689 6.79492C16.6878 6.79492 15.8965 7.18522 15.2949 7.96582C14.6934 8.74642 14.3926 9.86361 14.3926 11.3174Z" fill="#888888"/> +<path d="M30.1299 15.5928C30.8389 15.5928 31.4583 15.3779 31.9883 14.9482C32.5182 14.5186 32.8118 13.9814 32.8691 13.3369H34.749C34.7132 14.0029 34.484 14.6367 34.0615 15.2383C33.639 15.8398 33.0732 16.3197 32.3643 16.6777C31.6624 17.0358 30.9176 17.2148 30.1299 17.2148C28.5472 17.2148 27.2868 16.6885 26.3486 15.6357C25.4176 14.5758 24.9521 13.1292 24.9521 11.2959V10.9629C24.9521 9.83138 25.1598 8.8252 25.5752 7.94434C25.9906 7.06348 26.585 6.37956 27.3584 5.89258C28.139 5.4056 29.0592 5.16211 30.1191 5.16211C31.4225 5.16211 32.5039 5.55241 33.3633 6.33301C34.2298 7.11361 34.6917 8.12695 34.749 9.37305H32.8691C32.8118 8.62109 32.5254 8.00521 32.0098 7.52539C31.5013 7.03841 30.8711 6.79492 30.1191 6.79492C29.1094 6.79492 28.3252 7.16016 27.7666 7.89062C27.2152 8.61393 26.9395 9.66309 26.9395 11.0381V11.4141C26.9395 12.7533 27.2152 13.7845 27.7666 14.5078C28.318 15.2311 29.1058 15.5928 30.1299 15.5928Z" fill="#888888"/> +<path d="M43.751 13.917C43.751 13.3799 43.5469 12.9645 43.1387 12.6709C42.7376 12.3701 42.0322 12.1123 41.0225 11.8975C40.0199 11.6826 39.2214 11.4248 38.627 11.124C38.0397 10.8232 37.6029 10.4652 37.3164 10.0498C37.0371 9.63444 36.8975 9.1403 36.8975 8.56738C36.8975 7.61491 37.2985 6.80924 38.1006 6.15039C38.9098 5.49154 39.9411 5.16211 41.1943 5.16211C42.512 5.16211 43.5791 5.50228 44.3955 6.18262C45.2191 6.86296 45.6309 7.73307 45.6309 8.79297H43.6328C43.6328 8.2487 43.4001 7.77962 42.9346 7.38574C42.4762 6.99186 41.8962 6.79492 41.1943 6.79492C40.471 6.79492 39.9053 6.95247 39.4971 7.26758C39.0889 7.58268 38.8848 7.99447 38.8848 8.50293C38.8848 8.98275 39.0745 9.3444 39.4541 9.58789C39.8337 9.83138 40.5176 10.0641 41.5059 10.2861C42.5013 10.5081 43.307 10.7731 43.9229 11.0811C44.5387 11.389 44.9935 11.7614 45.2871 12.1982C45.5879 12.6279 45.7383 13.1543 45.7383 13.7773C45.7383 14.8158 45.3229 15.6501 44.4922 16.2803C43.6615 16.9033 42.5837 17.2148 41.2588 17.2148C40.3278 17.2148 39.5042 17.0501 38.7881 16.7207C38.0719 16.3913 37.5098 15.9329 37.1016 15.3457C36.7005 14.7513 36.5 14.1104 36.5 13.4229H38.4873C38.5231 14.0889 38.7881 14.6188 39.2822 15.0127C39.7835 15.3994 40.4424 15.5928 41.2588 15.5928C42.0107 15.5928 42.6123 15.4424 43.0635 15.1416C43.5218 14.8337 43.751 14.4255 43.751 13.917Z" fill="#888888"/> +</svg> diff --git a/packages/website/public/images/docs_logo.svg b/packages/website/public/images/docs_logo.svg deleted file mode 100644 index e3c4b628b..000000000 --- a/packages/website/public/images/docs_logo.svg +++ /dev/null @@ -1,24 +0,0 @@ -<svg width="278" height="72" viewBox="0 0 278 72" fill="none" xmlns="http://www.w3.org/2000/svg"> -<rect width="139" height="35.9999" fill="black" fill-opacity="0" transform="scale(2)"/> -<rect width="74.0872" height="35.9999" fill="black" fill-opacity="0" transform="scale(2)"/> -<path fill-rule="evenodd" clip-rule="evenodd" d="M115.234 33.6875L105.219 40.5522C105.477 44.3244 107.146 46.2101 110.226 46.2101C113.565 46.2101 115.234 43.9618 115.234 39.4642V33.6875ZM105.176 36.8338L115.191 29.9691C115.076 28.0041 114.607 26.5499 113.783 25.6069C112.959 24.6642 111.759 24.1924 110.183 24.1924C108.507 24.1924 107.253 24.7398 106.422 25.8345C105.591 26.9293 105.176 28.6109 105.176 30.8789V36.8338ZM120.394 38.6336C120.394 40.4934 120.16 42.1322 119.695 43.5498C119.229 44.9677 118.559 46.1546 117.686 47.1106C116.812 48.067 115.744 48.7892 114.483 49.277C113.222 49.7647 111.804 50.0089 110.228 50.0089C108.666 50.0089 107.255 49.7647 105.994 49.277C104.733 48.7892 103.662 48.067 102.781 47.1106C101.9 46.1546 101.22 44.9677 100.74 43.5498C100.259 42.1322 100.02 40.4934 100.02 38.6336V31.7491C100.02 29.8895 100.256 28.2511 100.729 26.8332C101.202 25.4156 101.879 24.2285 102.76 23.2721C103.641 22.3161 104.708 21.5941 105.962 21.1059C107.215 20.6182 108.623 20.374 110.185 20.374C111.761 20.374 113.179 20.6182 114.44 21.1059C115.701 21.5941 116.772 22.3161 117.653 23.2721C118.535 24.2285 119.212 25.4156 119.684 26.8332C120.157 28.2511 120.394 29.8895 120.394 31.7491V38.6336Z" fill="black"/> -<path fill-rule="evenodd" clip-rule="evenodd" d="M137.01 35.3006L142.385 27.7822H147.925L139.968 38.7311L148.175 50.0084H142.655L137.073 42.2232L131.511 50.0084H125.949L134.156 38.7311L126.199 27.7822H131.719L137.01 35.3006Z" fill="black"/> -<rect width="36" height="35.9999" fill="black" fill-opacity="0" transform="scale(2)"/> -<rect width="22.5701" height="11.8348" fill="black" fill-opacity="0" transform="translate(18.0508 48.3301) scale(2)"/> -<mask id="mask0" mask-type="alpha" maskUnits="userSpaceOnUse" x="18" y="48" width="46" height="24"> -<path fill-rule="evenodd" clip-rule="evenodd" d="M18.0508 71.9997H63.191V48.3301H18.0508V71.9997Z" fill="white"/> -</mask> -<g mask="url(#mask0)"> -<path fill-rule="evenodd" clip-rule="evenodd" d="M18.0508 67.1184C22.6601 69.8386 27.9385 71.5522 33.6161 71.9239C41.4577 72.4369 48.8759 70.3221 55.038 66.3361C58.1021 64.354 60.8534 61.9089 63.191 59.0905C61.2524 56.3622 59.1896 53.547 57.0111 50.6788L55.2311 48.3301C52.8884 52.0707 49.5201 55.0686 45.5555 56.9441L39.4742 50.9207L18.0508 67.1184Z" fill="black"/> -</g> -<rect width="11.6916" height="22.7346" fill="black" fill-opacity="0" transform="translate(0 18.6299) scale(2)"/> -<mask id="mask1" mask-type="alpha" maskUnits="userSpaceOnUse" x="0" y="18" width="24" height="47"> -<path fill-rule="evenodd" clip-rule="evenodd" d="M0 18.6299V64.099H23.3833V18.6299L0 18.6299Z" fill="white"/> -</mask> -<g mask="url(#mask1)"> -<path fill-rule="evenodd" clip-rule="evenodd" d="M4.72039 18.6299C2.09283 23.2496 0.437543 28.5247 0.0749777 34.193C-0.432648 42.134 1.66198 49.6455 5.60982 55.8826C7.56303 58.9691 9.97065 61.7416 12.7445 64.099C15.4422 62.1375 18.2268 60.0505 21.0641 57.847L23.3833 56.0501C19.6922 53.6805 16.7332 50.2769 14.8817 46.271L20.8743 40.0586L4.72039 18.6299Z" fill="black"/> -</g> -<path fill-rule="evenodd" clip-rule="evenodd" d="M54.0006 4.9803C49.4018 2.20541 44.1346 0.455949 38.4679 0.0772542C30.6434 -0.445638 23.2417 1.71125 17.096 5.77624C14.0546 7.78768 11.3231 10.2669 9 13.123C10.9328 15.9011 12.9892 18.7682 15.1602 21.69L16.9306 24.0783C19.2665 20.2759 22.622 17.2279 26.5714 15.3216L26.5759 15.3196L32.2882 21.07L54.0006 4.9803Z" fill="black"/> -<path fill-rule="evenodd" clip-rule="evenodd" d="M67.3574 53.7131C69.9376 49.2175 71.5681 44.0992 71.9269 38.5992C72.4342 30.8203 70.3437 23.4613 66.4027 17.3486C64.4432 14.3092 62.0259 11.58 59.2397 9.26074C56.5427 11.1839 53.7595 13.2301 50.9238 15.3915L48.6016 17.1569C52.3061 19.4848 55.2749 22.8335 57.1283 26.7755L57.1639 26.8575L51.3951 32.7948L67.3574 53.7131Z" fill="black"/> -<path d="M164.041 38.1836C164.041 34.6172 164.886 31.7526 166.576 29.5898C168.266 27.4128 170.479 26.3242 173.215 26.3242C175.936 26.3242 178.092 27.2552 179.682 29.1172V17H183.656V50H180.004L179.811 47.5078C178.221 49.4557 176.008 50.4297 173.172 50.4297C170.479 50.4297 168.281 49.3268 166.576 47.1211C164.886 44.9154 164.041 42.0365 164.041 38.4844V38.1836ZM168.016 38.6348C168.016 41.2702 168.56 43.3327 169.648 44.8223C170.737 46.3118 172.241 47.0566 174.16 47.0566C176.681 47.0566 178.521 45.9251 179.682 43.6621V32.9844C178.493 30.793 176.667 29.6973 174.203 29.6973C172.255 29.6973 170.737 30.4492 169.648 31.9531C168.56 33.457 168.016 35.6842 168.016 38.6348ZM188.791 38.1621C188.791 35.8848 189.235 33.8366 190.123 32.0176C191.025 30.1986 192.271 28.7949 193.861 27.8066C195.465 26.8184 197.292 26.3242 199.34 26.3242C202.505 26.3242 205.062 27.4199 207.01 29.6113C208.972 31.8027 209.953 34.7174 209.953 38.3555V38.6348C209.953 40.8978 209.516 42.9316 208.643 44.7363C207.783 46.5267 206.544 47.9232 204.926 48.9258C203.322 49.9284 201.474 50.4297 199.383 50.4297C196.232 50.4297 193.675 49.334 191.713 47.1426C189.765 44.9512 188.791 42.0508 188.791 38.4414V38.1621ZM192.787 38.6348C192.787 41.2129 193.382 43.2826 194.57 44.8438C195.773 46.4049 197.378 47.1855 199.383 47.1855C201.402 47.1855 203.007 46.3978 204.195 44.8223C205.384 43.2324 205.979 41.0124 205.979 38.1621C205.979 35.6126 205.37 33.5501 204.152 31.9746C202.949 30.3848 201.345 29.5898 199.34 29.5898C197.378 29.5898 195.795 30.3704 194.592 31.9316C193.389 33.4928 192.787 35.7272 192.787 38.6348ZM224.262 47.1855C225.68 47.1855 226.919 46.7559 227.979 45.8965C229.038 45.0371 229.626 43.9629 229.74 42.6738H233.5C233.428 44.0059 232.97 45.2734 232.125 46.4766C231.28 47.6797 230.148 48.6393 228.73 49.3555C227.327 50.0716 225.837 50.4297 224.262 50.4297C221.096 50.4297 218.576 49.377 216.699 47.2715C214.837 45.1517 213.906 42.2585 213.906 38.5918V37.9258C213.906 35.6628 214.322 33.6504 215.152 31.8887C215.983 30.127 217.172 28.7591 218.719 27.7852C220.28 26.8112 222.12 26.3242 224.24 26.3242C226.847 26.3242 229.01 27.1048 230.729 28.666C232.462 30.2272 233.385 32.2539 233.5 34.7461H229.74C229.626 33.2422 229.053 32.0104 228.021 31.0508C227.005 30.0768 225.744 29.5898 224.24 29.5898C222.221 29.5898 220.652 30.3203 219.535 31.7812C218.432 33.2279 217.881 35.3262 217.881 38.0762V38.8281C217.881 41.5065 218.432 43.569 219.535 45.0156C220.638 46.4622 222.214 47.1855 224.262 47.1855ZM251.504 43.834C251.504 42.7598 251.096 41.929 250.279 41.3418C249.477 40.7402 248.066 40.2246 246.047 39.7949C244.042 39.3652 242.445 38.8496 241.256 38.248C240.081 37.6465 239.208 36.9303 238.635 36.0996C238.076 35.2689 237.797 34.2806 237.797 33.1348C237.797 31.2298 238.599 29.6185 240.203 28.3008C241.822 26.9831 243.884 26.3242 246.391 26.3242C249.026 26.3242 251.16 27.0046 252.793 28.3652C254.44 29.7259 255.264 31.4661 255.264 33.5859H251.268C251.268 32.4974 250.802 31.5592 249.871 30.7715C248.954 29.9837 247.794 29.5898 246.391 29.5898C244.944 29.5898 243.812 29.9049 242.996 30.5352C242.18 31.1654 241.771 31.9889 241.771 33.0059C241.771 33.9655 242.151 34.6888 242.91 35.1758C243.669 35.6628 245.037 36.1283 247.014 36.5723C249.005 37.0163 250.616 37.5462 251.848 38.1621C253.079 38.778 253.989 39.5228 254.576 40.3965C255.178 41.2559 255.479 42.3086 255.479 43.5547C255.479 45.6315 254.648 47.3001 252.986 48.5605C251.325 49.8066 249.169 50.4297 246.52 50.4297C244.658 50.4297 243.01 50.1003 241.578 49.4414C240.146 48.7826 239.021 47.8659 238.205 46.6914C237.403 45.5026 237.002 44.2207 237.002 42.8457H240.977C241.048 44.1777 241.578 45.2376 242.566 46.0254C243.569 46.7988 244.887 47.1855 246.52 47.1855C248.023 47.1855 249.227 46.8848 250.129 46.2832C251.046 45.6673 251.504 44.8509 251.504 43.834Z" fill="#666666"/> -</svg> diff --git a/packages/website/translations/chinese.json b/packages/website/translations/chinese.json index 95b9bda62..e3798a072 100644 --- a/packages/website/translations/chinese.json +++ b/packages/website/translations/chinese.json @@ -83,7 +83,7 @@ "BUILD_A_RELAYER_DESCRIPTION": "Learn how to build your own 0x relayer from scratch", "DEVELOP_ON_ETHEREUM": "develop on Ethereum", "DEVELOP_ON_ETHEREUM_DESCRIPTION": "Learn more about building applications ontop of Ethereum", - "ORDER_BASICS": "0x order basics", + "ORDER_BASICS": "Make & take orders", "ORDER_BASICS_DESCRIPTION": "Tutorial on how to create, validate and fill an order using 0x", "USE_NETWORKED_LIQUIDITY": "use networked liquidity", "USE_NETWORKED_LIQUIDITY_DESCRIPTION": "Access the shared liquidity pool using the Standard Relayer API", diff --git a/packages/website/translations/english.json b/packages/website/translations/english.json index 465bd49b4..f91633492 100644 --- a/packages/website/translations/english.json +++ b/packages/website/translations/english.json @@ -87,7 +87,7 @@ "BUILD_A_RELAYER_DESCRIPTION": "Learn how to build your own 0x relayer from scratch", "DEVELOP_ON_ETHEREUM": "develop on Ethereum", "DEVELOP_ON_ETHEREUM_DESCRIPTION": "Learn more about building applications ontop of Ethereum", - "ORDER_BASICS": "0x order basics", + "ORDER_BASICS": "Make & take orders", "ORDER_BASICS_DESCRIPTION": "Tutorial on how to create, validate and fill an order using 0x", "USE_NETWORKED_LIQUIDITY": "use networked liquidity", "USE_NETWORKED_LIQUIDITY_DESCRIPTION": "Learn how to tap into networked liquidity using the Standard Relayer API", diff --git a/packages/website/translations/korean.json b/packages/website/translations/korean.json index 5485e5583..ca8cbe3d0 100644 --- a/packages/website/translations/korean.json +++ b/packages/website/translations/korean.json @@ -83,7 +83,7 @@ "BUILD_A_RELAYER_DESCRIPTION": "Learn how to build your own 0x relayer from scratch", "DEVELOP_ON_ETHEREUM": "develop on Ethereum", "DEVELOP_ON_ETHEREUM_DESCRIPTION": "Learn more about building applications ontop of Ethereum", - "ORDER_BASICS": "0x order basics", + "ORDER_BASICS": "Make & take orders", "ORDER_BASICS_DESCRIPTION": "Tutorial on how to create, validate and fill an order using 0x", "USE_NETWORKED_LIQUIDITY": "use networked liquidity", "USE_NETWORKED_LIQUIDITY_DESCRIPTION": "Learn how to tap into networked liquidity using the Standard Relayer API", diff --git a/packages/website/translations/russian.json b/packages/website/translations/russian.json index a2e2a8cef..a43d1e7b7 100644 --- a/packages/website/translations/russian.json +++ b/packages/website/translations/russian.json @@ -83,7 +83,7 @@ "BUILD_A_RELAYER_DESCRIPTION": "Learn how to build your own 0x relayer from scratch", "DEVELOP_ON_ETHEREUM": "develop on Ethereum", "DEVELOP_ON_ETHEREUM_DESCRIPTION": "Learn more about building applications ontop of Ethereum", - "ORDER_BASICS": "0x order basics", + "ORDER_BASICS": "Make & take orders", "ORDER_BASICS_DESCRIPTION": "Tutorial on how to create, validate and fill an order using 0x", "USE_NETWORKED_LIQUIDITY": "use networked liquidity", "USE_NETWORKED_LIQUIDITY_DESCRIPTION": "Learn how to tap into networked liquidity using the Standard Relayer API", diff --git a/packages/website/translations/spanish.json b/packages/website/translations/spanish.json index acbc59c3d..4d404ac6b 100644 --- a/packages/website/translations/spanish.json +++ b/packages/website/translations/spanish.json @@ -84,7 +84,7 @@ "BUILD_A_RELAYER_DESCRIPTION": "Learn how to build your own 0x relayer from scratch", "DEVELOP_ON_ETHEREUM": "develop on Ethereum", "DEVELOP_ON_ETHEREUM_DESCRIPTION": "Learn more about building applications ontop of Ethereum", - "ORDER_BASICS": "0x order basics", + "ORDER_BASICS": "Make & take orders", "ORDER_BASICS_DESCRIPTION": "Tutorial on how to create, validate and fill an order using 0x", "USE_NETWORKED_LIQUIDITY": "use networked liquidity", "USE_NETWORKED_LIQUIDITY_DESCRIPTION": "Learn how to tap into networked liquidity using the Standard Relayer API", diff --git a/packages/website/ts/components/documentation/docs_logo.tsx b/packages/website/ts/components/documentation/docs_logo.tsx index 2840d5960..ac331db79 100644 --- a/packages/website/ts/components/documentation/docs_logo.tsx +++ b/packages/website/ts/components/documentation/docs_logo.tsx @@ -1,17 +1,34 @@ import { Link } from '@0x/react-shared'; import * as React from 'react'; +import { styled } from 'ts/style/theme'; import { WebsitePaths } from 'ts/types'; +import { Container } from '../ui/container'; + export interface DocsLogoProps { - height: number; containerStyle?: React.CSSProperties; } +const Image = styled.img` + &:hover { + opacity: 0.7; + } +`; + export const DocsLogo: React.StatelessComponent<DocsLogoProps> = props => { return ( - <Link to={WebsitePaths.Docs}> - <img src="/images/docs_logo.svg" height={props.height} /> - </Link> + <Container className="flex"> + <Container> + <Link to={WebsitePaths.Home}> + <Image src="/images/developers/logo/0x.svg" height={34} /> + </Link> + </Container> + <Container paddingTop="6px" paddingLeft="7px"> + <Link to={WebsitePaths.Docs}> + <Image src="/images/developers/logo/docs.svg" height={20} /> + </Link> + </Container> + </Container> ); }; diff --git a/packages/website/ts/components/documentation/docs_top_bar.tsx b/packages/website/ts/components/documentation/docs_top_bar.tsx index 2054d0860..c4291b78f 100644 --- a/packages/website/ts/components/documentation/docs_top_bar.tsx +++ b/packages/website/ts/components/documentation/docs_top_bar.tsx @@ -38,17 +38,17 @@ export class DocsTopBar extends React.Component<DocsTopBarProps, DocsTopBarState return ( <Container height={80}> <Container - className="flex items-center lg-pt3 md-pt3 sm-pt1 lg-mt1 md-mt1 sm-mt0 lg-justify-end md-justify-end sm-justify-start" + className="flex items-center lg-pt3 md-pt3 sm-pt1 lg-justify-end md-justify-end sm-justify-start" width="100%" > <Container className="sm-hide xs-hide"> - <Container className="flex items-center justify-between right" width="300px"> + <Container className="flex items-center justify-between right" width="250px"> {this._renderMenuItems(constants.DEVELOPER_TOPBAR_LINKS)} </Container> </Container> <Container className="lg-hide md-hide"> <Container paddingTop="6px"> - <DocsLogo height={30} /> + <DocsLogo /> </Container> </Container> <Container className="md-hide lg-hide absolute" right="18px" top="12px"> @@ -63,7 +63,7 @@ export class DocsTopBar extends React.Component<DocsTopBarProps, DocsTopBarState /> </Container> </Container> - <Container width={'100%'} height={'1px'} backgroundColor={colors.grey300} marginTop={'13px'} /> + <Container width={'100%'} height={'1px'} backgroundColor={colors.grey300} marginTop={'16px'} /> {this.props.screenWidth === ScreenWidths.Sm && this._renderDrawer()} </Container> ); diff --git a/packages/website/ts/components/documentation/sidebar_header.tsx b/packages/website/ts/components/documentation/sidebar_header.tsx index fece2704b..9ced52c74 100644 --- a/packages/website/ts/components/documentation/sidebar_header.tsx +++ b/packages/website/ts/components/documentation/sidebar_header.tsx @@ -29,6 +29,7 @@ export const SidebarHeader: React.StatelessComponent<SidebarHeaderProps> = ({ fontColor={colors.lightLinkBlue} fontSize={screenWidth === ScreenWidths.Sm ? '20px' : '22px'} fontWeight="bold" + lineHeight="26px" > {title} </Text> @@ -36,7 +37,7 @@ export const SidebarHeader: React.StatelessComponent<SidebarHeaderProps> = ({ {!_.isUndefined(docsVersion) && !_.isUndefined(availableDocVersions) && !_.isUndefined(onVersionSelected) && ( - <div className="right" style={{ alignSelf: 'flex-end' }}> + <div className="right" style={{ alignSelf: 'flex-end', paddingBottom: 4 }}> <VersionDropDown selectedVersion={docsVersion} versions={availableDocVersions} diff --git a/packages/website/ts/components/documentation/version_drop_down.tsx b/packages/website/ts/components/documentation/version_drop_down.tsx index a1c8b0547..5e77530fd 100644 --- a/packages/website/ts/components/documentation/version_drop_down.tsx +++ b/packages/website/ts/components/documentation/version_drop_down.tsx @@ -27,7 +27,7 @@ const PlainActiveNode: React.StatelessComponent<ActiveNodeProps> = ({ className, const ActiveNode = styled(PlainActiveNode)` cursor: pointer; - border: 2px solid ${colors.beigeWhite}; + border: 1px solid ${colors.beigeWhite}; border-radius: 4px; padding: 4px 6px 4px 8px; `; diff --git a/packages/website/ts/components/dropdowns/developers_drop_down.tsx b/packages/website/ts/components/dropdowns/developers_drop_down.tsx index 6e85c1499..b8a35fab0 100644 --- a/packages/website/ts/components/dropdowns/developers_drop_down.tsx +++ b/packages/website/ts/components/dropdowns/developers_drop_down.tsx @@ -89,7 +89,7 @@ export class DevelopersDropDown extends React.Component<DevelopersDropDownProps, ); } private _renderDropdownMenu(): React.ReactNode { - const sectionPadding = '28px'; + const sectionPadding = '26px'; const dropdownMenu = ( <Container> <Container className="flex" padding={sectionPadding}> diff --git a/packages/website/ts/components/nested_sidebar_menu.tsx b/packages/website/ts/components/nested_sidebar_menu.tsx index db7d55261..4d4bc4617 100644 --- a/packages/website/ts/components/nested_sidebar_menu.tsx +++ b/packages/website/ts/components/nested_sidebar_menu.tsx @@ -4,11 +4,13 @@ import * as _ from 'lodash'; import * as React from 'react'; import { Button } from 'ts/components/ui/button'; import { Text } from 'ts/components/ui/text'; +import { ScreenWidths } from 'ts/types'; export interface NestedSidebarMenuProps { sectionNameToLinks: ObjectMap<ALink[]>; sidebarHeader?: React.ReactNode; shouldReformatMenuItemNames?: boolean; + screenWidth: ScreenWidths; } export const NestedSidebarMenu = (props: NestedSidebarMenuProps) => { @@ -22,7 +24,7 @@ export const NestedSidebarMenu = (props: NestedSidebarMenuProps) => { ...link, title: menuItemTitle, }; - return <MenuItem key={`menu-item-${menuItemTitle}`} link={finalLink} />; + return <MenuItem key={`menu-item-${menuItemTitle}`} link={finalLink} screenWidth={props.screenWidth} />; }); // tslint:disable-next-line:no-unused-variable return ( @@ -44,6 +46,7 @@ export const NestedSidebarMenu = (props: NestedSidebarMenuProps) => { export interface MenuItemProps { link: ALink; + screenWidth: ScreenWidths; } export interface MenuItemState { @@ -70,7 +73,13 @@ export class MenuItem extends React.Component<MenuItemProps, MenuItemState> { borderRadius="4px" padding="0.4em 0.375em" width="100%" - backgroundColor={isActive ? colors.lightLinkBlue : colors.grey100} + backgroundColor={ + isActive + ? colors.lightLinkBlue + : this.props.screenWidth === ScreenWidths.Sm + ? 'white' + : colors.grey100 + } fontSize="14px" textAlign="left" > diff --git a/packages/website/ts/pages/documentation/developers_page.tsx b/packages/website/ts/pages/documentation/developers_page.tsx index 89389e488..a84be7bfe 100644 --- a/packages/website/ts/pages/documentation/developers_page.tsx +++ b/packages/website/ts/pages/documentation/developers_page.tsx @@ -157,9 +157,10 @@ export class DevelopersPage extends React.Component<DevelopersPageProps, Develop > <Container borderBottom={this.state.isSidebarScrolling ? `1px solid ${colors.grey300}` : 'none'} + paddingBottom="2px" > <Container paddingTop="30px" paddingLeft="10px" paddingBottom="8px"> - <DocsLogo height={36} /> + <DocsLogo /> </Container> </Container> <SidebarContainer onWheel={this._throttledSidebarScrolling}> diff --git a/packages/website/ts/pages/documentation/doc_page.tsx b/packages/website/ts/pages/documentation/doc_page.tsx index 8392c90e4..adf2261b5 100644 --- a/packages/website/ts/pages/documentation/doc_page.tsx +++ b/packages/website/ts/pages/documentation/doc_page.tsx @@ -94,7 +94,11 @@ export class DocPage extends React.Component<DocPageProps, DocPageState> { const sidebar = _.isUndefined(this.state.docAgnosticFormat) ? ( <div /> ) : ( - <NestedSidebarMenu sidebarHeader={this._renderSidebarHeader()} sectionNameToLinks={sectionNameToLinks} /> + <NestedSidebarMenu + sidebarHeader={this._renderSidebarHeader()} + sectionNameToLinks={sectionNameToLinks} + screenWidth={this.props.screenWidth} + /> ); return ( <DevelopersPage diff --git a/packages/website/ts/pages/documentation/docs_home.tsx b/packages/website/ts/pages/documentation/docs_home.tsx index bbbee2d2d..017573304 100644 --- a/packages/website/ts/pages/documentation/docs_home.tsx +++ b/packages/website/ts/pages/documentation/docs_home.tsx @@ -346,6 +346,7 @@ export class DocsHome extends React.Component<DocsHomeProps, DocsHomeState> { sidebarHeader={isSmallScreen ? this._renderSidebarHeader() : undefined} sectionNameToLinks={sectionNameToLinks} shouldReformatMenuItemNames={false} + screenWidth={this.props.screenWidth} /> ); return ( diff --git a/packages/website/ts/pages/wiki/wiki.tsx b/packages/website/ts/pages/wiki/wiki.tsx index c1802b1f8..c3c1600a5 100644 --- a/packages/website/ts/pages/wiki/wiki.tsx +++ b/packages/website/ts/pages/wiki/wiki.tsx @@ -76,6 +76,7 @@ export class Wiki extends React.Component<WikiProps, WikiState> { <NestedSidebarMenu sidebarHeader={isSmallScreen ? this._renderSidebarHeader() : undefined} sectionNameToLinks={sectionNameToLinks} + screenWidth={this.props.screenWidth} /> ); return ( diff --git a/packages/website/ts/utils/constants.ts b/packages/website/ts/utils/constants.ts index 0a8a86c50..379f28022 100644 --- a/packages/website/ts/utils/constants.ts +++ b/packages/website/ts/utils/constants.ts @@ -104,10 +104,6 @@ export const constants = { URL_MISSION_AND_VALUES_BLOG_POST: 'https://blog.0xproject.com/the-0x-mission-and-values-181a58706f9f', DEVELOPER_TOPBAR_LINKS: [ { - title: Key.Home, - to: WebsitePaths.Home, - }, - { title: Key.Wiki, to: WebsitePaths.Wiki, }, diff --git a/python-packages/order_utils/setup.py b/python-packages/order_utils/setup.py index 1b07b612c..7f1da2f34 100755 --- a/python-packages/order_utils/setup.py +++ b/python-packages/order_utils/setup.py @@ -160,7 +160,13 @@ setup( "publish": PublishCommand, "ganache": GanacheCommand, }, - install_requires=["eth-abi", "eth_utils", "mypy_extensions", "web3"], + install_requires=[ + "eth-abi", + "eth_utils", + "ethereum", + "mypy_extensions", + "web3", + ], extras_require={ "dev": [ "bandit", diff --git a/python-packages/order_utils/src/zero_ex/dev_utils/abi_utils.py b/python-packages/order_utils/src/zero_ex/dev_utils/abi_utils.py index 71b6128ca..9afeacfdf 100644 --- a/python-packages/order_utils/src/zero_ex/dev_utils/abi_utils.py +++ b/python-packages/order_utils/src/zero_ex/dev_utils/abi_utils.py @@ -10,8 +10,8 @@ from typing import Any, List from mypy_extensions import TypedDict -from eth_abi import encode_abi from web3 import Web3 +from eth_abi import encode_abi from .type_assertions import assert_is_string, assert_is_list diff --git a/python-packages/order_utils/src/zero_ex/order_utils/__init__.py b/python-packages/order_utils/src/zero_ex/order_utils/__init__.py index 80445cb6e..fb5bc2f5d 100644 --- a/python-packages/order_utils/src/zero_ex/order_utils/__init__.py +++ b/python-packages/order_utils/src/zero_ex/order_utils/__init__.py @@ -9,3 +9,157 @@ just this purpose. To start it: ``docker run -d -p 8545:8545 0xorg/ganache-cli --networkId 50 -m "concert load couple harbor equip island argue ramp clarify fence smart topic"``. """ + +import json +from typing import Dict +from pkg_resources import resource_string + +from mypy_extensions import TypedDict + +from eth_utils import is_address, keccak, to_checksum_address, to_bytes +from web3 import Web3 +from web3.utils import datatypes +import web3.exceptions + + +class Constants: # pylint: disable=too-few-public-methods + """Static data used by order utilities.""" + + contract_name_to_abi = { + "Exchange": json.loads( + resource_string( + "zero_ex.contract_artifacts", "artifacts/Exchange.json" + ) + )["compilerOutput"]["abi"] + } + + network_to_exchange_addr: Dict[str, str] = { + "1": "0x4f833a24e1f95d70f028921e27040ca56e09ab0b", + "3": "0x4530c0483a1633c7a1c97d2c53721caff2caaaaf", + "42": "0x35dd2932454449b14cee11a94d3674a936d5d7b2", + "50": "0x48bacb9266a570d521063ef5dd96e61686dbe788", + } + + null_address = "0x0000000000000000000000000000000000000000" + + eip191_header = b"\x19\x01" + + eip712_domain_separator_schema_hash = keccak( + b"EIP712Domain(string name,string version,address verifyingContract)" + ) + + eip712_domain_struct_header = ( + eip712_domain_separator_schema_hash + + keccak(b"0x Protocol") + + keccak(b"2") + ) + + eip712_order_schema_hash = keccak( + b"Order(" + + b"address makerAddress," + + b"address takerAddress," + + b"address feeRecipientAddress," + + b"address senderAddress," + + b"uint256 makerAssetAmount," + + b"uint256 takerAssetAmount," + + b"uint256 makerFee," + + b"uint256 takerFee," + + b"uint256 expirationTimeSeconds," + + b"uint256 salt," + + b"bytes makerAssetData," + + b"bytes takerAssetData" + + b")" + ) + + +class Order(TypedDict): # pylint: disable=too-many-instance-attributes + """Object representation of a 0x order.""" + + maker_address: str + taker_address: str + fee_recipient_address: str + sender_address: str + maker_asset_amount: int + taker_asset_amount: int + maker_fee: int + taker_fee: int + expiration_time_seconds: int + salt: int + maker_asset_data: str + taker_asset_data: str + + +def make_empty_order() -> Order: + """Construct an empty order.""" + return { + "maker_address": Constants.null_address, + "taker_address": Constants.null_address, + "sender_address": Constants.null_address, + "fee_recipient_address": Constants.null_address, + "maker_asset_data": Constants.null_address, + "taker_asset_data": Constants.null_address, + "salt": 0, + "maker_fee": 0, + "taker_fee": 0, + "maker_asset_amount": 0, + "taker_asset_amount": 0, + "expiration_time_seconds": 0, + } + + +def generate_order_hash_hex(order: Order, exchange_address: str) -> str: + # docstring considered all one line by pylint: disable=line-too-long + """Calculate the hash of the given order as a hexadecimal string. + + >>> generate_order_hash_hex( + ... { + ... 'maker_address': "0x0000000000000000000000000000000000000000", + ... 'taker_address': "0x0000000000000000000000000000000000000000", + ... 'fee_recipient_address': "0x0000000000000000000000000000000000000000", + ... 'sender_address': "0x0000000000000000000000000000000000000000", + ... 'maker_asset_amount': 1000000000000000000, + ... 'taker_asset_amount': 1000000000000000000, + ... 'maker_fee': 0, + ... 'taker_fee': 0, + ... 'expiration_time_seconds': 12345, + ... 'salt': 12345, + ... 'maker_asset_data': "0000000000000000000000000000000000000000", + ... 'taker_asset_data': "0000000000000000000000000000000000000000", + ... }, + ... exchange_address="0x0000000000000000000000000000000000000000", + ... ) + '55eaa6ec02f3224d30873577e9ddd069a288c16d6fb407210eecbc501fa76692' + """ # noqa: E501 (line too long) + # TODO: use JSON schema validation to validate order. pylint: disable=fixme + def pad_20_bytes_to_32(twenty_bytes: bytes): + return bytes(12) + twenty_bytes + + def int_to_32_big_endian_bytes(i: int): + return i.to_bytes(32, byteorder="big") + + eip712_domain_struct_hash = keccak( + Constants.eip712_domain_struct_header + + pad_20_bytes_to_32(to_bytes(hexstr=exchange_address)) + ) + + eip712_order_struct_hash = keccak( + Constants.eip712_order_schema_hash + + pad_20_bytes_to_32(to_bytes(hexstr=order["maker_address"])) + + pad_20_bytes_to_32(to_bytes(hexstr=order["taker_address"])) + + pad_20_bytes_to_32(to_bytes(hexstr=order["fee_recipient_address"])) + + pad_20_bytes_to_32(to_bytes(hexstr=order["sender_address"])) + + int_to_32_big_endian_bytes(order["maker_asset_amount"]) + + int_to_32_big_endian_bytes(order["taker_asset_amount"]) + + int_to_32_big_endian_bytes(order["maker_fee"]) + + int_to_32_big_endian_bytes(order["taker_fee"]) + + int_to_32_big_endian_bytes(order["expiration_time_seconds"]) + + int_to_32_big_endian_bytes(order["salt"]) + + keccak(to_bytes(hexstr=order["maker_asset_data"])) + + keccak(to_bytes(hexstr=order["taker_asset_data"])) + ) + + return keccak( + Constants.eip191_header + + eip712_domain_struct_hash + + eip712_order_struct_hash + ).hex() diff --git a/python-packages/order_utils/src/zero_ex/order_utils/signature_utils.py b/python-packages/order_utils/src/zero_ex/order_utils/signature_utils.py index 12525ba88..2e75be6d5 100644 --- a/python-packages/order_utils/src/zero_ex/order_utils/signature_utils.py +++ b/python-packages/order_utils/src/zero_ex/order_utils/signature_utils.py @@ -1,31 +1,17 @@ """Signature utilities.""" -from typing import Dict, Tuple -import json -from pkg_resources import resource_string +from typing import Tuple from eth_utils import is_address, to_checksum_address from web3 import Web3 import web3.exceptions from web3.utils import datatypes +from zero_ex.order_utils import Constants from zero_ex.dev_utils.type_assertions import assert_is_hex_string # prefer `black` formatting. pylint: disable=C0330 -EXCHANGE_ABI = json.loads( - resource_string("zero_ex.contract_artifacts", "artifacts/Exchange.json") -)["compilerOutput"]["abi"] - -network_to_exchange_addr: Dict[str, str] = { - "1": "0x4f833a24e1f95d70f028921e27040ca56e09ab0b", - "3": "0x4530c0483a1633c7a1c97d2c53721caff2caaaaf", - "42": "0x35dd2932454449b14cee11a94d3674a936d5d7b2", - "50": "0x48bacb9266a570d521063ef5dd96e61686dbe788", -} - - -# prefer `black` formatting. pylint: disable=C0330 def is_valid_signature( provider: Web3.HTTPProvider, data: str, signature: str, signer_address: str ) -> Tuple[bool, str]: @@ -63,10 +49,11 @@ def is_valid_signature( web3_instance = Web3(provider) # false positive from pylint: disable=no-member network_id = web3_instance.net.version - contract_address = network_to_exchange_addr[network_id] + contract_address = Constants.network_to_exchange_addr[network_id] # false positive from pylint: disable=no-member contract: datatypes.Contract = web3_instance.eth.contract( - address=to_checksum_address(contract_address), abi=EXCHANGE_ABI + address=to_checksum_address(contract_address), + abi=Constants.contract_name_to_abi["Exchange"], ) try: return ( diff --git a/python-packages/order_utils/stubs/sha3/__init__.pyi b/python-packages/order_utils/stubs/sha3/__init__.pyi new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/python-packages/order_utils/stubs/sha3/__init__.pyi diff --git a/python-packages/order_utils/test/test_generate_order_hash_hex.py b/python-packages/order_utils/test/test_generate_order_hash_hex.py new file mode 100644 index 000000000..e393f38d7 --- /dev/null +++ b/python-packages/order_utils/test/test_generate_order_hash_hex.py @@ -0,0 +1,18 @@ +"""Test zero_ex.order_utils.get_order_hash_hex().""" + +from zero_ex.order_utils import ( + generate_order_hash_hex, + make_empty_order, + Constants, +) + + +def test_get_order_hash_hex__empty_order(): + """Test the hashing of an uninitialized order.""" + expected_hash_hex = ( + "faa49b35faeb9197e9c3ba7a52075e6dad19739549f153b77dfcf59408a4b422" + ) + actual_hash_hex = generate_order_hash_hex( + make_empty_order(), Constants.null_address + ) + assert actual_hash_hex == expected_hash_hex @@ -6786,7 +6786,7 @@ ganache-core@0xProject/ganache-core#monorepo-dep: ethereumjs-tx "0xProject/ethereumjs-tx#fake-tx-include-signature-by-default" ethereumjs-util "^5.2.0" ethereumjs-vm "2.3.5" - ethereumjs-wallet "~0.6.0" + ethereumjs-wallet "0.6.0" fake-merkle-patricia-tree "~1.0.1" heap "~0.2.6" js-scrypt "^0.2.0" |