feat(instant sale): add the instant sale with copies flow
This commit is contained in:
parent
5c338a156e
commit
4c5f1e7642
|
@ -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 ? (
|
||||
<Spin />
|
||||
) : 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()) ? (
|
||||
<Spin />
|
||||
) : auctionView.isInstantSale ? (
|
||||
bids.length ? (
|
||||
auctionView.myBidderPot ||
|
||||
!isAuctionManagerAuthorityNotWalletOwner ? (
|
||||
'Claim'
|
||||
) : (
|
||||
'Purchase'
|
||||
|
|
|
@ -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<MetaContextState>({
|
|||
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}
|
||||
|
|
|
@ -76,7 +76,14 @@ export interface MetaState {
|
|||
|
||||
export interface MetaContextState extends MetaState {
|
||||
isLoading: boolean;
|
||||
update: () => void;
|
||||
update: (
|
||||
auctionAddress?: any,
|
||||
bidderAddress?: any,
|
||||
) => [
|
||||
ParsedAccount<AuctionData>,
|
||||
ParsedAccount<BidderPot>,
|
||||
ParsedAccount<BidderMetadata>,
|
||||
];
|
||||
}
|
||||
|
||||
export type AccountAndPubkey = {
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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
|
||||
</ArtSelector>
|
||||
|
||||
{/*<label className="action-field">*/}
|
||||
{/* <Checkbox*/}
|
||||
{/* defaultChecked={false}*/}
|
||||
{/* checked={copiesChecked}*/}
|
||||
{/* disabled={!copiesEnabled}*/}
|
||||
{/* onChange={e => setCopiesChecked(e.target.checked)}*/}
|
||||
{/* >*/}
|
||||
{/* <span className="field-title">*/}
|
||||
{/* Create copies of a Master Edition NFT?*/}
|
||||
{/* </span>*/}
|
||||
{/* </Checkbox>*/}
|
||||
{/* {copiesChecked && copiesEnabled && (*/}
|
||||
{/* <>*/}
|
||||
{/* <span className="field-info">*/}
|
||||
{/* Each copy will be given unique edition number e.g. 1 of 30*/}
|
||||
{/* </span>*/}
|
||||
{/* <Input*/}
|
||||
{/* autoFocus*/}
|
||||
{/* className="input"*/}
|
||||
{/* placeholder="Enter number of copies sold"*/}
|
||||
{/* allowClear*/}
|
||||
{/* onChange={info =>*/}
|
||||
{/* props.setAttributes({*/}
|
||||
{/* ...props.attributes,*/}
|
||||
{/* editions: parseInt(info.target.value),*/}
|
||||
{/* })*/}
|
||||
{/* }*/}
|
||||
{/* />*/}
|
||||
{/* </>*/}
|
||||
{/* )}*/}
|
||||
{/*</label>*/}
|
||||
<label className="action-field">
|
||||
<Checkbox
|
||||
defaultChecked={false}
|
||||
checked={copiesChecked}
|
||||
disabled={!copiesEnabled}
|
||||
onChange={e => setCopiesChecked(e.target.checked)}
|
||||
>
|
||||
<span className="field-title">
|
||||
Create copies of a Master Edition NFT?
|
||||
</span>
|
||||
</Checkbox>
|
||||
{copiesChecked && copiesEnabled && (
|
||||
<>
|
||||
<span className="field-info">
|
||||
Each copy will be given unique edition number e.g. 1 of 30
|
||||
</span>
|
||||
<Input
|
||||
autoFocus
|
||||
className="input"
|
||||
placeholder="Enter number of copies sold"
|
||||
allowClear
|
||||
onChange={info =>
|
||||
props.setAttributes({
|
||||
...props.attributes,
|
||||
editions: parseInt(info.target.value),
|
||||
})
|
||||
}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</label>
|
||||
|
||||
<label className="action-field">
|
||||
<span className="field-title">Price</span>
|
||||
|
|
|
@ -25,7 +25,7 @@ export const AuctionListView = () => {
|
|||
const auctions = useAuctions(AuctionViewState.Live);
|
||||
const auctionsEnded = [
|
||||
...useAuctions(AuctionViewState.Ended),
|
||||
...useAuctions(AuctionViewState.BuyNow).filter((auction) => Number(auction.myBidderPot?.info.emptied) === 0)
|
||||
...useAuctions(AuctionViewState.BuyNow)
|
||||
];
|
||||
const [activeKey, setActiveKey] = useState(LiveAuctionViewState.All);
|
||||
const { isLoading } = useMeta();
|
||||
|
|
Loading…
Reference in New Issue