utils#getEtherscanLink TypeScript Examples
The following examples show how to use
utils#getEtherscanLink.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: Transaction.tsx From interface-v2 with GNU General Public License v3.0 | 6 votes |
Transaction: React.FC<TransactionProps> = ({ hash }) => {
const classes = useStyles();
const { chainId } = useActiveWeb3React();
const allTransactions = useAllTransactions();
const tx = allTransactions?.[hash];
const summary = tx?.summary;
const pending = !tx?.confirmedTime;
const success =
!pending &&
tx &&
tx.receipt &&
(tx.receipt.status === 1 || typeof tx.receipt.status === 'undefined');
if (!chainId) return null;
return (
<Box className={classes.transactionState}>
<a
className={classes.transactionStatusText}
href={getEtherscanLink(chainId, hash, 'transaction')}
target='_blank'
rel='noopener noreferrer'
>
{summary ?? hash} ↗
</a>
<Box className={classes.iconWrapper}>
{pending ? (
<CircularProgress size={16} />
) : success ? (
<CheckCircle size='16' />
) : (
<Triangle size='16' />
)}
</Box>
</Box>
);
}
Example #2
Source File: AddressInput.tsx From interface-v2 with GNU General Public License v3.0 | 6 votes |
AddressInput: React.FC<AddressInputProps> = ({
value,
onChange,
placeholder,
label,
}) => {
const { chainId } = useActiveWeb3React();
const { address, loading, name } = useENS(value);
const error = Boolean(value.length > 0 && !loading && !address);
const classes = useStyles({ error });
return (
<Box className={classes.addressInput}>
<Box display='flex' justifyContent='space-between' alignItems='center'>
<Typography>{label}</Typography>
{address && chainId && (
<a
href={getEtherscanLink(chainId, name ?? address, 'address')}
target='_blank'
rel='noopener noreferrer'
>
(View on Block Explorer)
</a>
)}
</Box>
<input
value={value}
placeholder={placeholder}
onChange={(evt) => {
const input = evt.target.value;
const withoutSpaces = input.replace(/\s+/g, '');
onChange(withoutSpaces);
}}
/>
</Box>
);
}
Example #3
Source File: TransactionConfirmationModal.tsx From interface-v2 with GNU General Public License v3.0 | 5 votes |
TransactionSubmittedContent: React.FC<TransactionSubmittedContentProps> = ({
onDismiss,
chainId,
hash,
txPending,
modalContent,
}) => {
const classes = useStyles();
return (
<Box padding={4}>
<Box className={classes.modalHeader}>
<Typography variant='h5'>
Transaction {txPending ? 'Submitted' : 'Completed'}
</Typography>
<CloseIcon onClick={onDismiss} />
</Box>
{!txPending && (
<Box mt={8} display='flex' justifyContent='center'>
<TransactionSuccess />
</Box>
)}
<Box className={classes.modalContent}>
<Typography variant='body1'>{modalContent}</Typography>
</Box>
<Box display='flex' justifyContent='space-between' mt={2}>
{chainId && hash && (
<a
href={getEtherscanLink(chainId, hash, 'transaction')}
target='_blank'
rel='noopener noreferrer'
style={{ width: '48%', textDecoration: 'none' }}
>
<Button className={classes.submitButton}>
View on Block Explorer
</Button>
</a>
)}
<Button
className={classes.submitButton}
style={{ width: '48%' }}
onClick={onDismiss}
>
Close
</Button>
</Box>
</Box>
);
}
Example #4
Source File: RecentTransactionsModal.tsx From goose-frontend-amm with GNU General Public License v3.0 | 5 votes |
RecentTransactionsModal = ({ onDismiss = defaultOnDismiss }: RecentTransactionsModalProps) => {
const { account, chainId } = useActiveWeb3React()
const allTransactions = useAllTransactions()
// Logic taken from Web3Status/index.tsx line 175
const sortedRecentTransactions = useMemo(() => {
const txs = Object.values(allTransactions)
return txs.filter(isTransactionRecent).sort(newTransactionsFirst)
}, [allTransactions])
return (
<Modal title="Recent Transactions" onDismiss={onDismiss}>
{!account && (
<Flex justifyContent="center" flexDirection="column" alignItems="center">
<Text mb="8px" bold>
Please connect your wallet to view your recent transactions
</Text>
<Button variant="tertiary" size="sm" onClick={onDismiss}>
Close
</Button>
</Flex>
)}
{account && chainId && sortedRecentTransactions.length === 0 && (
<Flex justifyContent="center" flexDirection="column" alignItems="center">
<Text mb="8px" bold>
No recent transactions
</Text>
<Button variant="tertiary" size="sm" onClick={onDismiss}>
Close
</Button>
</Flex>
)}
{account &&
chainId &&
sortedRecentTransactions.map((sortedRecentTransaction) => {
const { hash, summary } = sortedRecentTransaction
const { icon, color } = getRowStatus(sortedRecentTransaction)
return (
<>
<Flex key={hash} alignItems="center" justifyContent="space-between" mb="4px">
<LinkExternal href={getEtherscanLink(chainId, hash, 'transaction')} color={color}>
{summary ?? hash}
</LinkExternal>
{icon}
</Flex>
</>
)
})}
</Modal>
)
}
Example #5
Source File: UnsupportedCurrencyFooter.tsx From forward.swaps with GNU General Public License v3.0 | 5 votes |
export default function UnsupportedCurrencyFooter({ show, currencies }: { show: boolean currencies: (Currency | undefined)[] }) { const { chainId } = useActiveWeb3React() const [showDetails, setShowDetails] = useState(false) const tokens = chainId && currencies ? currencies.map(currency => { return wrappedCurrency(currency, chainId) }) : [] const unsupportedTokens: { [address: string]: Token } = useUnsupportedTokens() return ( <DetailsFooter show={show}> <Modal isOpen={showDetails} onDismiss={() => setShowDetails(false)}> <Card padding="2rem"> <AutoColumn gap="lg"> <RowBetween> <TYPE.mediumHeader>Unsupported Assets</TYPE.mediumHeader> <CloseIcon onClick={() => setShowDetails(false)} /> </RowBetween> {tokens.map(token => { return ( token && unsupportedTokens && Object.keys(unsupportedTokens).includes(token.address) && ( <OutlineCard key={token.address?.concat('not-supported')}> <AutoColumn gap="10px"> <AutoRow gap="5px" align="center"> <CurrencyLogo currency={token} size={'24px'} /> <TYPE.body fontWeight={500}>{token.symbol}</TYPE.body> </AutoRow> {chainId && ( <ExternalLink href={getEtherscanLink(chainId, token.address, 'address')}> <AddressText>{token.address}</AddressText> </ExternalLink> )} </AutoColumn> </OutlineCard> ) ) })} <AutoColumn gap="lg"> <TYPE.body fontWeight={500}> Some assets are not available through this interface because they may not work well with our smart contract or we are unable to allow trading for legal reasons. </TYPE.body> </AutoColumn> </AutoColumn> </Card> </Modal> <ButtonEmpty padding={'0'} onClick={() => setShowDetails(true)}> <TYPE.blue>Read more about unsupported assets</TYPE.blue> </ButtonEmpty> </DetailsFooter> ) }
Example #6
Source File: AccountDetails.tsx From interface-v2 with GNU General Public License v3.0 | 4 votes |
AccountDetails: React.FC<AccountDetailsProps> = ({
toggleWalletModal,
pendingTransactions,
confirmedTransactions,
ENSName,
openOptions,
}) => {
const { chainId, account, connector } = useActiveWeb3React();
const classes = useStyles();
const { palette } = useTheme();
const dispatch = useDispatch<AppDispatch>();
function formatConnectorName() {
const { ethereum } = window as any;
const isMetaMask = !!(
ethereum &&
!ethereum.isBitKeep &&
ethereum.isMetaMask
);
const isBitkeep = !!(ethereum && ethereum.isBitKeep);
const isBlockWallet = !!(ethereum && ethereum.isBlockWallet);
const name = Object.keys(SUPPORTED_WALLETS)
.filter(
(k) =>
SUPPORTED_WALLETS[k].connector === connector &&
(connector !== injected ||
(isBlockWallet && k === 'BLOCKWALLET') ||
(isBitkeep && k === 'BITKEEP') ||
(isMetaMask && k === 'METAMASK')),
)
.map((k) => SUPPORTED_WALLETS[k].name)[0];
return <Typography variant='body2'>Connected with {name}</Typography>;
}
const clearAllTransactionsCallback = useCallback(() => {
if (chainId) dispatch(clearAllTransactions({ chainId }));
}, [dispatch, chainId]);
return (
<Box paddingX={3} paddingY={4}>
<Box display='flex' justifyContent='space-between'>
<Typography variant='h5'>Account</Typography>
<Close style={{ cursor: 'pointer' }} onClick={toggleWalletModal} />
</Box>
<Box
mt={2}
padding={2}
borderRadius={10}
bgcolor={palette.secondary.dark}
>
<Box display='flex' justifyContent='space-between' alignItems='center'>
{formatConnectorName()}
<Box display='flex' alignItems='center'>
{connector !== injected &&
connector !== walletlink &&
connector !== safeApp && (
<Typography
style={{ cursor: 'pointer', marginRight: 8 }}
onClick={() => {
(connector as any).close();
}}
variant='body2'
>
Disconnect
</Typography>
)}
{connector !== safeApp && (
<Typography
style={{ cursor: 'pointer' }}
onClick={() => {
openOptions();
}}
variant='body2'
>
Change
</Typography>
)}
</Box>
</Box>
<Box display='flex' alignItems='center' my={1.5}>
<StatusIcon />
<Typography
variant='h5'
style={{ marginLeft: 8 }}
id='web3-account-identifier-row'
>
{ENSName ? ENSName : account && shortenAddress(account)}
</Typography>
</Box>
<Box display='flex' justifyContent='space-between' alignItems='center'>
{account && (
<Copy toCopy={account}>
<span style={{ marginLeft: '4px' }}>Copy Address</span>
</Copy>
)}
{chainId && account && (
<a
className={classes.addressLink}
href={
chainId &&
getEtherscanLink(
chainId,
ENSName ? ENSName : account,
'address',
)
}
target='_blank'
rel='noopener noreferrer'
>
<LinkIcon size={16} />
<Typography variant='body2'>View on Block Explorer</Typography>
</a>
)}
</Box>
</Box>
{!!pendingTransactions.length || !!confirmedTransactions.length ? (
<>
<Box
display='flex'
justifyContent='space-between'
alignItems='center'
paddingX={2}
pt={2}
mb={1}
>
<Typography variant='body2'>Recent Transactions</Typography>
<Typography
variant='body2'
style={{ cursor: 'pointer' }}
onClick={clearAllTransactionsCallback}
>
Clear all
</Typography>
</Box>
<Box paddingX={2} flex={1} overflow='auto'>
{renderTransactions(pendingTransactions)}
{renderTransactions(confirmedTransactions)}
</Box>
</>
) : (
<Box paddingX={2} pt={2}>
<Typography variant='body2'>
Your transactions will appear here...
</Typography>
</Box>
)}
</Box>
);
}
Example #7
Source File: TransactionsTable.tsx From interface-v2 with GNU General Public License v3.0 | 4 votes |
TransactionsTable: React.FC<TransactionsTableProps> = ({ data }) => {
const [txFilter, setTxFilter] = useState(-1);
const txHeadCells = headCells(txFilter, setTxFilter);
const classes = useStyles();
const { chainId } = useActiveWeb3React();
const { palette, breakpoints } = useTheme();
const isMobile = useMediaQuery(breakpoints.down('xs'));
const { t } = useTranslation();
const getTxString = (txn: any) => {
const messageData = {
token0Symbol: txn.pair.token1.symbol,
token1Symbol: txn.pair.token0.symbol,
};
if (txn.type === TxnType.SWAP) {
return t('txnSwapMessage', messageData);
} else if (txn.type === TxnType.ADD) {
return t('txnAddMessage', messageData);
} else if (txn.type === TxnType.REMOVE) {
return t('txnRemoveMessage', messageData);
}
return '';
};
const mobileHTML = (txn: any, index: number) => {
return (
<Box mt={index === 0 ? 0 : 3} key={index}>
<Box mb={1}>
{chainId ? (
<a
href={getEtherscanLink(
chainId,
txn.transaction.id,
'transaction',
)}
target='_blank'
rel='noopener noreferrer'
style={{ textDecoration: 'none' }}
>
<Typography
variant='body1'
style={{ color: palette.primary.main }}
>
{getTxString(txn)}
</Typography>
</a>
) : (
<Typography variant='body1' style={{ color: palette.primary.main }}>
{getTxString(txn)}
</Typography>
)}
</Box>
<Divider />
<Box className={classes.mobileRow}>
<Typography variant='body1'>Total Value</Typography>
<Typography variant='body1' color='textPrimary'>
${Number(txn.amountUSD).toLocaleString()}
</Typography>
</Box>
<Box className={classes.mobileRow}>
<Typography variant='body1'>Token Amount</Typography>
<Typography variant='body1' color='textPrimary'>
{formatNumber(txn.amount0)} {txn.pair.token0.symbol}
</Typography>
</Box>
<Box className={classes.mobileRow}>
<Typography variant='body1'>Token Amount</Typography>
<Typography variant='body1' color='textPrimary'>
{formatNumber(txn.amount1)} {txn.pair.token1.symbol}
</Typography>
</Box>
<Box className={classes.mobileRow}>
<Typography variant='body1'>TXN</Typography>
{chainId ? (
<a
href={getEtherscanLink(
chainId,
txn.transaction.id,
'transaction',
)}
target='_blank'
rel='noopener noreferrer'
style={{ textDecoration: 'none' }}
>
<Typography
variant='body1'
style={{ color: palette.primary.main }}
>
{shortenTx(txn.transaction.id)}
</Typography>
</a>
) : (
<Typography variant='body1' style={{ color: palette.primary.main }}>
{shortenTx(txn.transaction.id)}
</Typography>
)}
</Box>
<Box className={classes.mobileRow}>
<Typography variant='body1'>Time</Typography>
<Typography variant='body1' color='textPrimary'>
{dayjs(Number(txn.transaction.timestamp) * 1000).fromNow()}
</Typography>
</Box>
</Box>
);
};
const desktopHTML = (txn: any) => {
return [
{
html: chainId ? (
<a
href={getEtherscanLink(chainId, txn.transaction.id, 'transaction')}
target='_blank'
rel='noopener noreferrer'
style={{ textDecoration: 'none' }}
>
<Typography variant='body1' style={{ color: palette.primary.main }}>
{getTxString(txn)}
</Typography>
</a>
) : (
<Typography variant='body1' style={{ color: palette.primary.main }}>
{getTxString(txn)}
</Typography>
),
},
{
html: (
<Typography variant='body1' color='textPrimary'>
${Number(txn.amountUSD).toLocaleString()}
</Typography>
),
},
{
html: (
<Typography variant='body1' color='textPrimary'>
{formatNumber(txn.amount1)} {txn.pair.token1.symbol}
</Typography>
),
},
{
html: (
<Typography variant='body1' color='textPrimary'>
{formatNumber(txn.amount0)} {txn.pair.token0.symbol}
</Typography>
),
},
{
html: chainId ? (
<a
href={getEtherscanLink(chainId, txn.transaction.id, 'transaction')}
target='_blank'
rel='noopener noreferrer'
style={{ textDecoration: 'none' }}
>
<Typography variant='body1' style={{ color: palette.primary.main }}>
{shortenTx(txn.transaction.id)}
</Typography>
</a>
) : (
<Typography variant='body1' style={{ color: palette.primary.main }}>
{shortenTx(txn.transaction.id)}
</Typography>
),
},
{
html: (
<Typography variant='body1' color='textPrimary'>
{dayjs(Number(txn.transaction.timestamp) * 1000).fromNow()}
</Typography>
),
},
];
};
return (
<Box position='relative'>
{isMobile && (
<Box
display='flex'
alignItems='center'
position='absolute'
top={-48}
right={0}
>
<Box padding={1} onClick={() => setTxFilter(-1)}>
<Typography
variant='body1'
color={txFilter === -1 ? 'textPrimary' : 'textSecondary'}
>
All
</Typography>
</Box>
<Box padding={1} onClick={() => setTxFilter(TxnType.SWAP)}>
<Typography
variant='body1'
color={
txFilter === TxnType.SWAP ? 'textPrimary' : 'textSecondary'
}
>
Swap
</Typography>
</Box>
<Box padding={1} onClick={() => setTxFilter(TxnType.ADD)}>
<Typography
variant='body1'
color={txFilter === TxnType.ADD ? 'textPrimary' : 'textSecondary'}
>
Add
</Typography>
</Box>
<Box padding={1} onClick={() => setTxFilter(TxnType.REMOVE)}>
<Typography
variant='body1'
color={
txFilter === TxnType.REMOVE ? 'textPrimary' : 'textSecondary'
}
>
Remove
</Typography>
</Box>
</Box>
)}
<CustomTable
showPagination={data.length > 10}
headCells={txHeadCells}
defaultOrderBy={txHeadCells[5]}
rowsPerPage={10}
data={data.filter((item) =>
txFilter === -1 ? true : item.type === txFilter,
)}
mobileHTML={mobileHTML}
desktopHTML={desktopHTML}
/>
</Box>
);
}
Example #8
Source File: AnalyticsPairDetails.tsx From interface-v2 with GNU General Public License v3.0 | 4 votes |
AnalyticsPairDetails: React.FC = () => {
const classes = useStyles();
const { palette, breakpoints } = useTheme();
const isMobile = useMediaQuery(breakpoints.down('xs'));
const history = useHistory();
const match = useRouteMatch<{ id: string }>();
const pairAddress = match.params.id;
const [pairData, setPairData] = useState<any>(null);
const [pairTransactions, setPairTransactions] = useState<any>(null);
const pairTransactionsList = useMemo(() => {
if (pairTransactions) {
const mints = pairTransactions.mints.map((item: any) => {
return { ...item, type: TxnType.ADD };
});
const swaps = pairTransactions.swaps.map((item: any) => {
const amount0 = item.amount0Out > 0 ? item.amount0Out : item.amount1Out;
const amount1 = item.amount0In > 0 ? item.amount0In : item.amount1In;
const token0 =
item.amount0Out > 0 ? item.pair.token0 : item.pair.token1;
const token1 =
item.amount0Out > 0 ? item.pair.token1 : item.pair.token0;
return {
...item,
amount0,
amount1,
pair: { token0, token1 },
type: TxnType.SWAP,
};
});
const burns = pairTransactions.burns.map((item: any) => {
return { ...item, type: TxnType.REMOVE };
});
return mints.concat(swaps).concat(burns);
} else {
return null;
}
}, [pairTransactions]);
const { chainId } = useActiveWeb3React();
const currency0 = pairData
? new Token(
ChainId.MATIC,
getAddress(pairData.token0.id),
pairData.token0.decimals,
)
: undefined;
const currency1 = pairData
? new Token(
ChainId.MATIC,
getAddress(pairData.token1.id),
pairData.token1.decimals,
)
: undefined;
const token0Rate =
pairData && pairData.reserve0 && pairData.reserve1
? Number(pairData.reserve1) / Number(pairData.reserve0) >= 0.0001
? (Number(pairData.reserve1) / Number(pairData.reserve0)).toFixed(
Number(pairData.reserve1) / Number(pairData.reserve0) > 1 ? 2 : 4,
)
: '< 0.0001'
: '-';
const token1Rate =
pairData && pairData.reserve0 && pairData.reserve1
? Number(pairData.reserve0) / Number(pairData.reserve1) >= 0.0001
? (Number(pairData.reserve0) / Number(pairData.reserve1)).toFixed(
Number(pairData.reserve0) / Number(pairData.reserve1) > 1 ? 2 : 4,
)
: '< 0.0001'
: '-';
const usingUtVolume =
pairData &&
pairData.oneDayVolumeUSD === 0 &&
!!pairData.oneDayVolumeUntracked;
const fees =
pairData && (pairData.oneDayVolumeUSD || pairData.oneDayVolumeUSD === 0)
? usingUtVolume
? (
Number(pairData.oneDayVolumeUntracked) *
GlobalConst.utils.FEEPERCENT
).toLocaleString()
: (
Number(pairData.oneDayVolumeUSD) * GlobalConst.utils.FEEPERCENT
).toLocaleString()
: '-';
useEffect(() => {
async function checkEthPrice() {
const [newPrice] = await getEthPrice();
const pairInfo = await getBulkPairData([pairAddress], newPrice);
if (pairInfo && pairInfo.length > 0) {
setPairData(pairInfo[0]);
}
}
async function fetchTransctions() {
const transactions = await getPairTransactions(pairAddress);
if (transactions) {
setPairTransactions(transactions);
}
}
checkEthPrice();
fetchTransctions();
}, [pairAddress]);
return (
<>
<AnalyticsHeader type='pair' data={pairData} />
{pairData ? (
<>
<Box
width={1}
display='flex'
flexWrap='wrap'
justifyContent='space-between'
>
<Box>
<Box display='flex' alignItems='center'>
<DoubleCurrencyLogo
currency0={currency0}
currency1={currency1}
size={32}
/>
<Box ml={1}>
<Typography className={classes.heading2}>
<Link to={`/analytics/token/${pairData.token0.id}`}>
{pairData.token0.symbol}
</Link>{' '}
/{' '}
<Link to={`/analytics/token/${pairData.token1.id}`}>
{pairData.token1.symbol}
</Link>
</Typography>
</Box>
</Box>
<Box mt={2} display='flex'>
<Box
paddingY={0.75}
paddingX={1.5}
borderRadius={20}
display='flex'
alignItems='center'
bgcolor={palette.grey.A700}
>
<CurrencyLogo currency={currency0} size='16px' />
<Typography
variant='body2'
color='textPrimary'
style={{ marginLeft: 6 }}
>
1 {pairData.token0.symbol} = {token0Rate}{' '}
{pairData.token1.symbol}
</Typography>
</Box>
<Box
padding={0.75}
paddingX={1.5}
ml={2}
borderRadius={20}
display='flex'
alignItems='center'
bgcolor={palette.grey.A700}
>
<CurrencyLogo currency={currency1} size='16px' />
<Typography
variant='body2'
color='textPrimary'
style={{ marginLeft: 6 }}
>
1 {pairData.token1.symbol} = {token1Rate}{' '}
{pairData.token0.symbol}
</Typography>
</Box>
</Box>
</Box>
<Box my={2} display='flex'>
<Box
className={classes.button}
mr={1.5}
border={`1px solid ${palette.primary.main}`}
onClick={() => {
history.push(
`/pools?currency0=${pairData.token0.id}¤cy1=${pairData.token1.id}`,
);
}}
>
<Typography variant='body2'>Add Liquidity</Typography>
</Box>
<Box
className={cx(classes.button, classes.filledButton)}
onClick={() => {
history.push(
`/swap?currency0=${pairData.token0.id}¤cy1=${pairData.token1.id}`,
);
}}
>
<Typography variant='body2'>Swap</Typography>
</Box>
</Box>
</Box>
<Box width={1} className={classes.panel} mt={4}>
<Grid container>
<Grid item xs={12} sm={12} md={6}>
<AnalyticsPairChart pairData={pairData} />
</Grid>
<Grid item xs={12} sm={12} md={6}>
<Box
my={2}
height={1}
display='flex'
justifyContent='center'
alignItems='center'
>
<Box
width={isMobile ? 1 : 0.8}
display='flex'
justifyContent='space-between'
>
<Box width={212}>
<Box>
<Typography
variant='caption'
style={{ color: palette.text.disabled }}
>
TOTAL TOKENS LOCKED
</Typography>
<Box
mt={1.5}
bgcolor={palette.grey.A400}
borderRadius={8}
padding={1.5}
>
<Box
display='flex'
alignItems='center'
justifyContent='space-between'
>
<Box display='flex' alignItems='center'>
<CurrencyLogo currency={currency0} size='16px' />
<Typography
variant='caption'
color='textPrimary'
style={{ marginLeft: 6 }}
>
{pairData.token0.symbol} :
</Typography>
</Box>
<Typography variant='caption' color='textPrimary'>
{Number(pairData.reserve0).toLocaleString()}
</Typography>
</Box>
<Box
mt={1}
display='flex'
alignItems='center'
justifyContent='space-between'
>
<Box display='flex' alignItems='center'>
<CurrencyLogo currency={currency1} size='16px' />
<Typography
variant='caption'
color='textPrimary'
style={{ marginLeft: 6 }}
>
{pairData.token1.symbol} :
</Typography>
</Box>
<Typography variant='caption' color='textPrimary'>
{Number(pairData.reserve1).toLocaleString()}
</Typography>
</Box>
</Box>
</Box>
<Box mt={4}>
<Typography
variant='caption'
style={{ color: palette.text.disabled }}
>
7d Trading Vol
</Typography>
<Typography variant={isMobile ? 'body1' : 'h5'}>
${pairData.oneWeekVolumeUSD.toLocaleString()}
</Typography>
</Box>
<Box mt={4}>
<Typography
variant='caption'
style={{ color: palette.text.disabled }}
>
24h FEES
</Typography>
<Typography variant={isMobile ? 'body1' : 'h5'}>
${fees}
</Typography>
</Box>
</Box>
<Box width={140}>
<Typography
variant='caption'
style={{ color: palette.text.disabled }}
>
TOTAL LIQUIDITY
</Typography>
<Typography variant={isMobile ? 'body1' : 'h5'}>
$
{Number(
pairData.reserveUSD
? pairData.reserveUSD
: pairData.trackedReserveUSD,
).toLocaleString()}
</Typography>
<Box mt={4}>
<Typography
variant='caption'
style={{ color: palette.text.disabled }}
>
24h Trading Vol
</Typography>
<Typography variant={isMobile ? 'body1' : 'h5'}>
${pairData.oneDayVolumeUSD.toLocaleString()}
</Typography>
</Box>
<Box mt={4}>
<Typography
variant='caption'
style={{ color: palette.text.disabled }}
>
Contract Address
</Typography>
<Typography
variant='h5'
style={{ color: palette.primary.main }}
>
{chainId ? (
<a
href={getEtherscanLink(
chainId,
pairData.id,
'address',
)}
target='_blank'
rel='noopener noreferrer'
style={{
color: palette.primary.main,
textDecoration: 'none',
}}
>
{shortenAddress(pairData.id)}
</a>
) : (
shortenAddress(pairData.id)
)}
</Typography>
</Box>
</Box>
</Box>
</Box>
</Grid>
</Grid>
</Box>
<Box width={1} mt={5}>
<Typography variant='body1'>Transactions</Typography>
</Box>
<Box width={1} className={classes.panel} mt={4}>
{pairTransactionsList ? (
<TransactionsTable data={pairTransactionsList} />
) : (
<Skeleton variant='rect' width='100%' height={150} />
)}
</Box>
</>
) : (
<Skeleton width='100%' height={100} />
)}
</>
);
}
Example #9
Source File: AnalyticsTokenDetails.tsx From interface-v2 with GNU General Public License v3.0 | 4 votes |
AnalyticsTokenDetails: React.FC = () => {
const classes = useStyles();
const { palette, breakpoints } = useTheme();
const isMobile = useMediaQuery(breakpoints.down('xs'));
const history = useHistory();
const match = useRouteMatch<{ id: string }>();
const tokenAddress = match.params.id;
const [token, setToken] = useState<any>(null);
const { chainId } = useActiveWeb3React();
const currency = token
? new Token(ChainId.MATIC, getAddress(token.id), token.decimals)
: undefined;
const [tokenPairs, updateTokenPairs] = useState<any>(null);
const {
bookmarkTokens,
addBookmarkToken,
removeBookmarkToken,
} = useBookmarkTokens();
useEffect(() => {
async function fetchTokenInfo() {
const [newPrice, oneDayPrice] = await getEthPrice();
const tokenInfo = await getTokenInfo(newPrice, oneDayPrice, tokenAddress);
if (tokenInfo) {
setToken(tokenInfo[0]);
}
}
fetchTokenInfo();
}, [tokenAddress]);
useEffect(() => {
async function fetchTokenPairs() {
const [newPrice] = await getEthPrice();
const tokenPairs = await getTokenPairs2(tokenAddress);
const formattedPairs = tokenPairs
? tokenPairs.map((pair: any) => {
return pair.id;
})
: [];
const pairData = await getBulkPairData(formattedPairs, newPrice);
if (pairData) {
updateTokenPairs(pairData);
}
}
fetchTokenPairs();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [updateTokenPairs, tokenAddress]);
const tokenPercentColor = getPriceColor(
token ? Number(token.priceChangeUSD) : 0,
palette,
);
return (
<>
<AnalyticsHeader type='token' data={token} />
{token ? (
<>
<Box
width={1}
display='flex'
flexWrap='wrap'
justifyContent='space-between'
>
<Box display='flex'>
<CurrencyLogo currency={currency} size='32px' />
<Box ml={1.5}>
<Box display='flex' alignItems='center'>
<Box display='flex' alignItems='flex-end' mr={0.5}>
<Typography className={classes.heading1}>
{token.name}{' '}
</Typography>
<Typography className={classes.heading2}>
({token.symbol})
</Typography>
</Box>
{bookmarkTokens.includes(token.id) ? (
<StarChecked
onClick={() => removeBookmarkToken(token.id)}
/>
) : (
<StarUnchecked onClick={() => addBookmarkToken(token.id)} />
)}
</Box>
<Box mt={1.25} display='flex' alignItems='center'>
<Typography
variant='h5'
style={{ color: palette.text.primary }}
>
${formatNumber(token.priceUSD)}
</Typography>
<Box
className={classes.priceChangeWrapper}
ml={2}
bgcolor={tokenPercentColor.bgColor}
color={tokenPercentColor.textColor}
>
<Typography variant='body2'>
{getFormattedPrice(Number(token.priceChangeUSD))}%
</Typography>
</Box>
</Box>
</Box>
</Box>
<Box my={2} display='flex'>
<Box
className={classes.button}
mr={1.5}
border={`1px solid ${palette.primary.main}`}
onClick={() => {
history.push(`/pools?currency0=${token.id}¤cy1=ETH`);
}}
>
<Typography variant='body2'>Add Liquidity</Typography>
</Box>
<Box
className={cx(classes.button, classes.filledButton)}
onClick={() => {
history.push(`/swap?currency0=${token.id}¤cy1=ETH`);
}}
>
<Typography variant='body2'>Swap</Typography>
</Box>
</Box>
</Box>
<Box width={1} className={classes.panel} mt={4}>
<Grid container>
<Grid item xs={12} sm={12} md={6}>
<AnalyticsTokenChart token={token} />
</Grid>
<Grid item xs={12} sm={12} md={6}>
<Box
my={2}
height={1}
display='flex'
flexDirection='column'
alignItems='center'
justifyContent='center'
>
<Box
width={isMobile ? 1 : 0.8}
display='flex'
justifyContent='space-between'
>
<Box width={180}>
<Typography
variant='caption'
style={{ color: palette.text.disabled }}
>
TOTAL LIQUIDITY
</Typography>
<Typography variant={isMobile ? 'body1' : 'h5'}>
${token.totalLiquidityUSD.toLocaleString()}
</Typography>
</Box>
<Box width={140}>
<Typography
variant='caption'
style={{ color: palette.text.disabled }}
>
7d Trading Vol
</Typography>
<Typography variant={isMobile ? 'body1' : 'h5'}>
${token.oneWeekVolumeUSD.toLocaleString()}
</Typography>
</Box>
</Box>
<Box
width={isMobile ? 1 : 0.8}
mt={4}
display='flex'
justifyContent='space-between'
>
<Box width={180}>
<Typography
variant='caption'
style={{ color: palette.text.disabled }}
>
24h Trading Vol
</Typography>
<Typography variant={isMobile ? 'body1' : 'h5'}>
${token.oneDayVolumeUSD.toLocaleString()}
</Typography>
</Box>
<Box width={140}>
<Typography
variant='caption'
style={{ color: palette.text.disabled }}
>
24h FEES
</Typography>
<Typography variant={isMobile ? 'body1' : 'h5'}>
$
{(
token.oneDayVolumeUSD * GlobalConst.utils.FEEPERCENT
).toLocaleString()}
</Typography>
</Box>
</Box>
<Box
width={isMobile ? 1 : 0.8}
mt={4}
display='flex'
justifyContent='space-between'
>
<Box width={180}>
<Typography
variant='caption'
style={{ color: palette.text.disabled }}
>
Contract Address
</Typography>
<Typography
variant='h5'
style={{ color: palette.primary.main }}
>
{chainId ? (
<a
href={getEtherscanLink(
chainId,
token.id,
'address',
)}
target='_blank'
rel='noopener noreferrer'
style={{
color: palette.primary.main,
textDecoration: 'none',
}}
>
{shortenAddress(token.id)}
</a>
) : (
shortenAddress(token.id)
)}
</Typography>
</Box>
</Box>
</Box>
</Grid>
</Grid>
</Box>
<Box width={1} mt={5}>
<Typography variant='body1'>{token.symbol} Pools</Typography>
</Box>
<Box width={1} className={classes.panel} mt={4}>
{tokenPairs ? (
<PairTable data={tokenPairs} />
) : (
<Skeleton variant='rect' width='100%' height={150} />
)}
</Box>
</>
) : (
<Skeleton width='100%' height={100} />
)}
</>
);
}
Example #10
Source File: ImportToken.tsx From forward.swaps with GNU General Public License v3.0 | 4 votes |
export function ImportToken({ tokens, onBack, onDismiss, handleCurrencySelect }: ImportProps) {
const theme = useTheme()
const { chainId } = useActiveWeb3React()
const [confirmed, setConfirmed] = useState(false)
const addToken = useAddUserToken()
// use for showing import source on inactive tokens
const inactiveTokenList = useCombinedInactiveList()
// higher warning severity if either is not on a list
const fromLists =
(chainId && inactiveTokenList?.[chainId]?.[tokens[0]?.address]?.list) ||
(chainId && inactiveTokenList?.[chainId]?.[tokens[1]?.address]?.list)
return (
<Wrapper>
<PaddedColumn gap="14px" style={{ width: '100%', flex: '1 1' }}>
<RowBetween>
{onBack ? <ArrowLeft style={{ cursor: 'pointer' }} onClick={onBack} /> : <div></div>}
<TYPE.mediumHeader>Import {tokens.length > 1 ? 'Tokens' : 'Token'}</TYPE.mediumHeader>
{onDismiss ? <CloseIcon onClick={onDismiss} /> : <div></div>}
</RowBetween>
</PaddedColumn>
<SectionBreak />
<PaddedColumn gap="md">
{tokens.map(token => {
const list = chainId && inactiveTokenList?.[chainId]?.[token.address]?.list
return (
<Card backgroundColor={theme.bg2} key={'import' + token.address} className=".token-warning-container">
<AutoColumn gap="10px">
<AutoRow align="center">
<CurrencyLogo currency={token} size={'24px'} />
<TYPE.body ml="8px" mr="8px" fontWeight={500}>
{token.symbol}
</TYPE.body>
<TYPE.darkGray fontWeight={300}>{token.name}</TYPE.darkGray>
</AutoRow>
{chainId && (
<ExternalLink href={getEtherscanLink(chainId, token.address, 'address')}>
<AddressText>{token.address}</AddressText>
</ExternalLink>
)}
{list !== undefined ? (
<RowFixed>
{list.logoURI && <ListLogo logoURI={list.logoURI} size="12px" />}
<TYPE.small ml="6px" color={theme.text3}>
via {list.name}
</TYPE.small>
</RowFixed>
) : (
<WarningWrapper borderRadius="4px" padding="4px" highWarning={true}>
<RowFixed>
<AlertTriangle stroke={theme.red1} size="10px" />
<TYPE.body color={theme.red1} ml="4px" fontSize="10px" fontWeight={500}>
Unkown Source
</TYPE.body>
</RowFixed>
</WarningWrapper>
)}
</AutoColumn>
</Card>
)
})}
<Card
style={{ backgroundColor: fromLists ? transparentize(0.8, theme.yellow2) : transparentize(0.8, theme.red1) }}
>
<AutoColumn justify="center" style={{ textAlign: 'center', gap: '16px', marginBottom: '12px' }}>
<AlertTriangle stroke={fromLists ? theme.yellow2 : theme.red1} size={32} />
<TYPE.body fontWeight={600} fontSize={20} color={fromLists ? theme.yellow2 : theme.red1}>
Trade at your own risk!
</TYPE.body>
</AutoColumn>
<AutoColumn style={{ textAlign: 'center', gap: '16px', marginBottom: '12px' }}>
<TYPE.body fontWeight={400} color={fromLists ? theme.yellow2 : theme.red1}>
Anyone can create a token, including creating fake versions of existing tokens that claim to represent
projects.
</TYPE.body>
<TYPE.body fontWeight={600} color={fromLists ? theme.yellow2 : theme.red1}>
If you purchase this token, you may not be able to sell it back.
</TYPE.body>
</AutoColumn>
<AutoRow justify="center" style={{ cursor: 'pointer' }} onClick={() => setConfirmed(!confirmed)}>
<Checkbox
className=".understand-checkbox"
name="confirmed"
type="checkbox"
checked={confirmed}
onChange={() => setConfirmed(!confirmed)}
/>
<TYPE.body ml="10px" fontSize="16px" color={fromLists ? theme.yellow2 : theme.red1} fontWeight={500}>
I understand
</TYPE.body>
</AutoRow>
</Card>
<ButtonPrimary
disabled={!confirmed}
altDisabledStyle={true}
borderRadius="20px"
padding="10px 1rem"
onClick={() => {
tokens.map(token => addToken(token))
handleCurrencySelect && handleCurrencySelect(tokens[0])
}}
className=".token-dismiss-button"
>
Import
</ButtonPrimary>
</PaddedColumn>
</Wrapper>
)
}
Example #11
Source File: ManageTokens.tsx From forward.swaps with GNU General Public License v3.0 | 4 votes |
export default function ManageTokens({
setModalView,
setImportToken
}: {
setModalView: (view: CurrencyModalView) => void
setImportToken: (token: Token) => void
}) {
const { chainId } = useActiveWeb3React()
const [searchQuery, setSearchQuery] = useState<string>('')
const theme = useTheme()
// manage focus on modal show
const inputRef = useRef<HTMLInputElement>()
const handleInput = useCallback(event => {
const input = event.target.value
const checksummedInput = isAddress(input)
setSearchQuery(checksummedInput || input)
}, [])
// if they input an address, use it
const isAddressSearch = isAddress(searchQuery)
const searchToken = useToken(searchQuery)
// all tokens for local lisr
const userAddedTokens: Token[] = useUserAddedTokens()
const removeToken = useRemoveUserAddedToken()
const handleRemoveAll = useCallback(() => {
if (chainId && userAddedTokens) {
userAddedTokens.map(token => {
return removeToken(chainId, token.address)
})
}
}, [removeToken, userAddedTokens, chainId])
const tokenList = useMemo(() => {
return (
chainId &&
userAddedTokens.map(token => (
<RowBetween key={token.address} width="100%">
<RowFixed>
<CurrencyLogo currency={token} size={'20px'} />
<ExternalLink href={getEtherscanLink(chainId, token.address, 'address')}>
<TYPE.main ml={'10px'} fontWeight={600}>
{token.symbol}
</TYPE.main>
</ExternalLink>
</RowFixed>
<RowFixed>
<TrashIcon onClick={() => removeToken(chainId, token.address)} />
<ExternalLinkIcon href={getEtherscanLink(chainId, token.address, 'address')} />
</RowFixed>
</RowBetween>
))
)
}, [userAddedTokens, chainId, removeToken])
return (
<Wrapper>
<Column style={{ width: '100%', flex: '1 1' }}>
<PaddedColumn gap="14px">
<Row>
<SearchInput
type="text"
id="token-search-input"
placeholder={'0x0000'}
value={searchQuery}
autoComplete="off"
ref={inputRef as RefObject<HTMLInputElement>}
onChange={handleInput}
/>
</Row>
{searchQuery !== '' && !isAddressSearch && <TYPE.error error={true}>Enter valid token address</TYPE.error>}
{searchToken && (
<Card backgroundColor={theme.bg2} padding="10px 0">
<ImportRow
token={searchToken}
showImportView={() => setModalView(CurrencyModalView.importToken)}
setImportToken={setImportToken}
style={{ height: 'fit-content' }}
/>
</Card>
)}
</PaddedColumn>
<Separator />
<PaddedColumn gap="lg">
<RowBetween>
<TYPE.main fontWeight={600}>
{userAddedTokens?.length} Custom {userAddedTokens.length === 1 ? 'Token' : 'Tokens'}
</TYPE.main>
{userAddedTokens.length > 0 && (
<ButtonText onClick={handleRemoveAll}>
<TYPE.blue>Clear all</TYPE.blue>
</ButtonText>
)}
</RowBetween>
{tokenList}
</PaddedColumn>
</Column>
<Footer>
<TYPE.darkGray>Tip: Custom tokens are stored locally in your browser</TYPE.darkGray>
</Footer>
</Wrapper>
)
}