Merge pull request #648 from 0xProject/feature/website/fill-order
Add shared order support
This commit is contained in:
commit
9ca41b9536
@ -38,6 +38,7 @@ import {
|
|||||||
} from 'ts/types';
|
} from 'ts/types';
|
||||||
import { configs } from 'ts/utils/configs';
|
import { configs } from 'ts/utils/configs';
|
||||||
import { constants } from 'ts/utils/constants';
|
import { constants } from 'ts/utils/constants';
|
||||||
|
import { orderParser } from 'ts/utils/order_parser';
|
||||||
import { Translate } from 'ts/utils/translate';
|
import { Translate } from 'ts/utils/translate';
|
||||||
import { utils } from 'ts/utils/utils';
|
import { utils } from 'ts/utils/utils';
|
||||||
|
|
||||||
@ -86,7 +87,7 @@ export class LegacyPortal extends React.Component<LegacyPortalProps, LegacyPorta
|
|||||||
}
|
}
|
||||||
constructor(props: LegacyPortalProps) {
|
constructor(props: LegacyPortalProps) {
|
||||||
super(props);
|
super(props);
|
||||||
this._sharedOrderIfExists = this._getSharedOrderIfExists();
|
this._sharedOrderIfExists = orderParser.parse(window.location.search);
|
||||||
this._throttledScreenWidthUpdate = _.throttle(this._updateScreenWidth.bind(this), THROTTLE_TIMEOUT);
|
this._throttledScreenWidthUpdate = _.throttle(this._updateScreenWidth.bind(this), THROTTLE_TIMEOUT);
|
||||||
|
|
||||||
const isViewingBalances = _.includes(props.location.pathname, `${WebsitePaths.Portal}/balances`);
|
const isViewingBalances = _.includes(props.location.pathname, `${WebsitePaths.Portal}/balances`);
|
||||||
@ -362,32 +363,6 @@ export class LegacyPortal extends React.Component<LegacyPortalProps, LegacyPorta
|
|||||||
isWethNoticeDialogOpen: false,
|
isWethNoticeDialogOpen: false,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
private _getSharedOrderIfExists(): Order | undefined {
|
|
||||||
const queryString = window.location.search;
|
|
||||||
if (queryString.length === 0) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
const queryParams = queryString.substring(1).split('&');
|
|
||||||
const orderQueryParam = _.find(queryParams, queryParam => {
|
|
||||||
const queryPair = queryParam.split('=');
|
|
||||||
return queryPair[0] === 'order';
|
|
||||||
});
|
|
||||||
if (_.isUndefined(orderQueryParam)) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
const orderPair = orderQueryParam.split('=');
|
|
||||||
if (orderPair.length !== 2) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
const order = JSON.parse(decodeURIComponent(orderPair[1]));
|
|
||||||
const validationResult = validator.validate(order, portalOrderSchema);
|
|
||||||
if (validationResult.errors.length > 0) {
|
|
||||||
logUtils.log(`Invalid shared order: ${validationResult.errors}`);
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
return order;
|
|
||||||
}
|
|
||||||
private _updateScreenWidth(): void {
|
private _updateScreenWidth(): void {
|
||||||
const newScreenWidth = utils.getScreenWidth();
|
const newScreenWidth = utils.getScreenWidth();
|
||||||
this.props.dispatcher.updateScreenWidth(newScreenWidth);
|
this.props.dispatcher.updateScreenWidth(newScreenWidth);
|
||||||
|
@ -43,9 +43,14 @@ export const defaultMenuItemEntries: MenuItemEntry[] = [
|
|||||||
iconName: 'zmdi-circle-o',
|
iconName: 'zmdi-circle-o',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
to: `${WebsitePaths.Portal}/direct`,
|
to: `${WebsitePaths.Portal}/generate`,
|
||||||
labelText: 'Trade direct',
|
labelText: 'Generate order',
|
||||||
iconName: 'zmdi-swap',
|
iconName: 'zmdi-arrow-right-top',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
to: `${WebsitePaths.Portal}/fill`,
|
||||||
|
labelText: 'Fill order',
|
||||||
|
iconName: 'zmdi-arrow-left-bottom',
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@ import { BlockchainErrDialog } from 'ts/components/dialogs/blockchain_err_dialog
|
|||||||
import { LedgerConfigDialog } from 'ts/components/dialogs/ledger_config_dialog';
|
import { LedgerConfigDialog } from 'ts/components/dialogs/ledger_config_dialog';
|
||||||
import { PortalDisclaimerDialog } from 'ts/components/dialogs/portal_disclaimer_dialog';
|
import { PortalDisclaimerDialog } from 'ts/components/dialogs/portal_disclaimer_dialog';
|
||||||
import { EthWrappers } from 'ts/components/eth_wrappers';
|
import { EthWrappers } from 'ts/components/eth_wrappers';
|
||||||
|
import { FillOrder } from 'ts/components/fill_order';
|
||||||
import { AssetPicker } from 'ts/components/generate_order/asset_picker';
|
import { AssetPicker } from 'ts/components/generate_order/asset_picker';
|
||||||
import { BackButton } from 'ts/components/portal/back_button';
|
import { BackButton } from 'ts/components/portal/back_button';
|
||||||
import { Loading } from 'ts/components/portal/loading';
|
import { Loading } from 'ts/components/portal/loading';
|
||||||
@ -42,6 +43,7 @@ import {
|
|||||||
} from 'ts/types';
|
} from 'ts/types';
|
||||||
import { configs } from 'ts/utils/configs';
|
import { configs } from 'ts/utils/configs';
|
||||||
import { constants } from 'ts/utils/constants';
|
import { constants } from 'ts/utils/constants';
|
||||||
|
import { orderParser } from 'ts/utils/order_parser';
|
||||||
import { Translate } from 'ts/utils/translate';
|
import { Translate } from 'ts/utils/translate';
|
||||||
import { utils } from 'ts/utils/utils';
|
import { utils } from 'ts/utils/utils';
|
||||||
|
|
||||||
@ -116,9 +118,11 @@ const styles: Styles = {
|
|||||||
|
|
||||||
export class Portal extends React.Component<PortalProps, PortalState> {
|
export class Portal extends React.Component<PortalProps, PortalState> {
|
||||||
private _blockchain: Blockchain;
|
private _blockchain: Blockchain;
|
||||||
|
private _sharedOrderIfExists: Order;
|
||||||
private _throttledScreenWidthUpdate: () => void;
|
private _throttledScreenWidthUpdate: () => void;
|
||||||
constructor(props: PortalProps) {
|
constructor(props: PortalProps) {
|
||||||
super(props);
|
super(props);
|
||||||
|
this._sharedOrderIfExists = orderParser.parse(window.location.search);
|
||||||
this._throttledScreenWidthUpdate = _.throttle(this._updateScreenWidth.bind(this), THROTTLE_TIMEOUT);
|
this._throttledScreenWidthUpdate = _.throttle(this._updateScreenWidth.bind(this), THROTTLE_TIMEOUT);
|
||||||
const didAcceptPortalDisclaimer = localStorage.getItemIfExists(constants.LOCAL_STORAGE_KEY_ACCEPT_DISCLAIMER);
|
const didAcceptPortalDisclaimer = localStorage.getItemIfExists(constants.LOCAL_STORAGE_KEY_ACCEPT_DISCLAIMER);
|
||||||
const hasAcceptedDisclaimer =
|
const hasAcceptedDisclaimer =
|
||||||
@ -336,9 +340,14 @@ export class Portal extends React.Component<PortalProps, PortalState> {
|
|||||||
render: this._renderTradeHistory.bind(this),
|
render: this._renderTradeHistory.bind(this),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
pathName: `${WebsitePaths.Portal}/direct`,
|
pathName: `${WebsitePaths.Portal}/generate`,
|
||||||
headerText: 'Trade Direct',
|
headerText: 'Generate Order',
|
||||||
render: this._renderTradeDirect.bind(this),
|
render: this._renderGenerateOrderForm.bind(this),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pathName: `${WebsitePaths.Portal}/fill`,
|
||||||
|
headerText: 'Fill Order',
|
||||||
|
render: this._renderFillOrder.bind(this),
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
return (
|
return (
|
||||||
@ -386,7 +395,7 @@ export class Portal extends React.Component<PortalProps, PortalState> {
|
|||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
private _renderTradeDirect(match: any, location: Location, history: History): React.ReactNode {
|
private _renderGenerateOrderForm(): React.ReactNode {
|
||||||
return (
|
return (
|
||||||
<GenerateOrderForm
|
<GenerateOrderForm
|
||||||
blockchain={this._blockchain}
|
blockchain={this._blockchain}
|
||||||
@ -395,6 +404,25 @@ export class Portal extends React.Component<PortalProps, PortalState> {
|
|||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
private _renderFillOrder(): React.ReactNode {
|
||||||
|
const initialFillOrder = !_.isUndefined(this.props.userSuppliedOrderCache)
|
||||||
|
? this.props.userSuppliedOrderCache
|
||||||
|
: this._sharedOrderIfExists;
|
||||||
|
return (
|
||||||
|
<FillOrder
|
||||||
|
blockchain={this._blockchain}
|
||||||
|
blockchainErr={this.props.blockchainErr}
|
||||||
|
initialOrder={initialFillOrder}
|
||||||
|
isOrderInUrl={!_.isUndefined(this._sharedOrderIfExists)}
|
||||||
|
orderFillAmount={this.props.orderFillAmount}
|
||||||
|
networkId={this.props.networkId}
|
||||||
|
userAddress={this.props.userAddress}
|
||||||
|
tokenByAddress={this.props.tokenByAddress}
|
||||||
|
dispatcher={this.props.dispatcher}
|
||||||
|
lastForceTokenStateRefetch={this.props.lastForceTokenStateRefetch}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
private _renderTokenBalances(): React.ReactNode {
|
private _renderTokenBalances(): React.ReactNode {
|
||||||
const allTokens = _.values(this.props.tokenByAddress);
|
const allTokens = _.values(this.props.tokenByAddress);
|
||||||
const trackedTokens = _.filter(allTokens, t => t.isTracked);
|
const trackedTokens = _.filter(allTokens, t => t.isTracked);
|
||||||
|
33
packages/website/ts/utils/order_parser.ts
Normal file
33
packages/website/ts/utils/order_parser.ts
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
import { logUtils } from '@0xproject/utils';
|
||||||
|
import * as _ from 'lodash';
|
||||||
|
|
||||||
|
import { portalOrderSchema } from 'ts/schemas/portal_order_schema';
|
||||||
|
import { validator } from 'ts/schemas/validator';
|
||||||
|
import { Order } from 'ts/types';
|
||||||
|
|
||||||
|
export const orderParser = {
|
||||||
|
parse(queryString: string): Order | undefined {
|
||||||
|
if (queryString.length === 0) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
const queryParams = queryString.substring(1).split('&');
|
||||||
|
const orderQueryParam = _.find(queryParams, queryParam => {
|
||||||
|
const queryPair = queryParam.split('=');
|
||||||
|
return queryPair[0] === 'order';
|
||||||
|
});
|
||||||
|
if (_.isUndefined(orderQueryParam)) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
const orderPair = orderQueryParam.split('=');
|
||||||
|
if (orderPair.length !== 2) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
const order = JSON.parse(decodeURIComponent(orderPair[1]));
|
||||||
|
const validationResult = validator.validate(order, portalOrderSchema);
|
||||||
|
if (validationResult.errors.length > 0) {
|
||||||
|
logUtils.log(`Invalid shared order: ${validationResult.errors}`);
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
return order;
|
||||||
|
},
|
||||||
|
};
|
Loading…
x
Reference in New Issue
Block a user