mirror of https://github.com/certusone/oyster.git
Added modal to select token chain
This commit is contained in:
parent
979a369f6a
commit
b3a0dabf4b
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
</>
|
||||
);
|
||||
};
|
|
@ -0,0 +1,7 @@
|
|||
.input-token-search {
|
||||
margin: 20px 0 20px 0;
|
||||
}
|
||||
.assets-scroll {
|
||||
height: 60vh;
|
||||
overflow: auto;
|
||||
}
|
|
@ -52,7 +52,7 @@ export const Transfer = () => {
|
|||
asset: tokens?.[0]?.address,
|
||||
});
|
||||
}
|
||||
}, [request, tokens, setRequest])
|
||||
}, [request, tokens, setRequest]);
|
||||
|
||||
const setAssetInformation = async (asset: string) => {
|
||||
setRequest({
|
||||
|
@ -87,9 +87,10 @@ export const Transfer = () => {
|
|||
address: asset,
|
||||
name: symbol,
|
||||
balance: balance,
|
||||
balanceAsNumber: (new BN(balance.toString())
|
||||
balanceAsNumber:
|
||||
new BN(balance.toString())
|
||||
.div(new BN(10).pow(new BN(decimals - 2)))
|
||||
.toNumber()) / 100,
|
||||
.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 (
|
||||
<>
|
||||
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue