Use memoized token map
This commit is contained in:
parent
65467d00ea
commit
ef97779a84
38
src/App.tsx
38
src/App.tsx
|
@ -24,25 +24,9 @@ import "./App.css";
|
|||
// to the `Swap` component, and then everything else is taken care of.
|
||||
function App() {
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
width: "450px",
|
||||
marginLeft: "auto",
|
||||
marginRight: "auto",
|
||||
position: "absolute",
|
||||
left: 0,
|
||||
right: 0,
|
||||
top: 0,
|
||||
bottom: 0,
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
flexDirection: "column",
|
||||
}}
|
||||
>
|
||||
<SnackbarProvider maxSnack={5} autoHideDuration={8000}>
|
||||
<AppInner />
|
||||
</SnackbarProvider>
|
||||
</div>
|
||||
<SnackbarProvider maxSnack={5} autoHideDuration={8000}>
|
||||
<AppInner />
|
||||
</SnackbarProvider>
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -106,7 +90,21 @@ function AppInner() {
|
|||
}, [wallet, enqueueSnackbar]);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div
|
||||
style={{
|
||||
width: "450px",
|
||||
marginLeft: "auto",
|
||||
marginRight: "auto",
|
||||
position: "absolute",
|
||||
left: 0,
|
||||
right: 0,
|
||||
top: 0,
|
||||
bottom: 0,
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
flexDirection: "column",
|
||||
}}
|
||||
>
|
||||
<Button
|
||||
variant="outlined"
|
||||
onClick={() => (!isConnected ? wallet.connect() : wallet.disconnect())}
|
||||
|
|
|
@ -8,7 +8,7 @@ import {
|
|||
import { Info } from "@material-ui/icons";
|
||||
import PopupState, { bindTrigger, bindPopover } from "material-ui-popup-state";
|
||||
import { PublicKey } from "@solana/web3.js";
|
||||
import { useTokenList } from "./context/TokenList";
|
||||
import { useTokenMap } from "./context/TokenList";
|
||||
import { useSwapContext, useSwapFair } from "./context/Swap";
|
||||
import { useMint } from "./context/Mint";
|
||||
import { useDexContext, useMarketName, useFair } from "./context/Dex";
|
||||
|
@ -41,18 +41,16 @@ export function InfoLabel() {
|
|||
const fromMintInfo = useMint(fromMint);
|
||||
const fair = useSwapFair();
|
||||
|
||||
const tokenList = useTokenList();
|
||||
let fromTokenInfo = tokenList.filter(
|
||||
(t) => t.address === fromMint.toString()
|
||||
)[0];
|
||||
let toTokenInfo = tokenList.filter((t) => t.address === toMint.toString())[0];
|
||||
const tokenMap = useTokenMap();
|
||||
let fromTokenInfo = tokenMap.get(fromMint.toString());
|
||||
let toTokenInfo = tokenMap.get(toMint.toString());
|
||||
|
||||
return (
|
||||
<div className={styles.infoLabel}>
|
||||
<Typography color="textSecondary"></Typography>
|
||||
<div style={{ display: "flex" }}>
|
||||
<div className={styles.fairPriceLabel}>
|
||||
{fair !== undefined
|
||||
{fair !== undefined && toTokenInfo && fromTokenInfo
|
||||
? `1 ${toTokenInfo.symbol} = ${fair.toFixed(
|
||||
fromMintInfo?.decimals
|
||||
)} ${fromTokenInfo.symbol}`
|
||||
|
@ -103,13 +101,9 @@ function InfoButton() {
|
|||
function InfoDetails() {
|
||||
const { fromMint, toMint } = useSwapContext();
|
||||
const { swapClient } = useDexContext();
|
||||
const tokenList = useTokenList();
|
||||
const fromMintTicker = tokenList
|
||||
.filter((t) => t.address === fromMint.toString())
|
||||
.map((t) => t.symbol)[0];
|
||||
const toMintTicker = tokenList
|
||||
.filter((t) => t.address === toMint.toString())
|
||||
.map((t) => t.symbol)[0];
|
||||
const tokenMap = useTokenMap();
|
||||
const fromMintTicker = tokenMap.get(fromMint.toString())?.symbol;
|
||||
const toMintTicker = tokenMap.get(toMint.toString())?.symbol;
|
||||
const addresses = [
|
||||
{ ticker: fromMintTicker, mint: fromMint },
|
||||
{ ticker: toMintTicker, mint: toMint },
|
||||
|
|
|
@ -32,7 +32,7 @@ import { SettingsOutlined as Settings, Close } from "@material-ui/icons";
|
|||
import PopupState, { bindTrigger, bindPopover } from "material-ui-popup-state";
|
||||
import { useSwapContext, useSwapFair } from "./context/Swap";
|
||||
import { useMarket, useOpenOrders, useDexContext } from "./context/Dex";
|
||||
import { useTokenList } from "./context/TokenList";
|
||||
import { useTokenMap } from "./context/TokenList";
|
||||
import { useMint } from "./context/Mint";
|
||||
import { useOwnedTokenAccount } from "./context/Token";
|
||||
|
||||
|
@ -298,17 +298,17 @@ function OpenOrdersRow({
|
|||
const [ooAccount, setOoAccount] = useState(openOrders[0]);
|
||||
const { swapClient } = useDexContext();
|
||||
const marketClient = useMarket(market);
|
||||
const tokenList = useTokenList();
|
||||
const tokenMap = useTokenMap();
|
||||
const base = useMint(marketClient?.baseMintAddress);
|
||||
const quote = useMint(marketClient?.quoteMintAddress);
|
||||
const baseWallet = useOwnedTokenAccount(marketClient?.baseMintAddress);
|
||||
const quoteWallet = useOwnedTokenAccount(marketClient?.quoteMintAddress);
|
||||
const baseTicker = tokenList
|
||||
.filter((t) => t.address === marketClient?.baseMintAddress.toString())
|
||||
.map((t) => t.symbol)[0];
|
||||
const quoteTicker = tokenList
|
||||
.filter((t) => t.address === marketClient?.quoteMintAddress.toString())
|
||||
.map((t) => t.symbol)[0];
|
||||
const baseTicker = marketClient
|
||||
? tokenMap.get(marketClient?.baseMintAddress.toString())?.symbol
|
||||
: "-";
|
||||
const quoteTicker = marketClient
|
||||
? tokenMap.get(marketClient?.quoteMintAddress.toString())?.symbol
|
||||
: "-";
|
||||
const marketName =
|
||||
baseTicker && quoteTicker
|
||||
? `${baseTicker} / ${quoteTicker}`
|
||||
|
|
|
@ -21,7 +21,7 @@ import {
|
|||
useMarket,
|
||||
} from "./context/Dex";
|
||||
import { MintContextProvider, useMint } from "./context/Mint";
|
||||
import { TokenListContextProvider, useTokenList } from "./context/TokenList";
|
||||
import { TokenListContextProvider, useTokenMap } from "./context/TokenList";
|
||||
import { TokenContextProvider, useOwnedTokenAccount } from "./context/Token";
|
||||
import TokenDialog from "./TokenDialog";
|
||||
import { SettingsButton } from "./Settings";
|
||||
|
@ -228,8 +228,8 @@ function TokenButton({
|
|||
}
|
||||
|
||||
export function TokenIcon({ mint, style }: { mint: PublicKey; style: any }) {
|
||||
const tokenList = useTokenList();
|
||||
let tokenInfo = tokenList.filter((t) => t.address === mint.toString())[0];
|
||||
const tokenMap = useTokenMap();
|
||||
let tokenInfo = tokenMap.get(mint.toString());
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
|
@ -238,8 +238,8 @@ export function TokenIcon({ mint, style }: { mint: PublicKey; style: any }) {
|
|||
flexDirection: "column",
|
||||
}}
|
||||
>
|
||||
{tokenInfo.logoURI ? (
|
||||
<img alt="token logo" style={style} src={tokenInfo.logoURI} />
|
||||
{tokenInfo?.logoURI ? (
|
||||
<img alt="token logo" style={style} src={tokenInfo?.logoURI} />
|
||||
) : (
|
||||
<div style={style}></div>
|
||||
)}
|
||||
|
@ -248,10 +248,10 @@ export function TokenIcon({ mint, style }: { mint: PublicKey; style: any }) {
|
|||
}
|
||||
|
||||
function TokenName({ mint }: { mint: PublicKey }) {
|
||||
const tokenList = useTokenList();
|
||||
let tokenInfo = tokenList.filter((t) => t.address === mint.toString())[0];
|
||||
const tokenMap = useTokenMap();
|
||||
let tokenInfo = tokenMap.get(mint.toString());
|
||||
return (
|
||||
<Typography style={{ marginLeft: "5px" }}>{tokenInfo.symbol}</Typography>
|
||||
<Typography style={{ marginLeft: "5px" }}>{tokenInfo?.symbol}</Typography>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { useState } from "react";
|
||||
import { useState, useMemo } from "react";
|
||||
import { PublicKey } from "@solana/web3.js";
|
||||
import {
|
||||
makeStyles,
|
||||
|
@ -12,7 +12,7 @@ import {
|
|||
} from "@material-ui/core";
|
||||
import { TokenIcon } from "./Swap";
|
||||
import { useDexContext } from "./context/Dex";
|
||||
import { useTokenList } from "./context/TokenList";
|
||||
import { useTokenMap } from "./context/TokenList";
|
||||
import { USDC_MINT, USDT_MINT } from "../utils/pubkeys";
|
||||
|
||||
const useStyles = makeStyles(() => ({
|
||||
|
@ -39,6 +39,9 @@ export default function TokenDialog({
|
|||
const [tokenFilter, setTokenFilter] = useState("");
|
||||
const styles = useStyles();
|
||||
const { swapClient } = useDexContext();
|
||||
const tokens = useMemo(() => {
|
||||
return swapClient.tokens().concat([USDC_MINT, USDT_MINT]);
|
||||
}, [swapClient]);
|
||||
return (
|
||||
<Dialog
|
||||
open={open}
|
||||
|
@ -64,19 +67,16 @@ export default function TokenDialog({
|
|||
/>
|
||||
<div>
|
||||
<List disablePadding>
|
||||
{swapClient
|
||||
.tokens()
|
||||
.concat([USDC_MINT, USDT_MINT])
|
||||
.map((mint) => (
|
||||
<TokenListItem
|
||||
key={mint.toString()}
|
||||
mint={mint}
|
||||
onClick={(mint) => {
|
||||
setMint(mint);
|
||||
onClose();
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
{tokens.map((mint) => (
|
||||
<TokenListItem
|
||||
key={mint.toString()}
|
||||
mint={mint}
|
||||
onClick={(mint) => {
|
||||
setMint(mint);
|
||||
onClose();
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
</List>
|
||||
</div>
|
||||
</DialogContent>
|
||||
|
@ -101,13 +101,15 @@ function TokenListItem({
|
|||
}
|
||||
|
||||
function TokenName({ mint }: { mint: PublicKey }) {
|
||||
const tokenList = useTokenList();
|
||||
let tokenInfo = tokenList.filter((t) => t.address === mint.toString())[0];
|
||||
const tokenMap = useTokenMap();
|
||||
let tokenInfo = tokenMap.get(mint.toString());
|
||||
return (
|
||||
<div style={{ marginLeft: "16px" }}>
|
||||
<Typography style={{ fontWeight: "bold" }}>{tokenInfo.symbol}</Typography>
|
||||
<Typography style={{ fontWeight: "bold" }}>
|
||||
{tokenInfo?.symbol}
|
||||
</Typography>
|
||||
<Typography color="textSecondary" style={{ fontSize: "14px" }}>
|
||||
{tokenInfo.name}
|
||||
{tokenInfo?.name}
|
||||
</Typography>
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -9,7 +9,7 @@ import {
|
|||
} from "@project-serum/serum";
|
||||
import { PublicKey } from "@solana/web3.js";
|
||||
import { DEX_PID } from "../../utils/pubkeys";
|
||||
import { useTokenList } from "./TokenList";
|
||||
import { useTokenMap } from "./TokenList";
|
||||
|
||||
type DexContext = {
|
||||
// Maps market address to open orders accounts.
|
||||
|
@ -196,14 +196,14 @@ export function useOrderbook(market?: PublicKey): Orderbook | undefined {
|
|||
}
|
||||
|
||||
export function useMarketName(market: PublicKey): string {
|
||||
const tokenList = useTokenList();
|
||||
const tokenMap = useTokenMap();
|
||||
const marketClient = useMarket(market);
|
||||
const baseTicker = tokenList
|
||||
.filter((t) => t.address === marketClient?.baseMintAddress.toString())
|
||||
.map((t) => t.symbol)[0];
|
||||
const quoteTicker = tokenList
|
||||
.filter((t) => t.address === marketClient?.quoteMintAddress.toString())
|
||||
.map((t) => t.symbol)[0];
|
||||
const baseTicker = marketClient
|
||||
? tokenMap.get(marketClient?.baseMintAddress.toString())?.symbol
|
||||
: "-";
|
||||
const quoteTicker = marketClient
|
||||
? tokenMap.get(marketClient?.quoteMintAddress.toString())?.symbol
|
||||
: "-";
|
||||
const name = `${baseTicker} / ${quoteTicker}`;
|
||||
return name;
|
||||
}
|
||||
|
|
|
@ -1,24 +1,36 @@
|
|||
import React, { useContext } from "react";
|
||||
import { TokenListContainer, TokenInfo } from "@solana/spl-token-registry";
|
||||
import React, { useContext, useMemo } from "react";
|
||||
import { TokenInfo } from "@solana/spl-token-registry";
|
||||
|
||||
type TokenListContext = {
|
||||
tokenMap: Map<string, TokenInfo>;
|
||||
};
|
||||
const _TokenListContext = React.createContext<null | TokenListContext>(null);
|
||||
|
||||
export function TokenListContextProvider(props: any) {
|
||||
const tokenList = useMemo(() => props.tokenList.getList(), [props.tokenList]);
|
||||
const tokenMap = useMemo(() => {
|
||||
const tokenMap = new Map();
|
||||
tokenList.forEach((t: TokenInfo) => {
|
||||
tokenMap.set(t.address, t);
|
||||
});
|
||||
return tokenMap;
|
||||
}, [tokenList]);
|
||||
return (
|
||||
<_TokenListContext.Provider value={{ tokenList: props.tokenList }}>
|
||||
<_TokenListContext.Provider value={{ tokenMap }}>
|
||||
{props.children}
|
||||
</_TokenListContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
type TokenListContext = {
|
||||
tokenList: TokenListContainer;
|
||||
};
|
||||
|
||||
export function useTokenList(): TokenInfo[] {
|
||||
function useTokenListContext(): TokenListContext {
|
||||
const ctx = useContext(_TokenListContext);
|
||||
if (ctx === null) {
|
||||
throw new Error("Context not available");
|
||||
}
|
||||
return ctx.tokenList.getList();
|
||||
return ctx;
|
||||
}
|
||||
|
||||
export function useTokenMap(): Map<string, TokenInfo> {
|
||||
const { tokenMap } = useTokenListContext();
|
||||
return tokenMap;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue