From 053a85da387160a06a522c2537a0217994d0984a Mon Sep 17 00:00:00 2001 From: Gary Wang Date: Thu, 17 Sep 2020 23:55:14 -0700 Subject: [PATCH] Allow adding erc20 tokens via contract address --- src/components/AddTokenDialog.js | 99 ++++++++++++++++++++++++-------- src/utils/tokens/names.js | 9 +++ 2 files changed, 83 insertions(+), 25 deletions(-) diff --git a/src/components/AddTokenDialog.js b/src/components/AddTokenDialog.js index ff6e1ce..9b5eae5 100644 --- a/src/components/AddTokenDialog.js +++ b/src/components/AddTokenDialog.js @@ -30,6 +30,8 @@ import { import Link from '@material-ui/core/Link'; import CopyableDisplay from './CopyableDisplay'; import DialogForm from './DialogForm'; +import { showSwapAddress } from '../utils/config'; +import { swapApiRequest } from '../utils/swap/api'; const feeFormat = new Intl.NumberFormat(undefined, { minimumFractionDigits: 6, @@ -40,7 +42,6 @@ const useStyles = makeStyles((theme) => ({ tabs: { marginBottom: theme.spacing(1), borderBottom: `1px solid ${theme.palette.background.paper}`, - width: '100%', }, })); @@ -52,15 +53,16 @@ export default function AddTokenDialog({ open, onClose }) { ); let classes = useStyles(); let updateTokenName = useUpdateTokenName(); - - let [mintAddress, setMintAddress] = useState(''); - let [tokenName, setTokenName] = useState(''); - let [tokenSymbol, setTokenSymbol] = useState(''); - let [sendTransaction, sending] = useSendTransaction(); + const [sendTransaction, sending] = useSendTransaction(); const { endpoint } = useConnectionConfig(); const popularTokens = TOKENS[endpoint]; const [walletAccounts] = useWalletTokenAccounts(); + const [tab, setTab] = useState(!!popularTokens ? 'popular' : 'manual'); + const [mintAddress, setMintAddress] = useState(''); + const [tokenName, setTokenName] = useState(''); + const [tokenSymbol, setTokenSymbol] = useState(''); + const [erc20Address, setErc20Address] = useState(''); useEffect(() => { if (!popularTokens) { @@ -68,17 +70,46 @@ export default function AddTokenDialog({ open, onClose }) { } }, [popularTokens]); - function onSubmit({ mintAddress, tokenName, tokenSymbol }) { - let mint = new PublicKey(mintAddress); - sendTransaction(wallet.createTokenAccount(mint), { + function onSubmit(params) { + if (tab === 'manual') { + params = { mintAddress, tokenName, tokenSymbol }; + } else if (tab === 'erc20') { + params = { erc20Address }; + } + sendTransaction(addToken(params), { onSuccess: () => { - updateTokenName(mint, tokenName, tokenSymbol); refreshWalletPublicKeys(wallet); onClose(); }, }); } + async function addToken({ + mintAddress, + tokenName, + tokenSymbol, + erc20Address, + }) { + if (erc20Address) { + let tokenInfo = await swapApiRequest('POST', `coins/eth/${erc20Address}`); + mintAddress = tokenInfo.splMint; + tokenName = tokenInfo.name; + tokenSymbol = tokenInfo.ticker; + if (tokenInfo.blockchain !== 'sol') { + tokenName = 'Wrapped ' + tokenName; + } + } + + let mint = new PublicKey(mintAddress); + updateTokenName(mint, tokenName, tokenSymbol); + return await wallet.createTokenAccount(mint); + } + + let valid = true; + if (tab === 'erc20') { + valid = erc20Address.length === 42 && erc20Address.startsWith('0x'); + } + return ( Add Token @@ -94,22 +125,14 @@ export default function AddTokenDialog({ open, onClose }) { {!!popularTokens && ( setTab(value)} > - - + + {showSwapAddress ? : null} + )} {tab === 'manual' || !popularTokens ? ( @@ -121,6 +144,8 @@ export default function AddTokenDialog({ open, onClose }) { margin="normal" value={mintAddress} onChange={(e) => setMintAddress(e.target.value)} + autoFocus + disabled={sending} /> setTokenName(e.target.value)} + disabled={sending} /> setTokenSymbol(e.target.value)} + disabled={sending} /> - ) : ( + ) : tab === 'popular' ? ( {popularTokens.map((token) => ( ))} - )} + ) : tab === 'erc20' ? ( + <> + setErc20Address(e.target.value.trim())} + autoFocus + disabled={sending} + /> + {erc20Address && valid ? ( + + View on Etherscan + + ) : null} + + ) : null} - {tab === 'manual' && ( + {tab !== 'popular' && (