Merge branch 'development' of https://github.com/0xProject/0x-monorepo into feature/instant/input-fees-rounding
This commit is contained in:
commit
11f7f2d29f
24
packages/instant/src/components/animations/full_rotation.tsx
Normal file
24
packages/instant/src/components/animations/full_rotation.tsx
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import { keyframes, styled } from '../../style/theme';
|
||||||
|
|
||||||
|
interface FullRotationProps {
|
||||||
|
height: string;
|
||||||
|
width: string;
|
||||||
|
}
|
||||||
|
const rotatingKeyframes = keyframes`
|
||||||
|
from {
|
||||||
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
to {
|
||||||
|
transform: rotate(360deg);
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const FullRotation =
|
||||||
|
styled.div <
|
||||||
|
FullRotationProps >
|
||||||
|
`
|
||||||
|
animation: ${rotatingKeyframes} 2s linear infinite;
|
||||||
|
height: ${props => props.height};
|
||||||
|
width: ${props => props.width};
|
||||||
|
`;
|
@ -41,8 +41,8 @@ export class BuyButton extends React.Component<BuyButtonProps> {
|
|||||||
let txnHash;
|
let txnHash;
|
||||||
try {
|
try {
|
||||||
txnHash = await this.props.assetBuyer.executeBuyQuoteAsync(this.props.buyQuote);
|
txnHash = await this.props.assetBuyer.executeBuyQuoteAsync(this.props.buyQuote);
|
||||||
await web3Wrapper.awaitTransactionSuccessAsync(txnHash);
|
const txnReceipt = await web3Wrapper.awaitTransactionSuccessAsync(txnHash);
|
||||||
this.props.onBuySuccess(this.props.buyQuote, txnHash);
|
this.props.onBuySuccess(this.props.buyQuote, txnReceipt.transactionHash);
|
||||||
} catch {
|
} catch {
|
||||||
this.props.onBuyFailure(this.props.buyQuote, txnHash);
|
this.props.onBuyFailure(this.props.buyQuote, txnHash);
|
||||||
}
|
}
|
||||||
|
@ -1,23 +1,22 @@
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
|
||||||
|
import { PlacingOrderButton } from '../components/placing_order_button';
|
||||||
import { SelectedAssetBuyButton } from '../containers/selected_asset_buy_button';
|
import { SelectedAssetBuyButton } from '../containers/selected_asset_buy_button';
|
||||||
import { SelectedAssetRetryButton } from '../containers/selected_asset_retry_button';
|
import { SelectedAssetRetryButton } from '../containers/selected_asset_retry_button';
|
||||||
|
import { SelectedAssetViewTransactionButton } from '../containers/selected_asset_view_transaction_button';
|
||||||
import { AsyncProcessState } from '../types';
|
import { AsyncProcessState } from '../types';
|
||||||
|
|
||||||
import { SecondaryButton } from './secondary_button';
|
|
||||||
|
|
||||||
export interface BuyOrderStateButtonProps {
|
export interface BuyOrderStateButtonProps {
|
||||||
buyOrderState: AsyncProcessState;
|
buyOrderProcessingState: AsyncProcessState;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const BuyOrderStateButton: React.StatelessComponent<BuyOrderStateButtonProps> = props => {
|
export const BuyOrderStateButton: React.StatelessComponent<BuyOrderStateButtonProps> = props => {
|
||||||
if (props.buyOrderState === AsyncProcessState.FAILURE) {
|
if (props.buyOrderProcessingState === AsyncProcessState.FAILURE) {
|
||||||
return <SelectedAssetRetryButton />;
|
return <SelectedAssetRetryButton />;
|
||||||
} else if (props.buyOrderState === AsyncProcessState.SUCCESS) {
|
} else if (props.buyOrderProcessingState === AsyncProcessState.SUCCESS) {
|
||||||
return <SecondaryButton text="Success" isDisabled={true} />;
|
return <SelectedAssetViewTransactionButton />;
|
||||||
} else if (props.buyOrderState === AsyncProcessState.PENDING) {
|
} else if (props.buyOrderProcessingState === AsyncProcessState.PENDING) {
|
||||||
return <SecondaryButton text="Processing" isDisabled={true} />;
|
return <PlacingOrderButton />;
|
||||||
}
|
}
|
||||||
|
|
||||||
return <SelectedAssetBuyButton />;
|
return <SelectedAssetBuyButton />;
|
||||||
|
@ -4,7 +4,7 @@ import * as React from 'react';
|
|||||||
|
|
||||||
import { SelectedAssetAmountInput } from '../containers/selected_asset_amount_input';
|
import { SelectedAssetAmountInput } from '../containers/selected_asset_amount_input';
|
||||||
import { ColorOption } from '../style/theme';
|
import { ColorOption } from '../style/theme';
|
||||||
import { AsyncProcessState } from '../types';
|
import { AsyncProcessState, OrderState } from '../types';
|
||||||
import { format } from '../util/format';
|
import { format } from '../util/format';
|
||||||
|
|
||||||
import { AmountPlaceholder } from './amount_placeholder';
|
import { AmountPlaceholder } from './amount_placeholder';
|
||||||
@ -16,10 +16,14 @@ export interface InstantHeadingProps {
|
|||||||
totalEthBaseAmount?: BigNumber;
|
totalEthBaseAmount?: BigNumber;
|
||||||
ethUsdPrice?: BigNumber;
|
ethUsdPrice?: BigNumber;
|
||||||
quoteRequestState: AsyncProcessState;
|
quoteRequestState: AsyncProcessState;
|
||||||
buyOrderState: AsyncProcessState;
|
buyOrderState: OrderState;
|
||||||
}
|
}
|
||||||
|
|
||||||
const placeholderColor = ColorOption.white;
|
const PLACEHOLDER_COLOR = ColorOption.white;
|
||||||
|
const ICON_WIDTH = 34;
|
||||||
|
const ICON_HEIGHT = 34;
|
||||||
|
const ICON_COLOR = ColorOption.white;
|
||||||
|
|
||||||
export class InstantHeading extends React.Component<InstantHeadingProps, {}> {
|
export class InstantHeading extends React.Component<InstantHeadingProps, {}> {
|
||||||
public render(): React.ReactNode {
|
public render(): React.ReactNode {
|
||||||
const iconOrAmounts = this._renderIcon() || this._renderAmountsSection();
|
const iconOrAmounts = this._renderIcon() || this._renderAmountsSection();
|
||||||
@ -64,15 +68,22 @@ export class InstantHeading extends React.Component<InstantHeadingProps, {}> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private _renderIcon(): React.ReactNode {
|
private _renderIcon(): React.ReactNode {
|
||||||
if (this.props.buyOrderState === AsyncProcessState.FAILURE) {
|
const processState = this.props.buyOrderState.processState;
|
||||||
return <Icon icon={'failed'} width={34} height={34} color={ColorOption.white} />;
|
|
||||||
|
if (processState === AsyncProcessState.FAILURE) {
|
||||||
|
return <Icon icon={'failed'} width={ICON_WIDTH} height={ICON_HEIGHT} color={ICON_COLOR} />;
|
||||||
|
} else if (processState === AsyncProcessState.SUCCESS) {
|
||||||
|
return <Icon icon={'success'} width={ICON_WIDTH} height={ICON_HEIGHT} color={ICON_COLOR} />;
|
||||||
}
|
}
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
private _renderTopText(): React.ReactNode {
|
private _renderTopText(): React.ReactNode {
|
||||||
if (this.props.buyOrderState === AsyncProcessState.FAILURE) {
|
const processState = this.props.buyOrderState.processState;
|
||||||
|
if (processState === AsyncProcessState.FAILURE) {
|
||||||
return 'Order failed';
|
return 'Order failed';
|
||||||
|
} else if (processState === AsyncProcessState.SUCCESS) {
|
||||||
|
return 'Tokens received!';
|
||||||
}
|
}
|
||||||
|
|
||||||
return 'I want to buy';
|
return 'I want to buy';
|
||||||
@ -80,10 +91,10 @@ export class InstantHeading extends React.Component<InstantHeadingProps, {}> {
|
|||||||
|
|
||||||
private _placeholderOrAmount(amountFunction: () => React.ReactNode): React.ReactNode {
|
private _placeholderOrAmount(amountFunction: () => React.ReactNode): React.ReactNode {
|
||||||
if (this.props.quoteRequestState === AsyncProcessState.PENDING) {
|
if (this.props.quoteRequestState === AsyncProcessState.PENDING) {
|
||||||
return <AmountPlaceholder isPulsating={true} color={placeholderColor} />;
|
return <AmountPlaceholder isPulsating={true} color={PLACEHOLDER_COLOR} />;
|
||||||
}
|
}
|
||||||
if (_.isUndefined(this.props.selectedAssetAmount)) {
|
if (_.isUndefined(this.props.selectedAssetAmount)) {
|
||||||
return <AmountPlaceholder isPulsating={false} color={placeholderColor} />;
|
return <AmountPlaceholder isPulsating={false} color={PLACEHOLDER_COLOR} />;
|
||||||
}
|
}
|
||||||
return amountFunction();
|
return amountFunction();
|
||||||
}
|
}
|
||||||
@ -94,7 +105,7 @@ export class InstantHeading extends React.Component<InstantHeadingProps, {}> {
|
|||||||
{format.ethBaseAmount(
|
{format.ethBaseAmount(
|
||||||
this.props.totalEthBaseAmount,
|
this.props.totalEthBaseAmount,
|
||||||
4,
|
4,
|
||||||
<AmountPlaceholder isPulsating={false} color={placeholderColor} />,
|
<AmountPlaceholder isPulsating={false} color={PLACEHOLDER_COLOR} />,
|
||||||
)}
|
)}
|
||||||
</Text>
|
</Text>
|
||||||
);
|
);
|
||||||
|
19
packages/instant/src/components/placing_order_button.tsx
Normal file
19
packages/instant/src/components/placing_order_button.tsx
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import * as React from 'react';
|
||||||
|
|
||||||
|
import { ColorOption } from '../style/theme';
|
||||||
|
|
||||||
|
import { Button } from './ui/button';
|
||||||
|
import { Container } from './ui/container';
|
||||||
|
import { Spinner } from './ui/spinner';
|
||||||
|
import { Text } from './ui/text';
|
||||||
|
|
||||||
|
export const PlacingOrderButton: React.StatelessComponent<{}> = props => (
|
||||||
|
<Button isDisabled={true} width="100%">
|
||||||
|
<Container display="inline-block" position="relative" top="3px" marginRight="8px">
|
||||||
|
<Spinner widthPx={20} heightPx={20} />
|
||||||
|
</Container>
|
||||||
|
<Text fontColor={ColorOption.white} fontWeight={600} fontSize="20px">
|
||||||
|
Placing Order…
|
||||||
|
</Text>
|
||||||
|
</Button>
|
||||||
|
);
|
@ -7,5 +7,5 @@ export interface RetryButtonProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const RetryButton: React.StatelessComponent<RetryButtonProps> = props => {
|
export const RetryButton: React.StatelessComponent<RetryButtonProps> = props => {
|
||||||
return <SecondaryButton text="Try Again" onClick={props.onClick} />;
|
return <SecondaryButton onClick={props.onClick}>Try Again</SecondaryButton>;
|
||||||
};
|
};
|
||||||
|
@ -6,9 +6,7 @@ import { ColorOption } from '../style/theme';
|
|||||||
import { Button, ButtonProps } from './ui/button';
|
import { Button, ButtonProps } from './ui/button';
|
||||||
import { Text } from './ui/text';
|
import { Text } from './ui/text';
|
||||||
|
|
||||||
export interface SecondaryButtonProps extends ButtonProps {
|
export interface SecondaryButtonProps extends ButtonProps {}
|
||||||
text: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const SecondaryButton: React.StatelessComponent<SecondaryButtonProps> = props => {
|
export const SecondaryButton: React.StatelessComponent<SecondaryButtonProps> = props => {
|
||||||
const buttonProps = _.omit(props, 'text');
|
const buttonProps = _.omit(props, 'text');
|
||||||
@ -21,7 +19,7 @@ export const SecondaryButton: React.StatelessComponent<SecondaryButtonProps> = p
|
|||||||
{...buttonProps}
|
{...buttonProps}
|
||||||
>
|
>
|
||||||
<Text fontColor={ColorOption.primaryColor} fontWeight={600} fontSize="16px">
|
<Text fontColor={ColorOption.primaryColor} fontWeight={600} fontSize="16px">
|
||||||
{props.text}
|
{props.children}
|
||||||
</Text>
|
</Text>
|
||||||
</Button>
|
</Button>
|
||||||
);
|
);
|
||||||
|
30
packages/instant/src/components/ui/spinner.tsx
Normal file
30
packages/instant/src/components/ui/spinner.tsx
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
import * as React from 'react';
|
||||||
|
|
||||||
|
import { FullRotation } from '../animations/full_rotation';
|
||||||
|
|
||||||
|
export interface SpinnerProps {
|
||||||
|
widthPx: number;
|
||||||
|
heightPx: number;
|
||||||
|
}
|
||||||
|
export const Spinner: React.StatelessComponent<SpinnerProps> = props => {
|
||||||
|
return (
|
||||||
|
<FullRotation width={`${props.widthPx}px`} height={`${props.heightPx}px`}>
|
||||||
|
<svg
|
||||||
|
width={props.widthPx}
|
||||||
|
height={props.heightPx}
|
||||||
|
viewBox="0 0 34 34"
|
||||||
|
fill="none"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<circle cx="17" cy="17" r="15" stroke="white" strokeOpacity="0.2" strokeWidth="4" />
|
||||||
|
<path
|
||||||
|
d="M17 32C25.2843 32 32 25.2843 32 17C32 8.71573 25.2843 2 17 2"
|
||||||
|
stroke="white"
|
||||||
|
strokeWidth="4"
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</FullRotation>
|
||||||
|
);
|
||||||
|
};
|
11
packages/instant/src/components/view_transaction_button.tsx
Normal file
11
packages/instant/src/components/view_transaction_button.tsx
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import * as React from 'react';
|
||||||
|
|
||||||
|
import { SecondaryButton } from './secondary_button';
|
||||||
|
|
||||||
|
export interface ViewTransactionButtonProps {
|
||||||
|
onClick: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ViewTransactionButton: React.StatelessComponent<ViewTransactionButtonProps> = props => {
|
||||||
|
return <SecondaryButton onClick={props.onClick}>View Transaction</SecondaryButton>;
|
||||||
|
};
|
@ -90,7 +90,7 @@ const mapDispatchToProps = (
|
|||||||
// invalidate the last buy quote.
|
// invalidate the last buy quote.
|
||||||
dispatch(actions.updateLatestBuyQuote(undefined));
|
dispatch(actions.updateLatestBuyQuote(undefined));
|
||||||
// reset our buy state
|
// reset our buy state
|
||||||
dispatch(actions.updateBuyOrderState(AsyncProcessState.NONE));
|
dispatch(actions.updateBuyOrderState({ processState: AsyncProcessState.NONE }));
|
||||||
|
|
||||||
if (!_.isUndefined(value) && !_.isUndefined(asset) && !_.isUndefined(assetBuyer)) {
|
if (!_.isUndefined(value) && !_.isUndefined(asset) && !_.isUndefined(assetBuyer)) {
|
||||||
// even if it's debounced, give them the illusion it's loading
|
// even if it's debounced, give them the illusion it's loading
|
||||||
|
@ -19,7 +19,7 @@ interface ConnectedState {
|
|||||||
|
|
||||||
interface ConnectedDispatch {
|
interface ConnectedDispatch {
|
||||||
onClick: (buyQuote: BuyQuote) => void;
|
onClick: (buyQuote: BuyQuote) => void;
|
||||||
onBuySuccess: (buyQuote: BuyQuote) => void;
|
onBuySuccess: (buyQuote: BuyQuote, txnHash: string) => void;
|
||||||
onBuyFailure: (buyQuote: BuyQuote) => void;
|
onBuyFailure: (buyQuote: BuyQuote) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -29,9 +29,10 @@ const mapStateToProps = (state: State, _ownProps: SelectedAssetBuyButtonProps):
|
|||||||
});
|
});
|
||||||
|
|
||||||
const mapDispatchToProps = (dispatch: Dispatch<Action>, ownProps: SelectedAssetBuyButtonProps): ConnectedDispatch => ({
|
const mapDispatchToProps = (dispatch: Dispatch<Action>, ownProps: SelectedAssetBuyButtonProps): ConnectedDispatch => ({
|
||||||
onClick: buyQuote => dispatch(actions.updateBuyOrderState(AsyncProcessState.PENDING)),
|
onClick: buyQuote => dispatch(actions.updateBuyOrderState({ processState: AsyncProcessState.PENDING })),
|
||||||
onBuySuccess: buyQuote => dispatch(actions.updateBuyOrderState(AsyncProcessState.SUCCESS)),
|
onBuySuccess: (buyQuote: BuyQuote, txnHash: string) =>
|
||||||
onBuyFailure: buyQuote => dispatch(actions.updateBuyOrderState(AsyncProcessState.FAILURE)),
|
dispatch(actions.updateBuyOrderState({ processState: AsyncProcessState.SUCCESS, txnHash })),
|
||||||
|
onBuyFailure: buyQuote => dispatch(actions.updateBuyOrderState({ processState: AsyncProcessState.FAILURE })),
|
||||||
});
|
});
|
||||||
|
|
||||||
export const SelectedAssetBuyButton: React.ComponentClass<SelectedAssetBuyButtonProps> = connect(
|
export const SelectedAssetBuyButton: React.ComponentClass<SelectedAssetBuyButtonProps> = connect(
|
||||||
|
@ -8,11 +8,11 @@ import { AsyncProcessState } from '../types';
|
|||||||
import { BuyOrderStateButton } from '../components/buy_order_state_button';
|
import { BuyOrderStateButton } from '../components/buy_order_state_button';
|
||||||
|
|
||||||
interface ConnectedState {
|
interface ConnectedState {
|
||||||
buyOrderState: AsyncProcessState;
|
buyOrderProcessingState: AsyncProcessState;
|
||||||
}
|
}
|
||||||
export interface SelectedAssetButtonProps {}
|
export interface SelectedAssetButtonProps {}
|
||||||
const mapStateToProps = (state: State, _ownProps: SelectedAssetButtonProps): ConnectedState => ({
|
const mapStateToProps = (state: State, _ownProps: SelectedAssetButtonProps): ConnectedState => ({
|
||||||
buyOrderState: state.buyOrderState,
|
buyOrderProcessingState: state.buyOrderState.processState,
|
||||||
});
|
});
|
||||||
|
|
||||||
export const SelectedAssetBuyOrderStateButton: React.ComponentClass<SelectedAssetButtonProps> = connect(
|
export const SelectedAssetBuyOrderStateButton: React.ComponentClass<SelectedAssetButtonProps> = connect(
|
||||||
|
@ -5,7 +5,7 @@ import { connect } from 'react-redux';
|
|||||||
import { oc } from 'ts-optchain';
|
import { oc } from 'ts-optchain';
|
||||||
|
|
||||||
import { State } from '../redux/reducer';
|
import { State } from '../redux/reducer';
|
||||||
import { AsyncProcessState } from '../types';
|
import { AsyncProcessState, OrderState } from '../types';
|
||||||
|
|
||||||
import { InstantHeading } from '../components/instant_heading';
|
import { InstantHeading } from '../components/instant_heading';
|
||||||
|
|
||||||
@ -16,7 +16,7 @@ interface ConnectedState {
|
|||||||
totalEthBaseAmount?: BigNumber;
|
totalEthBaseAmount?: BigNumber;
|
||||||
ethUsdPrice?: BigNumber;
|
ethUsdPrice?: BigNumber;
|
||||||
quoteRequestState: AsyncProcessState;
|
quoteRequestState: AsyncProcessState;
|
||||||
buyOrderState: AsyncProcessState;
|
buyOrderState: OrderState;
|
||||||
}
|
}
|
||||||
|
|
||||||
const mapStateToProps = (state: State, _ownProps: InstantHeadingProps): ConnectedState => ({
|
const mapStateToProps = (state: State, _ownProps: InstantHeadingProps): ConnectedState => ({
|
||||||
|
@ -0,0 +1,34 @@
|
|||||||
|
import * as _ from 'lodash';
|
||||||
|
import * as React from 'react';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
|
||||||
|
import { State } from '../redux/reducer';
|
||||||
|
|
||||||
|
import { ViewTransactionButton } from '../components/view_transaction_button';
|
||||||
|
import { AsyncProcessState } from '../types';
|
||||||
|
import { etherscanUtil } from '../util/etherscan';
|
||||||
|
|
||||||
|
export interface SelectedAssetViewTransactionButtonProps {}
|
||||||
|
|
||||||
|
interface ConnectedState {
|
||||||
|
onClick: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const mapStateToProps = (state: State, _ownProps: {}): ConnectedState => ({
|
||||||
|
onClick: () => {
|
||||||
|
if (state.assetBuyer && state.buyOrderState.processState === AsyncProcessState.SUCCESS) {
|
||||||
|
const etherscanUrl = etherscanUtil.getEtherScanTxnAddressIfExists(
|
||||||
|
state.buyOrderState.txnHash,
|
||||||
|
state.assetBuyer.networkId,
|
||||||
|
);
|
||||||
|
if (etherscanUrl) {
|
||||||
|
window.open(etherscanUrl, '_blank');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const SelectedAssetViewTransactionButton: React.ComponentClass<
|
||||||
|
SelectedAssetViewTransactionButtonProps
|
||||||
|
> = connect(mapStateToProps)(ViewTransactionButton);
|
@ -2,7 +2,7 @@ import { BuyQuote } from '@0x/asset-buyer';
|
|||||||
import { BigNumber } from '@0x/utils';
|
import { BigNumber } from '@0x/utils';
|
||||||
import * as _ from 'lodash';
|
import * as _ from 'lodash';
|
||||||
|
|
||||||
import { ActionsUnion, AsyncProcessState } from '../types';
|
import { ActionsUnion, OrderState } from '../types';
|
||||||
|
|
||||||
export interface PlainAction<T extends string> {
|
export interface PlainAction<T extends string> {
|
||||||
type: T;
|
type: T;
|
||||||
@ -23,7 +23,7 @@ function createAction<T extends string, P>(type: T, data?: P): PlainAction<T> |
|
|||||||
export enum ActionTypes {
|
export enum ActionTypes {
|
||||||
UPDATE_ETH_USD_PRICE = 'UPDATE_ETH_USD_PRICE',
|
UPDATE_ETH_USD_PRICE = 'UPDATE_ETH_USD_PRICE',
|
||||||
UPDATE_SELECTED_ASSET_AMOUNT = 'UPDATE_SELECTED_ASSET_AMOUNT',
|
UPDATE_SELECTED_ASSET_AMOUNT = 'UPDATE_SELECTED_ASSET_AMOUNT',
|
||||||
UPDATE_SELECTED_ASSET_BUY_STATE = 'UPDATE_SELECTED_ASSET_BUY_STATE',
|
UPDATE_BUY_ORDER_STATE = 'UPDATE_BUY_ORDER_STATE',
|
||||||
UPDATE_LATEST_BUY_QUOTE = 'UPDATE_LATEST_BUY_QUOTE',
|
UPDATE_LATEST_BUY_QUOTE = 'UPDATE_LATEST_BUY_QUOTE',
|
||||||
UPDATE_SELECTED_ASSET = 'UPDATE_SELECTED_ASSET',
|
UPDATE_SELECTED_ASSET = 'UPDATE_SELECTED_ASSET',
|
||||||
SET_QUOTE_REQUEST_STATE_PENDING = 'SET_QUOTE_REQUEST_STATE_PENDING',
|
SET_QUOTE_REQUEST_STATE_PENDING = 'SET_QUOTE_REQUEST_STATE_PENDING',
|
||||||
@ -37,8 +37,7 @@ export enum ActionTypes {
|
|||||||
export const actions = {
|
export const actions = {
|
||||||
updateEthUsdPrice: (price?: BigNumber) => createAction(ActionTypes.UPDATE_ETH_USD_PRICE, price),
|
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_AMOUNT, amount),
|
||||||
updateBuyOrderState: (buyState: AsyncProcessState) =>
|
updateBuyOrderState: (orderState: OrderState) => createAction(ActionTypes.UPDATE_BUY_ORDER_STATE, orderState),
|
||||||
createAction(ActionTypes.UPDATE_SELECTED_ASSET_BUY_STATE, buyState),
|
|
||||||
updateLatestBuyQuote: (buyQuote?: BuyQuote) => createAction(ActionTypes.UPDATE_LATEST_BUY_QUOTE, buyQuote),
|
updateLatestBuyQuote: (buyQuote?: BuyQuote) => createAction(ActionTypes.UPDATE_LATEST_BUY_QUOTE, buyQuote),
|
||||||
updateSelectedAsset: (assetData?: string) => createAction(ActionTypes.UPDATE_SELECTED_ASSET, assetData),
|
updateSelectedAsset: (assetData?: string) => createAction(ActionTypes.UPDATE_SELECTED_ASSET, assetData),
|
||||||
setQuoteRequestStatePending: () => createAction(ActionTypes.SET_QUOTE_REQUEST_STATE_PENDING),
|
setQuoteRequestStatePending: () => createAction(ActionTypes.SET_QUOTE_REQUEST_STATE_PENDING),
|
||||||
|
@ -4,7 +4,7 @@ import { BigNumber } from '@0x/utils';
|
|||||||
import * as _ from 'lodash';
|
import * as _ from 'lodash';
|
||||||
|
|
||||||
import { assetMetaDataMap } from '../data/asset_meta_data_map';
|
import { assetMetaDataMap } from '../data/asset_meta_data_map';
|
||||||
import { Asset, AssetMetaData, AsyncProcessState, DisplayStatus, Network } from '../types';
|
import { Asset, AssetMetaData, AsyncProcessState, DisplayStatus, Network, OrderState } from '../types';
|
||||||
import { assetUtils } from '../util/asset';
|
import { assetUtils } from '../util/asset';
|
||||||
|
|
||||||
import { Action, ActionTypes } from './actions';
|
import { Action, ActionTypes } from './actions';
|
||||||
@ -15,7 +15,7 @@ export interface State {
|
|||||||
assetMetaDataMap: ObjectMap<AssetMetaData>;
|
assetMetaDataMap: ObjectMap<AssetMetaData>;
|
||||||
selectedAsset?: Asset;
|
selectedAsset?: Asset;
|
||||||
selectedAssetAmount?: BigNumber;
|
selectedAssetAmount?: BigNumber;
|
||||||
buyOrderState: AsyncProcessState;
|
buyOrderState: OrderState;
|
||||||
ethUsdPrice?: BigNumber;
|
ethUsdPrice?: BigNumber;
|
||||||
latestBuyQuote?: BuyQuote;
|
latestBuyQuote?: BuyQuote;
|
||||||
quoteRequestState: AsyncProcessState;
|
quoteRequestState: AsyncProcessState;
|
||||||
@ -27,7 +27,7 @@ export const INITIAL_STATE: State = {
|
|||||||
network: Network.Mainnet,
|
network: Network.Mainnet,
|
||||||
selectedAssetAmount: undefined,
|
selectedAssetAmount: undefined,
|
||||||
assetMetaDataMap,
|
assetMetaDataMap,
|
||||||
buyOrderState: AsyncProcessState.NONE,
|
buyOrderState: { processState: AsyncProcessState.NONE },
|
||||||
ethUsdPrice: undefined,
|
ethUsdPrice: undefined,
|
||||||
latestBuyQuote: undefined,
|
latestBuyQuote: undefined,
|
||||||
latestError: undefined,
|
latestError: undefined,
|
||||||
@ -65,7 +65,7 @@ export const reducer = (state: State = INITIAL_STATE, action: Action): State =>
|
|||||||
latestBuyQuote: undefined,
|
latestBuyQuote: undefined,
|
||||||
quoteRequestState: AsyncProcessState.FAILURE,
|
quoteRequestState: AsyncProcessState.FAILURE,
|
||||||
};
|
};
|
||||||
case ActionTypes.UPDATE_SELECTED_ASSET_BUY_STATE:
|
case ActionTypes.UPDATE_BUY_ORDER_STATE:
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
buyOrderState: action.data,
|
buyOrderState: action.data,
|
||||||
@ -106,7 +106,7 @@ export const reducer = (state: State = INITIAL_STATE, action: Action): State =>
|
|||||||
...state,
|
...state,
|
||||||
latestBuyQuote: undefined,
|
latestBuyQuote: undefined,
|
||||||
quoteRequestState: AsyncProcessState.NONE,
|
quoteRequestState: AsyncProcessState.NONE,
|
||||||
buyOrderState: AsyncProcessState.NONE,
|
buyOrderState: { processState: AsyncProcessState.NONE },
|
||||||
selectedAssetAmount: undefined,
|
selectedAssetAmount: undefined,
|
||||||
};
|
};
|
||||||
default:
|
default:
|
||||||
|
@ -7,6 +7,20 @@ export enum AsyncProcessState {
|
|||||||
SUCCESS = 'Success',
|
SUCCESS = 'Success',
|
||||||
FAILURE = 'Failure',
|
FAILURE = 'Failure',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface RegularOrderState {
|
||||||
|
processState: AsyncProcessState.NONE | AsyncProcessState.PENDING;
|
||||||
|
}
|
||||||
|
interface SuccessfulOrderState {
|
||||||
|
processState: AsyncProcessState.SUCCESS;
|
||||||
|
txnHash: string;
|
||||||
|
}
|
||||||
|
interface FailureOrderState {
|
||||||
|
processState: AsyncProcessState.FAILURE;
|
||||||
|
txnHash?: string;
|
||||||
|
}
|
||||||
|
export type OrderState = RegularOrderState | SuccessfulOrderState | FailureOrderState;
|
||||||
|
|
||||||
export enum DisplayStatus {
|
export enum DisplayStatus {
|
||||||
Present,
|
Present,
|
||||||
Hidden,
|
Hidden,
|
||||||
|
24
packages/instant/src/util/etherscan.ts
Normal file
24
packages/instant/src/util/etherscan.ts
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import * as _ from 'lodash';
|
||||||
|
|
||||||
|
import { Network } from '../types';
|
||||||
|
|
||||||
|
const etherscanPrefix = (networkId: number): string | undefined => {
|
||||||
|
switch (networkId) {
|
||||||
|
case Network.Kovan:
|
||||||
|
return 'kovan.';
|
||||||
|
case Network.Mainnet:
|
||||||
|
return '';
|
||||||
|
default:
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const etherscanUtil = {
|
||||||
|
getEtherScanTxnAddressIfExists: (txnHash: string, networkId: number) => {
|
||||||
|
const prefix = etherscanPrefix(networkId);
|
||||||
|
if (_.isUndefined(prefix)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return `https://${prefix}etherscan.io/tx/${txnHash}`;
|
||||||
|
},
|
||||||
|
};
|
@ -6776,7 +6776,7 @@ ganache-core@0xProject/ganache-core#monorepo-dep:
|
|||||||
ethereumjs-tx "0xProject/ethereumjs-tx#fake-tx-include-signature-by-default"
|
ethereumjs-tx "0xProject/ethereumjs-tx#fake-tx-include-signature-by-default"
|
||||||
ethereumjs-util "^5.2.0"
|
ethereumjs-util "^5.2.0"
|
||||||
ethereumjs-vm "2.3.5"
|
ethereumjs-vm "2.3.5"
|
||||||
ethereumjs-wallet "~0.6.0"
|
ethereumjs-wallet "0.6.0"
|
||||||
fake-merkle-patricia-tree "~1.0.1"
|
fake-merkle-patricia-tree "~1.0.1"
|
||||||
heap "~0.2.6"
|
heap "~0.2.6"
|
||||||
js-scrypt "^0.2.0"
|
js-scrypt "^0.2.0"
|
||||||
@ -12579,6 +12579,13 @@ react-scroll@0xproject/react-scroll#pr-330-and-replace-state:
|
|||||||
lodash.throttle "^4.1.1"
|
lodash.throttle "^4.1.1"
|
||||||
prop-types "^15.5.8"
|
prop-types "^15.5.8"
|
||||||
|
|
||||||
|
react-scroll@0xproject/react-scroll#similar-to-pr-330-but-with-replace-state:
|
||||||
|
version "1.7.10"
|
||||||
|
resolved "https://codeload.github.com/0xproject/react-scroll/tar.gz/0f625b270d7e966313cac8b811c0ae807b37e170"
|
||||||
|
dependencies:
|
||||||
|
lodash.throttle "^4.1.1"
|
||||||
|
prop-types "^15.5.8"
|
||||||
|
|
||||||
react-side-effect@^1.0.2, react-side-effect@^1.1.0:
|
react-side-effect@^1.0.2, react-side-effect@^1.1.0:
|
||||||
version "1.1.5"
|
version "1.1.5"
|
||||||
resolved "https://registry.yarnpkg.com/react-side-effect/-/react-side-effect-1.1.5.tgz#f26059e50ed9c626d91d661b9f3c8bb38cd0ff2d"
|
resolved "https://registry.yarnpkg.com/react-side-effect/-/react-side-effect-1.1.5.tgz#f26059e50ed9c626d91d661b9f3c8bb38cd0ff2d"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user