From 4c5f1e7642053aae7b93d0829f40194adc15c8d2 Mon Sep 17 00:00:00 2001 From: shotgunofdeath Date: Sun, 12 Sep 2021 20:17:45 +0300 Subject: [PATCH] feat(instant sale): add the instant sale with copies flow --- .../web/src/components/AuctionCard/index.tsx | 34 ++++++--- js/packages/web/src/contexts/meta/meta.tsx | 26 +++++-- js/packages/web/src/contexts/meta/types.ts | 9 ++- .../models/metaplex/redeemPrintingV2Bid.ts | 10 +++ .../web/src/views/auctionCreate/index.tsx | 74 ++++++++++--------- .../web/src/views/home/auctionList.tsx | 2 +- 6 files changed, 102 insertions(+), 53 deletions(-) diff --git a/js/packages/web/src/components/AuctionCard/index.tsx b/js/packages/web/src/components/AuctionCard/index.tsx index f175c83..b8193e1 100644 --- a/js/packages/web/src/components/AuctionCard/index.tsx +++ b/js/packages/web/src/components/AuctionCard/index.tsx @@ -20,6 +20,7 @@ import { MAX_METADATA_LEN, MAX_EDITION_LEN, useWalletModal, + VaultState, } from '@oyster/common'; import { useWallet } from '@solana/wallet-adapter-react'; import { AuctionView, useBidsForAuction, useUserBalance } from '../../hooks'; @@ -183,7 +184,7 @@ export const AuctionCard = ({ action?: JSX.Element; }) => { const connection = useConnection(); - const {update} = useMeta(); + const { update } = useMeta(); const wallet = useWallet(); const { setVisible } = useWalletModal(); @@ -253,8 +254,14 @@ export const AuctionCard = ({ auctionView.auction.info.state === AuctionState.Created; //if instant sale auction bid and claimed hide buttons - if (auctionView.isInstantSale && auctionView.myBidderPot?.info.emptied) { - return <> + if ( + (auctionView.isInstantSale && + Number(auctionView.myBidderPot?.info.emptied) !== 0 && + isAuctionManagerAuthorityNotWalletOwner && + auctionView.auction.info.bidState.max.toNumber() === bids.length) || + auctionView.vault.info.state === VaultState.Deactivated + ) { + return <>; } return ( @@ -387,7 +394,9 @@ export const AuctionCard = ({ {loading ? ( ) : auctionView.isInstantSale ? ( - bids.length ? ( + !isAuctionManagerAuthorityNotWalletOwner ? ( + 'Claim master' + ) : auctionView.myBidderPot ? ( 'Claim Purchase' ) : ( 'Buy Now' @@ -509,7 +518,8 @@ export const AuctionCard = ({ // Placing a "bid" of the full amount results in a purchase to redeem. if ( myPayingAccount && - bids.length === 0 && + !auctionView.myBidderPot && + isAuctionManagerAuthorityNotWalletOwner && auctionView.auctionDataExtended?.info.instantSalePrice ) { try { @@ -523,15 +533,20 @@ export const AuctionCard = ({ ); setLastBid(bid); } catch (e) { - console.error('sendPlaceBid', e) + console.error('sendPlaceBid', e); setShowBidModal(false); setLoading(false); return; } - } - await update(); + const newAuctionState = await update( + auctionView.auction.pubkey, + wallet.publicKey, + ); + auctionView.auction = newAuctionState[0]; + auctionView.myBidderPot = newAuctionState[1]; + auctionView.myBidderMetadata = newAuctionState[2]; // Claim the purchase try { @@ -684,7 +699,8 @@ export const AuctionCard = ({ {loading || !accountByMint.get(QUOTE_MINT.toBase58()) ? ( ) : auctionView.isInstantSale ? ( - bids.length ? ( + auctionView.myBidderPot || + !isAuctionManagerAuthorityNotWalletOwner ? ( 'Claim' ) : ( 'Purchase' diff --git a/js/packages/web/src/contexts/meta/meta.tsx b/js/packages/web/src/contexts/meta/meta.tsx index 0e43ae4..24ec93b 100644 --- a/js/packages/web/src/contexts/meta/meta.tsx +++ b/js/packages/web/src/contexts/meta/meta.tsx @@ -7,6 +7,9 @@ import { METADATA_PROGRAM_ID, toPublicKey, useQuerySearch, + AuctionData, + BidderPot, + BidderMetadata, } from '@oyster/common'; import React, { useCallback, @@ -52,9 +55,11 @@ const MetaContext = React.createContext({ payoutTickets: {}, prizeTrackingTickets: {}, stores: {}, - update: () => {}, + // @ts-ignore + update: () => [AuctionData, BidderPot, BidderMetadata], }); +// eslint-disable-next-line react/prop-types export function MetaProvider({ children = null as any }) { const connection = useConnection(); const { isReady, storeAddress } = useStore(); @@ -109,7 +114,7 @@ export function MetaProvider({ children = null as any }) { [setState], ); - async function update () { + async function update(auctionAddress?, bidderAddress?) { if (!storeAddress) { if (isReady) { setIsLoading(false); @@ -122,7 +127,7 @@ export function MetaProvider({ children = null as any }) { console.log('-----> Query started'); const nextState = await loadAccounts(connection, all); - console.log('loadAccounts',nextState) + console.log('loadAccounts', nextState); console.log('------->Query finished'); setState(nextState); @@ -130,9 +135,17 @@ export function MetaProvider({ children = null as any }) { setIsLoading(false); console.log('------->set finished'); - updateMints(nextState.metadataByMint); - } + await updateMints(nextState.metadataByMint); + if (auctionAddress && bidderAddress) { + const auctionBidderKey = auctionAddress + '-' + bidderAddress; + return [ + nextState.auctions[auctionAddress], + nextState.bidderPotsByAuctionAndBidder[auctionBidderKey], + nextState.bidderMetadataByAuctionAndBidder[auctionBidderKey], + ]; + } + } useEffect(() => { update(); @@ -232,7 +245,8 @@ export function MetaProvider({ children = null as any }) { value={{ ...state, isLoading, - update + // @ts-ignore + update, }} > {children} diff --git a/js/packages/web/src/contexts/meta/types.ts b/js/packages/web/src/contexts/meta/types.ts index 98db5a8..53a941d 100644 --- a/js/packages/web/src/contexts/meta/types.ts +++ b/js/packages/web/src/contexts/meta/types.ts @@ -76,7 +76,14 @@ export interface MetaState { export interface MetaContextState extends MetaState { isLoading: boolean; - update: () => void; + update: ( + auctionAddress?: any, + bidderAddress?: any, + ) => [ + ParsedAccount, + ParsedAccount, + ParsedAccount, + ]; } export type AccountAndPubkey = { diff --git a/js/packages/web/src/models/metaplex/redeemPrintingV2Bid.ts b/js/packages/web/src/models/metaplex/redeemPrintingV2Bid.ts index 8384982..d9e4628 100644 --- a/js/packages/web/src/models/metaplex/redeemPrintingV2Bid.ts +++ b/js/packages/web/src/models/metaplex/redeemPrintingV2Bid.ts @@ -5,6 +5,7 @@ import { programIds, StringPublicKey, toPublicKey, + getAuctionExtended, } from '@oyster/common'; import { SystemProgram, @@ -69,6 +70,10 @@ export async function redeemPrintingV2Bid( const value = new RedeemPrintingV2BidArgs({ editionOffset, winIndex }); const data = Buffer.from(serialize(SCHEMA, value)); + const extended = await getAuctionExtended({ + auctionProgramId: PROGRAM_IDS.auction, + resource: vault, + }); const keys = [ { pubkey: toPublicKey(auctionManagerKey), @@ -199,6 +204,11 @@ export async function redeemPrintingV2Bid( isSigner: false, isWritable: false, }, + { + pubkey: toPublicKey(extended), + isSigner: false, + isWritable: false, + }, ]; instructions.push( diff --git a/js/packages/web/src/views/auctionCreate/index.tsx b/js/packages/web/src/views/auctionCreate/index.tsx index 667cc03..b886d2e 100644 --- a/js/packages/web/src/views/auctionCreate/index.tsx +++ b/js/packages/web/src/views/auctionCreate/index.tsx @@ -172,11 +172,13 @@ export const AuctionCreateView = () => { if (attributes.category === AuctionCategory.InstantSale) { if (attributes.items.length > 0) { const item = attributes.items[0]; - item.winningConfigType = - item.metadata.info.updateAuthority === - (wallet?.publicKey || SystemProgram.programId).toBase58() - ? WinningConfigType.FullRightsTransfer - : WinningConfigType.TokenOnlyTransfer; + if (!attributes.editions) { + item.winningConfigType = + item.metadata.info.updateAuthority === + (wallet?.publicKey || SystemProgram.programId).toBase58() + ? WinningConfigType.FullRightsTransfer + : WinningConfigType.TokenOnlyTransfer; + } item.amountRanges = [ new AmountRange({ amount: new BN(1), @@ -770,37 +772,37 @@ const InstantSaleStep = (props: { Select NFT - {/**/} +