feat: model asset meta data and add dynamic assetData state
This commit is contained in:
@@ -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",
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
}
|
||||
|
||||
51
packages/instant/src/components/asset_amount_input.tsx
Normal file
51
packages/instant/src/components/asset_amount_input.tsx
Normal 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);
|
||||
};
|
||||
}
|
||||
@@ -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}>
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
15
packages/instant/src/data/asset_meta_data.ts
Normal file
15
packages/instant/src/data/asset_meta_data.ts
Normal 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',
|
||||
},
|
||||
};
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
|
||||
15
yarn.lock
15
yarn.lock
@@ -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"
|
||||
|
||||
Reference in New Issue
Block a user