Cache promises (#17)

This commit is contained in:
Armani Ferrante 2021-05-20 16:29:42 -07:00 committed by GitHub
parent cecf600e58
commit 599e54c415
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 50 additions and 53 deletions

View File

@ -1,6 +1,6 @@
{ {
"name": "@project-serum/swap-ui", "name": "@project-serum/swap-ui",
"version": "0.1.0-alpha.10", "version": "0.1.0-alpha.11",
"main": "dist/index.js", "main": "dist/index.js",
"types": "dist/index.d.ts", "types": "dist/index.d.ts",
"homepage": ".", "homepage": ".",

View File

@ -27,8 +27,6 @@ export const BASE_TAKER_FEE_BPS = 0.0022;
type DexContext = { type DexContext = {
// Maps market address to open orders accounts. // Maps market address to open orders accounts.
openOrders: Map<string, Array<OpenOrders>>; openOrders: Map<string, Array<OpenOrders>>;
marketCache: Map<string, Market>;
setMarketCache: (c: Map<string, Market>) => void;
swapClient: SwapClient; swapClient: SwapClient;
}; };
const _DexContext = React.createContext<DexContext | null>(null); const _DexContext = React.createContext<DexContext | null>(null);
@ -37,9 +35,6 @@ export function DexContextProvider(props: any) {
const [ooAccounts, setOoAccounts] = useState<Map<string, Array<OpenOrders>>>( const [ooAccounts, setOoAccounts] = useState<Map<string, Array<OpenOrders>>>(
new Map() new Map()
); );
const [marketCache, setMarketCache] = useState<Map<string, Market>>(
new Map()
);
const swapClient = props.swapClient; const swapClient = props.swapClient;
// Two operations: // Two operations:
@ -73,31 +68,35 @@ export function DexContextProvider(props: any) {
"Too many markets. Please file an issue to update this" "Too many markets. Please file an issue to update this"
); );
} }
const marketAccounts = ( (
await anchor.utils.getMultipleAccounts( await anchor.utils.getMultipleAccounts(
swapClient.program.provider.connection, swapClient.program.provider.connection,
// @ts-ignore // @ts-ignore
[...markets].map((m) => new PublicKey(m)) [...markets].map((m) => new PublicKey(m))
) )
).map((programAccount) => { )
return { .map((programAccount) => {
publicKey: programAccount?.publicKey, return {
account: new Market( publicKey: programAccount?.publicKey,
Market.getLayout(DEX_PID).decode(programAccount?.account.data), account: new Promise<Market>((resolve) =>
-1, // Not used so don't bother fetching. resolve(
-1, // Not used so don't bother fetching. new Market(
swapClient.program.provider.opts, Market.getLayout(DEX_PID).decode(
DEX_PID programAccount?.account.data
), ),
}; -1, // Not used so don't bother fetching.
}); -1, // Not used so don't bother fetching.
setMarketCache((marketCache) => { swapClient.program.provider.opts,
const newMarketCache = new Map(marketCache); DEX_PID
marketAccounts.forEach((m) => { )
newMarketCache.set(m.publicKey!.toString(), m.account); )
),
};
})
.forEach((m) => {
_MARKET_CACHE.set(m.publicKey!.toString(), m.account);
}); });
return newMarketCache;
});
setOoAccounts(newOoAccounts); setOoAccounts(newOoAccounts);
}); });
}, [ }, [
@ -109,8 +108,6 @@ export function DexContextProvider(props: any) {
<_DexContext.Provider <_DexContext.Provider
value={{ value={{
openOrders: ooAccounts, openOrders: ooAccounts,
marketCache,
setMarketCache,
swapClient, swapClient,
}} }}
> >
@ -134,28 +131,25 @@ export function useOpenOrders(): Map<string, Array<OpenOrders>> {
// Lazy load a given market. // Lazy load a given market.
export function useMarket(market?: PublicKey): Market | undefined { export function useMarket(market?: PublicKey): Market | undefined {
const ctx = useDexContext(); const { swapClient } = useDexContext();
const asyncMarket = useAsync(async () => { const asyncMarket = useAsync(async () => {
if (!market) { if (!market) {
return undefined; return undefined;
} }
if (ctx.marketCache.get(market.toString())) { if (_MARKET_CACHE.get(market.toString())) {
return ctx.marketCache.get(market.toString()); return _MARKET_CACHE.get(market.toString());
} }
const marketClient = await Market.load( const marketClient = Market.load(
ctx.swapClient.program.provider.connection, swapClient.program.provider.connection,
market, market,
undefined, undefined,
DEX_PID DEX_PID
); );
let cache = new Map(ctx.marketCache); _MARKET_CACHE.set(market.toString(), marketClient);
cache.set(market.toString(), marketClient);
ctx.setMarketCache(cache);
return marketClient; return marketClient;
}, [ctx.swapClient.program.provider.connection, market]); }, [swapClient.program.provider.connection, market]);
if (asyncMarket.result) { if (asyncMarket.result) {
return asyncMarket.result; return asyncMarket.result;
@ -178,15 +172,17 @@ export function useOrderbook(market?: PublicKey): Orderbook | undefined {
return _ORDERBOOK_CACHE.get(market.toString()); return _ORDERBOOK_CACHE.get(market.toString());
} }
const [bids, asks] = await Promise.all([ const orderbook = new Promise<Orderbook>(async (resolve) => {
marketClient.loadBids(swapClient.program.provider.connection), const [bids, asks] = await Promise.all([
marketClient.loadAsks(swapClient.program.provider.connection), marketClient.loadBids(swapClient.program.provider.connection),
]); marketClient.loadAsks(swapClient.program.provider.connection),
]);
const orderbook = { resolve({
bids, bids,
asks, asks,
}; });
});
_ORDERBOOK_CACHE.set(market.toString(), orderbook); _ORDERBOOK_CACHE.set(market.toString(), orderbook);
@ -199,9 +195,9 @@ export function useOrderbook(market?: PublicKey): Orderbook | undefined {
if (marketClient?.bidsAddress) { if (marketClient?.bidsAddress) {
listener = swapClient.program.provider.connection.onAccountChange( listener = swapClient.program.provider.connection.onAccountChange(
marketClient?.bidsAddress, marketClient?.bidsAddress,
(info) => { async (info) => {
const bids = OrderbookSide.decode(marketClient, info.data); const bids = OrderbookSide.decode(marketClient, info.data);
const orderbook = _ORDERBOOK_CACHE.get( const orderbook = await _ORDERBOOK_CACHE.get(
marketClient.address.toString() marketClient.address.toString()
); );
const oldBestBid = orderbook?.bids.items(true).next().value; const oldBestBid = orderbook?.bids.items(true).next().value;
@ -237,9 +233,9 @@ export function useOrderbook(market?: PublicKey): Orderbook | undefined {
if (marketClient?.asksAddress) { if (marketClient?.asksAddress) {
listener = swapClient.program.provider.connection.onAccountChange( listener = swapClient.program.provider.connection.onAccountChange(
marketClient?.asksAddress, marketClient?.asksAddress,
(info) => { async (info) => {
const asks = OrderbookSide.decode(marketClient, info.data); const asks = OrderbookSide.decode(marketClient, info.data);
const orderbook = _ORDERBOOK_CACHE.get( const orderbook = await _ORDERBOOK_CACHE.get(
marketClient.address.toString() marketClient.address.toString()
); );
const oldBestOffer = orderbook?.asks.items(false).next().value; const oldBestOffer = orderbook?.asks.items(false).next().value;
@ -276,8 +272,6 @@ export function useOrderbook(market?: PublicKey): Orderbook | undefined {
return undefined; return undefined;
} }
const _ORDERBOOK_CACHE = new Map<string, Orderbook>();
export function useMarketName(market: PublicKey): string | null { export function useMarketName(market: PublicKey): string | null {
const tokenMap = useTokenMap(); const tokenMap = useTokenMap();
const marketClient = useMarket(market); const marketClient = useMarket(market);
@ -538,3 +532,6 @@ type Bbo = {
bestOffer?: number; bestOffer?: number;
mid?: number; mid?: number;
}; };
const _ORDERBOOK_CACHE = new Map<string, Promise<Orderbook>>();
const _MARKET_CACHE = new Map<string, Promise<Market>>();

View File

@ -130,7 +130,7 @@ export function useMint(mint?: PublicKey): MintInfo | undefined | null {
TOKEN_PROGRAM_ID, TOKEN_PROGRAM_ID,
new Account() new Account()
); );
const mintInfo = await mintClient.getMintInfo(); const mintInfo = mintClient.getMintInfo();
_MINT_CACHE.set(mint.toString(), mintInfo); _MINT_CACHE.set(mint.toString(), mintInfo);
return mintInfo; return mintInfo;
}, [provider.connection, mint]); }, [provider.connection, mint]);
@ -148,4 +148,4 @@ const _OWNED_TOKEN_ACCOUNTS_CACHE: Array<{
}> = []; }> = [];
// Cache storing all previously fetched mint infos. // Cache storing all previously fetched mint infos.
const _MINT_CACHE = new Map<string, MintInfo>(); const _MINT_CACHE = new Map<string, Promise<MintInfo>>();