From ed6116488af2372e1f5597e2bfd326ca74d08e3a Mon Sep 17 00:00:00 2001 From: exromany Date: Mon, 27 Sep 2021 17:32:25 +0300 Subject: [PATCH] feat: useAuctions on store-related auctions --- .../common/src/contexts/meta/loadAccounts.ts | 2 +- .../meta => utils}/createPipelineExecutor.ts | 1 - js/packages/common/src/utils/index.tsx | 1 + js/packages/web/src/hooks/useAuctions.ts | 152 ++++++++++-------- 4 files changed, 83 insertions(+), 73 deletions(-) rename js/packages/common/src/{contexts/meta => utils}/createPipelineExecutor.ts (96%) diff --git a/js/packages/common/src/contexts/meta/loadAccounts.ts b/js/packages/common/src/contexts/meta/loadAccounts.ts index 0954f51..408ab4c 100644 --- a/js/packages/common/src/contexts/meta/loadAccounts.ts +++ b/js/packages/common/src/contexts/meta/loadAccounts.ts @@ -37,7 +37,7 @@ import { ParsedAccount } from '../accounts/types'; import { getEmptyMetaState } from './getEmptyMetaState'; import { getMultipleAccounts } from '../accounts/getMultipleAccounts'; import { getProgramAccounts } from './web3'; -import { createPipelineExecutor } from './createPipelineExecutor'; +import { createPipelineExecutor } from '../../utils/createPipelineExecutor'; export const USE_SPEED_RUN = false; const WHITELISTED_METADATA = ['98vYFjBYS9TguUMWQRPjy2SZuxKuUMcqR4vnQiLjZbte']; diff --git a/js/packages/common/src/contexts/meta/createPipelineExecutor.ts b/js/packages/common/src/utils/createPipelineExecutor.ts similarity index 96% rename from js/packages/common/src/contexts/meta/createPipelineExecutor.ts rename to js/packages/common/src/utils/createPipelineExecutor.ts index 4c1ac29..44bc937 100644 --- a/js/packages/common/src/contexts/meta/createPipelineExecutor.ts +++ b/js/packages/common/src/utils/createPipelineExecutor.ts @@ -12,7 +12,6 @@ export async function createPipelineExecutor( } = {}, ) { function execute(iter: IteratorResult) { - // TODO: wait for async executor executor(iter.value); } diff --git a/js/packages/common/src/utils/index.tsx b/js/packages/common/src/utils/index.tsx index e27e980..c01f409 100644 --- a/js/packages/common/src/utils/index.tsx +++ b/js/packages/common/src/utils/index.tsx @@ -9,3 +9,4 @@ export * from './strings'; export * as shortvec from './shortvec'; export * from './isValidHttpUrl'; export * from './borsh'; +export * from './createPipelineExecutor'; diff --git a/js/packages/web/src/hooks/useAuctions.ts b/js/packages/web/src/hooks/useAuctions.ts index dd35c0b..c93d31d 100644 --- a/js/packages/web/src/hooks/useAuctions.ts +++ b/js/packages/web/src/hooks/useAuctions.ts @@ -11,10 +11,11 @@ import { MasterEditionV2, StringPublicKey, AuctionDataExtended, + createPipelineExecutor, } from '@oyster/common'; import { useWallet } from '@solana/wallet-adapter-react'; import BN from 'bn.js'; -import { useEffect, useState } from 'react'; +import { useEffect, useMemo, useState } from 'react'; import { useMeta } from '../contexts'; import { AuctionManager, @@ -58,51 +59,54 @@ export interface AuctionView { isInstantSale: boolean; } +type CachedRedemptionKeys = Record< + string, + ParsedAccount | { pubkey: StringPublicKey; info: null } +>; + +export function useStoreAuctionsList() { + const { auctions, auctionManagersByAuction } = useMeta(); + const result = useMemo(() => { + return Object.values(auctionManagersByAuction).map( + manager => auctions[manager.info.auction], + ); + }, [auctions, auctionManagersByAuction]); + return result; +} + export function useCachedRedemptionKeysByWallet() { - const { auctions, bidRedemptions } = useMeta(); + const { bidRedemptions } = useMeta(); + const auctions = useStoreAuctionsList(); const { publicKey } = useWallet(); - const [cachedRedemptionKeys, setCachedRedemptionKeys] = useState< - Record< - string, - | ParsedAccount - | { pubkey: StringPublicKey; info: null } - > - >({}); + const [cachedRedemptionKeys, setCachedRedemptionKeys] = + useState({}); useEffect(() => { + if (!publicKey) return; (async () => { - if (publicKey) { - const temp: Record< - string, - | ParsedAccount - | { pubkey: StringPublicKey; info: null } - > = {}; - const keys = Object.keys(auctions); - const tasks: Promise[] = []; - for (let i = 0; i < keys.length; i++) { - const a = keys[i]; - if (!cachedRedemptionKeys[a]) - tasks.push( - getBidderKeys(auctions[a].pubkey, publicKey.toBase58()).then( - key => { - temp[a] = bidRedemptions[key.bidRedemption] - ? bidRedemptions[key.bidRedemption] - : { pubkey: key.bidRedemption, info: null }; - }, - ), + const temp: CachedRedemptionKeys = {}; + await createPipelineExecutor( + auctions.values(), + async auction => { + if (!cachedRedemptionKeys[auction.pubkey]) { + await getBidderKeys(auction.pubkey, publicKey.toBase58()).then( + key => { + temp[auction.pubkey] = bidRedemptions[key.bidRedemption] + ? bidRedemptions[key.bidRedemption] + : { pubkey: key.bidRedemption, info: null }; + }, ); - else if (!cachedRedemptionKeys[a].info) { - temp[a] = - bidRedemptions[cachedRedemptionKeys[a].pubkey] || - cachedRedemptionKeys[a]; + } else if (!cachedRedemptionKeys[auction.pubkey].info) { + temp[auction.pubkey] = + bidRedemptions[cachedRedemptionKeys[auction.pubkey].pubkey] || + cachedRedemptionKeys[auction.pubkey]; } - } + }, + { delay: 1, sequence: 2 }, + ); - await Promise.all(tasks); - - setCachedRedemptionKeys(temp); - } + setCachedRedemptionKeys(temp); })(); }, [auctions, bidRedemptions, publicKey]); @@ -113,9 +117,9 @@ export const useAuctions = (state?: AuctionViewState) => { const [auctionViews, setAuctionViews] = useState([]); const { publicKey } = useWallet(); const cachedRedemptionKeys = useCachedRedemptionKeysByWallet(); + const auctions = useStoreAuctionsList(); const { - auctions, auctionManagersByAuction, safetyDepositBoxesByVaultAndIndex, metadataByMint, @@ -132,40 +136,39 @@ export const useAuctions = (state?: AuctionViewState) => { } = useMeta(); useEffect(() => { - const map = Object.keys(auctions).reduce((agg, a) => { - const auction = auctions[a]; - const nextAuctionView = processAccountsIntoAuctionView( - publicKey?.toBase58(), - auction, - auctionDataExtended, - auctionManagersByAuction, - safetyDepositBoxesByVaultAndIndex, - metadataByMint, - bidderMetadataByAuctionAndBidder, - bidderPotsByAuctionAndBidder, - bidRedemptionV2sByAuctionManagerAndWinningIndex, - masterEditions, - vaults, - safetyDepositConfigsByAuctionManagerAndIndex, - masterEditionsByPrintingMint, - masterEditionsByOneTimeAuthMint, - metadataByMasterEdition, - cachedRedemptionKeys, - state, - ); - agg[a] = nextAuctionView; - return agg; - }, {} as Record); + (async () => { + const auctionViews: AuctionView[] = []; - setAuctionViews( - (Object.values(map).filter(v => v) as AuctionView[]).sort((a, b) => { - return ( - b?.auction.info.endedAt - ?.sub(a?.auction.info.endedAt || new BN(0)) - .toNumber() || 0 - ); - }), - ); + await createPipelineExecutor( + auctions.values(), + auction => { + const auctionView = processAccountsIntoAuctionView( + publicKey?.toBase58(), + auction, + auctionDataExtended, + auctionManagersByAuction, + safetyDepositBoxesByVaultAndIndex, + metadataByMint, + bidderMetadataByAuctionAndBidder, + bidderPotsByAuctionAndBidder, + bidRedemptionV2sByAuctionManagerAndWinningIndex, + masterEditions, + vaults, + safetyDepositConfigsByAuctionManagerAndIndex, + masterEditionsByPrintingMint, + masterEditionsByOneTimeAuthMint, + metadataByMasterEdition, + cachedRedemptionKeys, + state, + ); + if (auctionView) { + auctionViews.push(auctionView); + } + }, + { delay: 1, sequence: 2 }, + ); + setAuctionViews(auctionViews.sort(sortByEnded)); + })(); }, [ state, auctions, @@ -190,6 +193,13 @@ export const useAuctions = (state?: AuctionViewState) => { return auctionViews; }; +function sortByEnded(a: AuctionView, b: AuctionView) { + return ( + (b.auction.info.endedAt?.toNumber() || 0) - + (a.auction.info.endedAt?.toNumber() || 0) + ); +} + function isInstantSale( auctionDataExt: ParsedAccount | null, auction: ParsedAccount,