Added modal to select token chain

This commit is contained in:
juan 2021-03-10 11:36:22 -05:00
parent 979a369f6a
commit b3a0dabf4b
5 changed files with 137 additions and 61 deletions

View File

@ -1,12 +1,9 @@
import React, { useState } from 'react';
import { NumericInput } from '@oyster/common';
import { Card, Select } from 'antd';
import { Card } from 'antd';
import './style.less';
import { useEthereum } from '../../contexts';
import { TokenDisplay } from '../TokenDisplay';
import { ASSET_CHAIN } from '../../models/bridge/constants';
const { Option } = Select;
import { TokenSelectModal } from '../TokenSelectModal';
export function Input(props: {
title: string;
@ -18,33 +15,6 @@ export function Input(props: {
onInputChange: (value: number | undefined) => void;
}) {
const [lastAmount, setLastAmount] = useState<string>('');
const { tokens } = useEthereum();
const renderReserveAccounts = tokens
.filter(t => (t.tags?.indexOf('longList') || -1) < 0)
.map(token => {
const mint = token.address;
return (
<Option
key={mint}
className="multichain-option"
value={mint}
name={token.symbol}
title={token.name}
>
<div className="multichain-option-content">
<TokenDisplay
asset={props.asset}
token={token}
chain={props.chain}
/>
<div className="multichain-option-name">
<span className={'token-name'}>{token.symbol}</span>
</div>
</div>
</Option>
);
});
return (
<Card
@ -58,7 +28,9 @@ export function Input(props: {
{!!props.balance && (
<div
className="ccy-input-header-right"
onClick={() => props.onInputChange && props.onInputChange(props.balance)}
onClick={() =>
props.onInputChange && props.onInputChange(props.balance)
}
>
Balance: {props.balance.toFixed(6)}
</div>
@ -90,21 +62,11 @@ export function Input(props: {
placeholder="0.00"
/>
<div className="ccy-input-header-right" style={{ display: 'flex' }}>
<Select
size="large"
showSearch
style={{ minWidth: 150 }}
placeholder="CCY"
value={props.asset}
onChange={(item: string) => {
props.setAsset(item);
}}
filterOption={(input, option) =>
option?.name?.toLowerCase().indexOf(input.toLowerCase()) >= 0
}
>
{renderReserveAccounts}
</Select>
<TokenSelectModal
onSelectToken={token => props.setAsset(token)}
asset={props.asset}
chain={props.chain}
/>
</div>
</div>
</Card>

View File

@ -0,0 +1,104 @@
import React, { useMemo, useState } from 'react';
import './style.less';
import { Modal, Input } from 'antd';
import { useEthereum } from '../../contexts';
import { TokenDisplay } from '../TokenDisplay';
import { ASSET_CHAIN } from '../../models/bridge/constants';
export const TokenSelectModal = (props: {
onSelectToken: (token: string) => void;
asset?: string;
chain?: ASSET_CHAIN;
}) => {
const { tokens } = useEthereum();
const [isModalVisible, setIsModalVisible] = useState<boolean>(false);
const [selected, setSelected] = useState<string>('');
const [search, setSearch] = useState<string>('');
const showModal = () => {
setIsModalVisible(true);
};
const hideModal = () => {
setIsModalVisible(false);
};
const firstToken = useMemo(() => {
if (!selected) {
return tokens.find(el => el.address === props.asset);
}
return tokens.find(el => el.address === selected);
}, [selected, tokens, props.asset]);
const renderTokensChain = useMemo(() => {
return tokens
.filter(
t =>
(t.tags?.indexOf('longList') || -1) < 0 &&
search &&
search.length >= 3 &&
t.symbol.includes(search.toUpperCase()),
)
.map(token => {
const mint = token.address;
return (
<div
key={mint}
className="multichain-option"
title={token.name}
onClick={() => {
props.onSelectToken(mint);
setSelected(mint);
hideModal();
}}
style={{ cursor: 'pointer' }}
>
<div className="multichain-option-content">
<TokenDisplay
asset={props.asset}
token={token}
chain={props.chain}
/>
<div className="multichain-option-name">
<span className={'token-name'}>{token.symbol}</span>
</div>
</div>
</div>
);
});
}, [search, tokens]);
return (
<>
{firstToken ? (
<div
key={firstToken.address}
className="multichain-option"
title={firstToken.name}
onClick={() => showModal()}
style={{ cursor: 'pointer' }}
>
<div className="multichain-option-content">
<TokenDisplay
asset={props.asset}
token={firstToken}
chain={props.chain}
/>
</div>
</div>
) : null}
<Modal
visible={isModalVisible}
onCancel={() => hideModal()}
footer={null}
>
<Input
className={'input-token-search'}
placeholder={'ETH, SOL, ... etc'}
value={search}
onChange={e => setSearch(e.target.value)}
/>
<div className={'assets-scroll'}>{[...renderTokensChain]}</div>
</Modal>
</>
);
};

View File

@ -0,0 +1,7 @@
.input-token-search {
margin: 20px 0 20px 0;
}
.assets-scroll {
height: 60vh;
overflow: auto;
}

View File

@ -46,13 +46,13 @@ export const Transfer = () => {
});
useEffect(() => {
if(tokens && !request.asset) {
if (tokens && !request.asset) {
setRequest({
...request,
asset: tokens?.[0]?.address,
});
}
}, [request, tokens, setRequest])
}, [request, tokens, setRequest]);
const setAssetInformation = async (asset: string) => {
setRequest({
@ -63,7 +63,7 @@ export const Transfer = () => {
useEffect(() => {
const asset = request.asset;
if(!asset || asset === request?.info?.address) {
if (!asset || asset === request?.info?.address) {
return;
}
@ -87,9 +87,10 @@ export const Transfer = () => {
address: asset,
name: symbol,
balance: balance,
balanceAsNumber: (new BN(balance.toString())
.div(new BN(10).pow(new BN(decimals - 2)))
.toNumber()) / 100,
balanceAsNumber:
new BN(balance.toString())
.div(new BN(10).pow(new BN(decimals - 2)))
.toNumber() / 100,
allowance: allowance,
decimals: decimals,
isWrapped: false,
@ -103,7 +104,10 @@ export const Transfer = () => {
let isWrapped = await b.isWrappedAsset(asset);
if (isWrapped) {
info.chainID = await e.assetChain();
info.assetAddress = Buffer.from((await e.assetAddress()).slice(2), 'hex');
info.assetAddress = Buffer.from(
(await e.assetAddress()).slice(2),
'hex',
);
info.isWrapped = true;
}
@ -113,7 +117,7 @@ export const Transfer = () => {
info,
});
})();
}, [request, provider])
}, [request, provider]);
return (
<>
@ -122,7 +126,7 @@ export const Transfer = () => {
title={`From ${chainToName(request.from)}`}
asset={request.asset}
chain={request.from}
balance={request.info?.balanceAsNumber || 0 }
balance={request.info?.balanceAsNumber || 0}
setAsset={asset => setAssetInformation(asset)}
amount={request.amount}
onInputChange={amount => {
@ -179,7 +183,7 @@ export const Transfer = () => {
(async () => {
let steps: ProgressUpdate[] = [];
try {
if(request.toChain === ASSET_CHAIN.Solana) {
if (request.toChain === ASSET_CHAIN.Solana) {
await toSolana(
connection,
wallet,
@ -211,8 +215,7 @@ export const Transfer = () => {
request.toChain,
)} Mainnet`}</h5>
<h2>
{request.amount?.toString()}{' '}
{request.info?.name}
{request.amount?.toString()} {request.info?.name}
</h2>
</div>
<div

View File

@ -93,7 +93,7 @@ export const EthereumProvider: FunctionComponent = ({ children }) => {
window.ethereum.enable();
// @ts-ignore
const provider = new ethers.providers.Web3Provider(
(window as any).ethereum ,
(window as any).ethereum,
);
const signer = provider.getSigner();
signer.getAddress().then(account => setAccounts([account]));