feat: model asset meta data and add dynamic assetData state

This commit is contained in:
fragosti
2018-10-12 16:11:30 -07:00
parent ccf021b8bf
commit f39541436a
10 changed files with 136 additions and 27 deletions

View File

@@ -44,6 +44,7 @@
"homepage": "https://github.com/0xProject/0x-monorepo/packages/instant/README.md",
"dependencies": {
"@0xproject/asset-buyer": "^2.0.0",
"@0xproject/order-utils": "^1.0.7",
"@0xproject/types": "^1.1.4",
"@0xproject/typescript-typings": "^2.0.2",
"@0xproject/utils": "^2.0.2",

View File

@@ -10,10 +10,13 @@ export interface AmountInputProps {
fontColor?: ColorOption;
fontSize?: string;
value?: BigNumber;
onChange?: (value?: BigNumber) => void;
onChange: (value?: BigNumber) => void;
}
export class AmountInput extends React.Component<AmountInputProps> {
public static defaultProps = {
onChange: _.noop.bind(_),
};
public render(): React.ReactNode {
const { fontColor, fontSize, value } = this.props;
return (
@@ -40,8 +43,6 @@ export class AmountInput extends React.Component<AmountInputProps> {
return;
}
}
if (!_.isUndefined(this.props.onChange)) {
this.props.onChange(bigNumberValue);
}
this.props.onChange(bigNumberValue);
};
}

View File

@@ -0,0 +1,51 @@
import { AssetProxyId } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import * as _ from 'lodash';
import * as React from 'react';
import { assetMetaData } from '../data/asset_meta_data';
import { ColorOption } from '../style/theme';
import { AmountInput, AmountInputProps } from './amount_input';
import { Container, Text } from './ui';
export interface AssetAmountInputProps extends AmountInputProps {
assetData?: string;
onChange: (value?: BigNumber, assetData?: string) => void;
}
export class AssetAmountInput extends React.Component<AssetAmountInputProps> {
public static defaultProps = {
onChange: _.noop.bind(_),
};
public render(): React.ReactNode {
const { assetData, onChange, ...rest } = this.props;
return (
<Container>
<AmountInput {...rest} onChange={this._handleChange} />
<Container display="inline-block" marginLeft="10px">
<Text fontSize={rest.fontSize} fontColor={ColorOption.white} textTransform="uppercase">
{this._getLabel()}
</Text>
</Container>
</Container>
);
}
private readonly _getLabel = (): string => {
const unknownLabel = '???';
if (_.isUndefined(this.props.assetData)) {
return unknownLabel;
}
const metaData = assetMetaData[this.props.assetData];
if (_.isUndefined(metaData)) {
return unknownLabel;
}
if (metaData.assetProxyId === AssetProxyId.ERC20) {
return metaData.symbol;
}
return unknownLabel;
};
private readonly _handleChange = (value?: BigNumber): void => {
this.props.onChange(value, this.props.assetData);
};
}

View File

@@ -43,14 +43,7 @@ export const InstantHeading: React.StatelessComponent<InstantHeadingProps> = pro
</Text>
</Container>
<Flex direction="row" justify="space-between">
<Container>
<SelectedAssetAmountInput fontSize="45px" />
<Container display="inline-block" marginLeft="10px">
<Text fontSize="45px" fontColor={ColorOption.white} textTransform="uppercase">
zrx
</Text>
</Container>
</Container>
<SelectedAssetAmountInput fontSize="45px" />
<Flex direction="column" justify="space-between">
<Container marginBottom="5px">
<Text fontSize="16px" fontColor={ColorOption.white} fontWeight={500}>

View File

@@ -1,6 +1,6 @@
import { BigNumber } from '@0xproject/utils';
export const BIG_NUMBER_ZERO = new BigNumber(0);
export const sraApiUrl = 'https://api.radarrelay.com/0x/v2/';
export const zrxContractAddress = '0xe41d2489571d322189246dafa5ebde1f4699f498';
export const zrxAssetData = '0xf47261b0000000000000000000000000e41d2489571d322189246dafa5ebde1f4699f498';
export const zrxDecimals = 18;
export const ethDecimals = 18;

View File

@@ -5,14 +5,14 @@ import * as React from 'react';
import { connect } from 'react-redux';
import { Dispatch } from 'redux';
import { zrxContractAddress, zrxDecimals } from '../constants';
import { zrxDecimals } from '../constants';
import { Action, actions } from '../redux/actions';
import { State } from '../redux/reducer';
import { ColorOption } from '../style/theme';
import { AsyncProcessState } from '../types';
import { assetBuyer } from '../util/asset_buyer';
import { AmountInput } from '../components/amount_input';
import { AssetAmountInput } from '../components/asset_amount_input';
export interface SelectedAssetAmountInputProps {
fontColor?: ColorOption;
@@ -21,31 +21,40 @@ export interface SelectedAssetAmountInputProps {
interface ConnectedState {
value?: BigNumber;
assetData?: string;
}
interface ConnectedDispatch {
onChange?: (value?: BigNumber) => void;
onChange: (value?: BigNumber, assetData?: string) => void;
}
const mapStateToProps = (state: State, _ownProps: SelectedAssetAmountInputProps): ConnectedState => ({
value: state.selectedAssetAmount,
assetData: state.selectedAssetData,
});
const updateBuyQuote = async (dispatch: Dispatch<Action>, assetAmount?: BigNumber): Promise<void> => {
if (_.isUndefined(assetAmount)) {
const updateBuyQuoteAsync = async (
dispatch: Dispatch<Action>,
assetData?: string,
assetAmount?: BigNumber,
): Promise<void> => {
if (_.isUndefined(assetAmount) || _.isUndefined(assetData)) {
return;
}
// get a new buy quote.
const baseUnitValue = Web3Wrapper.toBaseUnitAmount(assetAmount, zrxDecimals);
const newBuyQuote = await assetBuyer.getBuyQuoteForERC20TokenAddressAsync(zrxContractAddress, baseUnitValue);
const newBuyQuote = await assetBuyer.getBuyQuoteAsync(assetData, baseUnitValue);
// invalidate the last buy quote.
dispatch(actions.updateLatestBuyQuote(newBuyQuote));
};
const debouncedUpdateBuyQuote = _.debounce(updateBuyQuote, 200, { trailing: true });
const debouncedUpdateBuyQuoteAsync = _.debounce(updateBuyQuoteAsync, 200, { trailing: true });
const mapDispatchToProps = (dispatch: Dispatch<Action>): ConnectedDispatch => ({
onChange: async value => {
const mapDispatchToProps = (
dispatch: Dispatch<Action>,
_ownProps: SelectedAssetAmountInputProps,
): ConnectedDispatch => ({
onChange: (value, assetData) => {
// Update the input
dispatch(actions.updateSelectedAssetAmount(value));
// invalidate the last buy quote.
@@ -53,11 +62,11 @@ const mapDispatchToProps = (dispatch: Dispatch<Action>): ConnectedDispatch => ({
// reset our buy state
dispatch(actions.updateSelectedAssetBuyState(AsyncProcessState.NONE));
// tslint:disable-next-line:no-floating-promises
debouncedUpdateBuyQuote(dispatch, value);
debouncedUpdateBuyQuoteAsync(dispatch, assetData, value);
},
});
export const SelectedAssetAmountInput: React.ComponentClass<SelectedAssetAmountInputProps> = connect(
mapStateToProps,
mapDispatchToProps,
)(AmountInput);
)(AssetAmountInput);

View File

@@ -0,0 +1,15 @@
import { AssetProxyId, ObjectMap } from '@0xproject/types';
import { zrxAssetData } from '../constants';
import { AssetMetaData } from '../types';
// Map from assetData string to AssetMetaData object
// TODO: import this from somewhere else.
export const assetMetaData: ObjectMap<AssetMetaData> = {
[zrxAssetData]: {
assetProxyId: AssetProxyId.ERC20,
decimals: 18,
primaryColor: 'rgb(54, 50, 60)',
symbol: 'zrx',
},
};

View File

@@ -2,11 +2,13 @@ import { BuyQuote } from '@0xproject/asset-buyer';
import { BigNumber } from '@0xproject/utils';
import * as _ from 'lodash';
import { zrxAssetData } from '../constants';
import { AsyncProcessState } from '../types';
import { Action, ActionTypes } from './actions';
export interface State {
selectedAssetData?: string;
selectedAssetAmount?: BigNumber;
selectedAssetBuyState: AsyncProcessState;
ethUsdPrice?: BigNumber;
@@ -14,9 +16,11 @@ export interface State {
}
export const INITIAL_STATE: State = {
ethUsdPrice: undefined,
selectedAssetBuyState: AsyncProcessState.NONE,
// TODO: Remove hardcoded zrxAssetData
selectedAssetData: zrxAssetData,
selectedAssetAmount: undefined,
selectedAssetBuyState: AsyncProcessState.NONE,
ethUsdPrice: undefined,
latestBuyQuote: undefined,
};

View File

@@ -1,4 +1,4 @@
import { ObjectMap } from '@0xproject/types';
import { AssetProxyId, ObjectMap } from '@0xproject/types';
// Reusable
export enum AsyncProcessState {
@@ -11,3 +11,23 @@ export enum AsyncProcessState {
export type FunctionType = (...args: any[]) => any;
export type ActionCreatorsMapObject = ObjectMap<FunctionType>;
export type ActionsUnion<A extends ActionCreatorsMapObject> = ReturnType<A[keyof A]>;
export interface ERC20AssetMetaData {
assetProxyId: AssetProxyId.ERC20;
decimals: number;
primaryColor?: string;
symbol: string;
}
export interface ERC721AssetMetaData {
assetProxyId: AssetProxyId.ERC721;
name: string;
primaryColor?: string;
}
export type AssetMetaData = ERC20AssetMetaData | ERC721AssetMetaData;
export enum Network {
Kovan = 42,
Mainnet = 1,
}

View File

@@ -5602,6 +5602,21 @@ ethers@3.0.22:
uuid "2.0.1"
xmlhttprequest "1.8.0"
ethers@4.0.0-beta.14:
version "4.0.0-beta.14"
resolved "https://registry.npmjs.org/ethers/-/ethers-4.0.0-beta.14.tgz#76aa9257b9c93a7604ff4dc11f2a445d07f6459d"
dependencies:
"@types/node" "^10.3.2"
aes-js "3.0.0"
bn.js "^4.4.0"
elliptic "6.3.3"
hash.js "1.1.3"
js-sha3 "0.5.7"
scrypt-js "2.0.3"
setimmediate "1.0.4"
uuid "2.0.1"
xmlhttprequest "1.8.0"
ethers@~4.0.4:
version "4.0.4"
resolved "https://registry.yarnpkg.com/ethers/-/ethers-4.0.4.tgz#d3f85e8b27f4b59537e06526439b0fb15b44dc65"