Add USD values to balance list (#92)

This commit is contained in:
Armani Ferrante 2021-02-20 13:25:14 +08:00 committed by GitHub
parent ef3ca11bf0
commit 37f3d0a276
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 84 additions and 15 deletions

View File

@ -1,4 +1,4 @@
import React, { useState, useMemo } from 'react'; import React, { useState, useMemo, useEffect } from 'react';
import List from '@material-ui/core/List'; import List from '@material-ui/core/List';
import ListItem from '@material-ui/core/ListItem'; import ListItem from '@material-ui/core/ListItem';
import ListItemText from '@material-ui/core/ListItemText'; import ListItemText from '@material-ui/core/ListItemText';
@ -41,6 +41,7 @@ import {
useSolanaExplorerUrlSuffix, useSolanaExplorerUrlSuffix,
} from '../utils/connection'; } from '../utils/connection';
import { showTokenInfoDialog } from '../utils/config'; import { showTokenInfoDialog } from '../utils/config';
import { useConnection, MAINNET_URL } from '../utils/connection';
import CloseTokenAccountDialog from './CloseTokenAccountButton'; import CloseTokenAccountDialog from './CloseTokenAccountButton';
import ListItemIcon from '@material-ui/core/ListItemIcon'; import ListItemIcon from '@material-ui/core/ListItemIcon';
import TokenIcon from './TokenIcon'; import TokenIcon from './TokenIcon';
@ -68,14 +69,22 @@ export default function BalancesList() {
if (m[coin]) { if (m[coin]) {
// Only override a market if it's not deprecated . // Only override a market if it's not deprecated .
if (!m.deprecated) { if (!m.deprecated) {
m[coin] = market.address; m[coin] = {
publicKey: market.address,
name: market.name.split('/').join(''),
};
} }
} else { } else {
m[coin] = market.address; m[coin] = {
publicKey: market.address,
name: market.name.split('/').join(''),
};
} }
}); });
return m; return m;
}, []); }, []);
return ( return (
<Paper> <Paper>
<AppBar position="static" color="default" elevation={1}> <AppBar position="static" color="default" elevation={1}>
@ -160,7 +169,19 @@ const useStyles = makeStyles((theme) => ({
export function BalanceListItem({ publicKey, markets, expandable }) { export function BalanceListItem({ publicKey, markets, expandable }) {
const balanceInfo = useBalanceInfo(publicKey); const balanceInfo = useBalanceInfo(publicKey);
const classes = useStyles(); const classes = useStyles();
const connection = useConnection();
const [open, setOpen] = useState(false); const [open, setOpen] = useState(false);
const [price, setPrice] = useState(null);
useEffect(() => {
if (balanceInfo) {
const coin = balanceInfo.tokenSymbol.toUpperCase();
let m = markets[coin];
_priceStore.getPrice(connection, m.name).then((price) => {
setPrice(price);
});
}
}, [markets, price, balanceInfo, connection]);
expandable = expandable === undefined ? true : expandable; expandable = expandable === undefined ? true : expandable;
if (!balanceInfo) { if (!balanceInfo) {
@ -175,17 +196,32 @@ export function BalanceListItem({ publicKey, markets, expandable }) {
<ListItemIcon> <ListItemIcon>
<TokenIcon mint={mint} tokenName={tokenName} size={28} /> <TokenIcon mint={mint} tokenName={tokenName} size={28} />
</ListItemIcon> </ListItemIcon>
<ListItemText <div style={{ display: 'flex', flex: 1 }}>
primary={ <ListItemText
<> primary={
{balanceFormat.format(amount / Math.pow(10, decimals))}{' '} <>
{tokenName ?? abbreviateAddress(mint)} {balanceFormat.format(amount / Math.pow(10, decimals))}{' '}
{tokenSymbol ? ` (${tokenSymbol})` : null} {tokenName ?? abbreviateAddress(mint)}
</> {tokenSymbol ? ` (${tokenSymbol})` : null}
} </>
secondary={publicKey.toBase58()} }
secondaryTypographyProps={{ className: classes.address }} secondary={publicKey.toBase58()}
/> secondaryTypographyProps={{ className: classes.address }}
/>
{price && (
<div
style={{
display: 'flex',
justifyContent: 'center',
flexDirection: 'column',
}}
>
<Typography color="textSecondary">
${((amount / Math.pow(10, decimals)) * price).toFixed(2)}
</Typography>
</div>
)}
</div>
{expandable ? open ? <ExpandLess /> : <ExpandMore /> : <></>} {expandable ? open ? <ExpandLess /> : <ExpandMore /> : <></>}
</ListItem> </ListItem>
<Collapse in={open} timeout="auto" unmountOnExit> <Collapse in={open} timeout="auto" unmountOnExit>
@ -222,7 +258,7 @@ function BalanceListItemDetails({ publicKey, markets, balanceInfo }) {
const exportNeedsDisplay = const exportNeedsDisplay =
mint === null && tokenName === 'SOL' && tokenSymbol === 'SOL'; mint === null && tokenName === 'SOL' && tokenSymbol === 'SOL';
const market = markets[tokenSymbol.toUpperCase()]; const market = markets[tokenSymbol.toUpperCase()].publicKey;
return ( return (
<> <>
@ -353,3 +389,36 @@ function BalanceListItemDetails({ publicKey, markets, balanceInfo }) {
</> </>
); );
} }
// Create a cached API wrapper to avoid rate limits.
class PriceStore {
constructor() {
this.cache = {};
}
async getPrice(connection, marketName) {
return new Promise((resolve, reject) => {
if (connection._rpcEndpoint !== MAINNET_URL) {
resolve(undefined);
return;
}
if (this.cache[marketName] === undefined) {
this.cache[marketName] = null;
fetch(`https://serum-api.bonfida.com/orderbooks/${marketName}`).then(
(resp) => {
resp.json().then((resp) => {
const mid =
(resp.data.asks[0].price + resp.data.bids[0].price) / 2.0;
this.cache[marketName] = mid;
resolve(this.cache[marketName]);
});
},
);
} else {
return resolve(this.cache[marketName]);
}
});
}
}
const _priceStore = new PriceStore();