mirror of https://github.com/certusone/oyster.git
Bid redemption
This commit is contained in:
parent
0be625108f
commit
09885f6a2f
|
@ -90,6 +90,8 @@ export class AuctionData {
|
|||
|
||||
/// Used for precalculation on the front end, not a backend key
|
||||
auctionManagerKey?: PublicKey;
|
||||
/// Used for precalculation on the front end, not a backend key
|
||||
bidRedemptionKey?: PublicKey;
|
||||
|
||||
constructor(args: {
|
||||
authority: PublicKey;
|
||||
|
|
|
@ -648,7 +648,7 @@ export async function mintNewEditionFromMasterEditionViaToken(
|
|||
const newEdition = await getEdition(newMint);
|
||||
const masterEdition = await getEdition(tokenMint);
|
||||
|
||||
const data = Buffer.from('5');
|
||||
const data = Buffer.from([5]);
|
||||
|
||||
const keys = [
|
||||
{
|
||||
|
|
|
@ -219,7 +219,7 @@ export const VAULT_SCHEMA = new Map<any, any>([
|
|||
['authority', 'pubkey'],
|
||||
['fractionTreasury', 'pubkey'],
|
||||
['redeemTreasury', 'pubkey'],
|
||||
['allowFurtherShareCreation', 'boolean'],
|
||||
['allowFurtherShareCreation', 'u8'],
|
||||
['pricingLookupAddress', 'u8'],
|
||||
['tokenTypeCount', 'u8'],
|
||||
['state', 'u8'],
|
||||
|
|
|
@ -269,7 +269,7 @@ export const sendTransactions = async (
|
|||
const instructions = instructionSet[i];
|
||||
const signers = signersSet[i];
|
||||
|
||||
if(instructions.length === 0) {
|
||||
if (instructions.length === 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -14,6 +14,10 @@ import {
|
|||
createMint,
|
||||
mintNewEditionFromMasterEditionViaToken,
|
||||
SafetyDepositBox,
|
||||
SequenceType,
|
||||
sendTransactions,
|
||||
sendSignedTransaction,
|
||||
sendTransactionWithRetry,
|
||||
} from '@oyster/common';
|
||||
|
||||
import { AccountLayout, MintLayout, Token } from '@solana/spl-token';
|
||||
|
@ -57,9 +61,8 @@ export async function sendRedeemBid(
|
|||
if (winnerIndex != null) {
|
||||
const winningConfig =
|
||||
auctionView.auctionManager.info.settings.winningConfigs[winnerIndex];
|
||||
const item = auctionView.items[winningConfig.safetyDepositBoxIndex];
|
||||
const item = auctionView.items[winnerIndex];
|
||||
const safetyDeposit = item.safetyDeposit;
|
||||
let newTokenAccount: PublicKey | undefined;
|
||||
switch (winningConfig.editionType) {
|
||||
case EditionType.LimitedEdition:
|
||||
await setupRedeemLimitedInstructions(
|
||||
|
@ -109,6 +112,7 @@ export async function sendRedeemBid(
|
|||
(winnerIndex != null &&
|
||||
auctionView.auctionManager.info.settings.openEditionWinnerConstraint !=
|
||||
WinningConstraint.NoOpenEdition);
|
||||
|
||||
if (auctionView.openEditionItem && eligibleForOpenEdition) {
|
||||
const item = auctionView.openEditionItem;
|
||||
const safetyDeposit = item.safetyDeposit;
|
||||
|
@ -124,6 +128,24 @@ export async function sendRedeemBid(
|
|||
instructions,
|
||||
);
|
||||
}
|
||||
|
||||
if (signers.length == 1)
|
||||
await sendTransactionWithRetry(
|
||||
connection,
|
||||
wallet,
|
||||
instructions[0],
|
||||
signers[0],
|
||||
'single',
|
||||
);
|
||||
else
|
||||
await sendTransactions(
|
||||
connection,
|
||||
wallet,
|
||||
instructions,
|
||||
signers,
|
||||
SequenceType.StopOnFailure,
|
||||
'single',
|
||||
);
|
||||
}
|
||||
|
||||
async function setupRedeemInstructions(
|
||||
|
@ -224,11 +246,6 @@ async function setupRedeemLimitedInstructions(
|
|||
signers: Array<Account[]>,
|
||||
instructions: Array<TransactionInstruction[]>,
|
||||
) {
|
||||
let winningPrizeSigner: Account[] = [];
|
||||
let winningPrizeInstructions: TransactionInstruction[] = [];
|
||||
|
||||
signers.push(winningPrizeSigner);
|
||||
instructions.push(winningPrizeInstructions);
|
||||
const updateAuth =
|
||||
item.metadata.info.nonUniqueSpecificUpdateAuthority ||
|
||||
item.nameSymbol?.info.updateAuthority;
|
||||
|
@ -237,39 +254,47 @@ async function setupRedeemLimitedInstructions(
|
|||
let newTokenAccount: PublicKey | undefined = accountsByMint.get(
|
||||
item.masterEdition.info.masterMint.toBase58(),
|
||||
)?.pubkey;
|
||||
if (!newTokenAccount)
|
||||
newTokenAccount = createTokenAccount(
|
||||
winningPrizeInstructions,
|
||||
wallet.publicKey,
|
||||
accountRentExempt,
|
||||
item.masterEdition.info.masterMint,
|
||||
wallet.publicKey,
|
||||
winningPrizeSigner,
|
||||
);
|
||||
const originalAuthorityAcct = await connection.getAccountInfo(
|
||||
await getOriginalAuthority(
|
||||
auctionView.auction.pubkey,
|
||||
item.metadata.pubkey,
|
||||
),
|
||||
);
|
||||
if (originalAuthorityAcct) {
|
||||
const originalAuthority = new PublicKey(
|
||||
originalAuthorityAcct.data.slice(1, 33),
|
||||
);
|
||||
|
||||
await redeemLimitedEditionBid(
|
||||
auctionView.auctionManager.info.vault,
|
||||
safetyDeposit.info.store,
|
||||
newTokenAccount,
|
||||
safetyDeposit.pubkey,
|
||||
auctionView.vault.info.fractionMint,
|
||||
auctionView.myBidderMetadata.info.bidderPubkey,
|
||||
wallet.publicKey,
|
||||
winningPrizeInstructions,
|
||||
originalAuthority,
|
||||
item.metadata.info.mint,
|
||||
item.masterEdition.info.masterMint,
|
||||
if (!auctionView.myBidRedemption?.info.bidRedeemed) {
|
||||
let winningPrizeSigner: Account[] = [];
|
||||
let winningPrizeInstructions: TransactionInstruction[] = [];
|
||||
|
||||
signers.push(winningPrizeSigner);
|
||||
instructions.push(winningPrizeInstructions);
|
||||
if (!newTokenAccount)
|
||||
newTokenAccount = createTokenAccount(
|
||||
winningPrizeInstructions,
|
||||
wallet.publicKey,
|
||||
accountRentExempt,
|
||||
item.masterEdition.info.masterMint,
|
||||
wallet.publicKey,
|
||||
winningPrizeSigner,
|
||||
);
|
||||
const originalAuthorityAcct = await connection.getAccountInfo(
|
||||
await getOriginalAuthority(
|
||||
auctionView.auction.pubkey,
|
||||
item.metadata.pubkey,
|
||||
),
|
||||
);
|
||||
if (originalAuthorityAcct) {
|
||||
const originalAuthority = new PublicKey(
|
||||
originalAuthorityAcct.data.slice(1, 33),
|
||||
);
|
||||
|
||||
await redeemLimitedEditionBid(
|
||||
auctionView.auctionManager.info.vault,
|
||||
safetyDeposit.info.store,
|
||||
newTokenAccount,
|
||||
safetyDeposit.pubkey,
|
||||
auctionView.vault.info.fractionMint,
|
||||
auctionView.myBidderMetadata.info.bidderPubkey,
|
||||
wallet.publicKey,
|
||||
winningPrizeInstructions,
|
||||
originalAuthority,
|
||||
item.metadata.info.mint,
|
||||
item.masterEdition.info.masterMint,
|
||||
);
|
||||
}
|
||||
|
||||
let cashInLimitedPrizeAuthorizationTokenSigner: Account[] = [];
|
||||
let cashInLimitedPrizeAuthorizationTokenInstruction: TransactionInstruction[] = [];
|
||||
|
@ -341,108 +366,116 @@ async function setupRedeemOpenInstructions(
|
|||
signers: Array<Account[]>,
|
||||
instructions: Array<TransactionInstruction[]>,
|
||||
) {
|
||||
let winningPrizeSigner: Account[] = [];
|
||||
let winningPrizeInstructions: TransactionInstruction[] = [];
|
||||
|
||||
signers.push(winningPrizeSigner);
|
||||
instructions.push(winningPrizeInstructions);
|
||||
const updateAuth =
|
||||
item.metadata.info.nonUniqueSpecificUpdateAuthority ||
|
||||
item.nameSymbol?.info.updateAuthority;
|
||||
|
||||
if (item.masterEdition && updateAuth && auctionView.myBidderMetadata) {
|
||||
let newTokenAccount: PublicKey | undefined = accountsByMint.get(
|
||||
item.masterEdition.info.masterMint.toBase58(),
|
||||
)?.pubkey;
|
||||
if (!newTokenAccount)
|
||||
newTokenAccount = createTokenAccount(
|
||||
|
||||
if (!auctionView.myBidRedemption?.info.bidRedeemed) {
|
||||
let winningPrizeSigner: Account[] = [];
|
||||
let winningPrizeInstructions: TransactionInstruction[] = [];
|
||||
|
||||
signers.push(winningPrizeSigner);
|
||||
instructions.push(winningPrizeInstructions);
|
||||
if (!newTokenAccount)
|
||||
newTokenAccount = createTokenAccount(
|
||||
winningPrizeInstructions,
|
||||
wallet.publicKey,
|
||||
accountRentExempt,
|
||||
item.masterEdition.info.masterMint,
|
||||
wallet.publicKey,
|
||||
winningPrizeSigner,
|
||||
);
|
||||
|
||||
const transferAuthority = approve(
|
||||
winningPrizeInstructions,
|
||||
[],
|
||||
auctionView.myBidderMetadata.info.bidderPubkey,
|
||||
wallet.publicKey,
|
||||
accountRentExempt,
|
||||
item.masterEdition.info.masterMint,
|
||||
wallet.publicKey,
|
||||
winningPrizeSigner,
|
||||
auctionView.auctionManager.info.settings.openEditionFixedPrice || 0,
|
||||
);
|
||||
|
||||
const transferAuthority = approve(
|
||||
winningPrizeInstructions,
|
||||
[],
|
||||
auctionView.myBidderMetadata.info.bidderPubkey,
|
||||
wallet.publicKey,
|
||||
auctionView.auctionManager.info.settings.openEditionFixedPrice || 0,
|
||||
);
|
||||
winningPrizeSigner.push(transferAuthority);
|
||||
|
||||
winningPrizeSigner.push(transferAuthority);
|
||||
|
||||
await redeemOpenEditionBid(
|
||||
auctionView.auctionManager.info.vault,
|
||||
safetyDeposit.info.store,
|
||||
newTokenAccount,
|
||||
safetyDeposit.pubkey,
|
||||
auctionView.vault.info.fractionMint,
|
||||
auctionView.myBidderMetadata.info.bidderPubkey,
|
||||
wallet.publicKey,
|
||||
winningPrizeInstructions,
|
||||
item.metadata.info.mint,
|
||||
item.masterEdition.info.masterMint,
|
||||
transferAuthority.publicKey,
|
||||
auctionView.auctionManager.info.acceptPayment,
|
||||
);
|
||||
|
||||
let cashInOpenPrizeAuthorizationTokenSigner: Account[] = [];
|
||||
let cashInOpenPrizeAuthorizationTokenInstruction: TransactionInstruction[] = [];
|
||||
signers.push(cashInOpenPrizeAuthorizationTokenSigner);
|
||||
instructions.push(cashInOpenPrizeAuthorizationTokenInstruction);
|
||||
|
||||
const newOpenEditionMint = createMint(
|
||||
cashInOpenPrizeAuthorizationTokenInstruction,
|
||||
wallet.publicKey,
|
||||
mintRentExempt,
|
||||
0,
|
||||
wallet.publicKey,
|
||||
wallet.publicKey,
|
||||
cashInOpenPrizeAuthorizationTokenSigner,
|
||||
);
|
||||
const newOpenEdition = createTokenAccount(
|
||||
cashInOpenPrizeAuthorizationTokenInstruction,
|
||||
wallet.publicKey,
|
||||
accountRentExempt,
|
||||
newOpenEditionMint,
|
||||
wallet.publicKey,
|
||||
cashInOpenPrizeAuthorizationTokenSigner,
|
||||
);
|
||||
|
||||
cashInOpenPrizeAuthorizationTokenInstruction.push(
|
||||
Token.createMintToInstruction(
|
||||
programIds().token,
|
||||
newOpenEditionMint,
|
||||
newOpenEdition,
|
||||
await redeemOpenEditionBid(
|
||||
auctionView.auctionManager.info.vault,
|
||||
safetyDeposit.info.store,
|
||||
newTokenAccount,
|
||||
safetyDeposit.pubkey,
|
||||
auctionView.vault.info.fractionMint,
|
||||
auctionView.myBidderMetadata.info.bidderPubkey,
|
||||
wallet.publicKey,
|
||||
winningPrizeInstructions,
|
||||
item.metadata.info.mint,
|
||||
item.masterEdition.info.masterMint,
|
||||
transferAuthority.publicKey,
|
||||
auctionView.auctionManager.info.acceptPayment,
|
||||
);
|
||||
}
|
||||
|
||||
if (newTokenAccount) {
|
||||
let cashInOpenPrizeAuthorizationTokenSigner: Account[] = [];
|
||||
let cashInOpenPrizeAuthorizationTokenInstruction: TransactionInstruction[] = [];
|
||||
signers.push(cashInOpenPrizeAuthorizationTokenSigner);
|
||||
instructions.push(cashInOpenPrizeAuthorizationTokenInstruction);
|
||||
|
||||
const newOpenEditionMint = createMint(
|
||||
cashInOpenPrizeAuthorizationTokenInstruction,
|
||||
wallet.publicKey,
|
||||
mintRentExempt,
|
||||
0,
|
||||
wallet.publicKey,
|
||||
wallet.publicKey,
|
||||
cashInOpenPrizeAuthorizationTokenSigner,
|
||||
);
|
||||
const newOpenEdition = createTokenAccount(
|
||||
cashInOpenPrizeAuthorizationTokenInstruction,
|
||||
wallet.publicKey,
|
||||
accountRentExempt,
|
||||
newOpenEditionMint,
|
||||
wallet.publicKey,
|
||||
cashInOpenPrizeAuthorizationTokenSigner,
|
||||
);
|
||||
|
||||
cashInOpenPrizeAuthorizationTokenInstruction.push(
|
||||
Token.createMintToInstruction(
|
||||
programIds().token,
|
||||
newOpenEditionMint,
|
||||
newOpenEdition,
|
||||
wallet.publicKey,
|
||||
[],
|
||||
1,
|
||||
),
|
||||
);
|
||||
|
||||
const burnAuthority = approve(
|
||||
cashInOpenPrizeAuthorizationTokenInstruction,
|
||||
[],
|
||||
newTokenAccount,
|
||||
wallet.publicKey,
|
||||
1,
|
||||
),
|
||||
);
|
||||
);
|
||||
|
||||
const burnAuthority = approve(
|
||||
cashInOpenPrizeAuthorizationTokenInstruction,
|
||||
[],
|
||||
newTokenAccount,
|
||||
wallet.publicKey,
|
||||
1,
|
||||
);
|
||||
cashInOpenPrizeAuthorizationTokenSigner.push(burnAuthority);
|
||||
|
||||
cashInOpenPrizeAuthorizationTokenSigner.push(burnAuthority);
|
||||
|
||||
mintNewEditionFromMasterEditionViaToken(
|
||||
newOpenEditionMint,
|
||||
item.metadata.info.mint,
|
||||
wallet.publicKey,
|
||||
item.masterEdition.info.masterMint,
|
||||
newTokenAccount,
|
||||
burnAuthority.publicKey,
|
||||
updateAuth,
|
||||
cashInOpenPrizeAuthorizationTokenInstruction,
|
||||
wallet.publicKey,
|
||||
);
|
||||
console.log(
|
||||
'My master edition key',
|
||||
item.masterEdition.pubkey.toBase58(),
|
||||
);
|
||||
await mintNewEditionFromMasterEditionViaToken(
|
||||
newOpenEditionMint,
|
||||
item.metadata.info.mint,
|
||||
wallet.publicKey,
|
||||
item.masterEdition.info.masterMint,
|
||||
newTokenAccount,
|
||||
burnAuthority.publicKey,
|
||||
updateAuth,
|
||||
cashInOpenPrizeAuthorizationTokenInstruction,
|
||||
wallet.publicKey,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,8 +13,9 @@ import {
|
|||
hooks,
|
||||
contexts,
|
||||
} from '@oyster/common';
|
||||
import { AuctionView } from '../../hooks';
|
||||
import { AuctionView, AuctionViewState } from '../../hooks';
|
||||
import { sendPlaceBid } from '../../actions/sendPlaceBid';
|
||||
import { sendRedeemBid } from '../../actions/sendRedeemBid';
|
||||
const { useWallet } = contexts.Wallet;
|
||||
export const AuctionCard = ({ auctionView }: { auctionView: AuctionView }) => {
|
||||
const [hours, setHours] = useState<number>(23);
|
||||
|
@ -101,26 +102,42 @@ export const AuctionCard = ({ auctionView }: { auctionView: AuctionView }) => {
|
|||
{myPayingAccount ? myPayingAccount.info.amount.toNumber() : 0.0}
|
||||
</div>
|
||||
|
||||
<Button
|
||||
type="primary"
|
||||
size="large"
|
||||
className="action-btn"
|
||||
disabled={!myPayingAccount || value === undefined}
|
||||
onClick={() => {
|
||||
console.log('Auctionview', auctionView);
|
||||
if (myPayingAccount && value)
|
||||
sendPlaceBid(
|
||||
connection,
|
||||
wallet,
|
||||
myPayingAccount.pubkey,
|
||||
auctionView,
|
||||
value,
|
||||
);
|
||||
}}
|
||||
style={{ marginTop: 20 }}
|
||||
>
|
||||
PLACE BID
|
||||
</Button>
|
||||
{auctionView.state == AuctionViewState.Ended ? (
|
||||
<Button
|
||||
type="primary"
|
||||
size="large"
|
||||
className="action-btn"
|
||||
disabled={!auctionView.myBidderMetadata}
|
||||
onClick={() => {
|
||||
console.log('Auctionview', auctionView);
|
||||
sendRedeemBid(connection, wallet, auctionView, accountByMint);
|
||||
}}
|
||||
style={{ marginTop: 20 }}
|
||||
>
|
||||
REDEEM BID
|
||||
</Button>
|
||||
) : (
|
||||
<Button
|
||||
type="primary"
|
||||
size="large"
|
||||
className="action-btn"
|
||||
disabled={!myPayingAccount || value === undefined}
|
||||
onClick={() => {
|
||||
console.log('Auctionview', auctionView);
|
||||
if (myPayingAccount && value)
|
||||
sendPlaceBid(
|
||||
connection,
|
||||
wallet,
|
||||
myPayingAccount.pubkey,
|
||||
auctionView,
|
||||
value,
|
||||
);
|
||||
}}
|
||||
style={{ marginTop: 20 }}
|
||||
>
|
||||
PLACE BID
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -28,6 +28,8 @@ import {
|
|||
BIDDER_POT_LEN,
|
||||
decodeVault,
|
||||
Vault,
|
||||
TokenAccount,
|
||||
useUserAccounts,
|
||||
} from '@oyster/common';
|
||||
import { MintInfo } from '@solana/spl-token';
|
||||
import { Connection, PublicKey, PublicKeyAndAccount } from '@solana/web3.js';
|
||||
|
@ -36,8 +38,11 @@ import React, { useContext, useEffect, useState } from 'react';
|
|||
import {
|
||||
AuctionManager,
|
||||
AuctionManagerStatus,
|
||||
BidRedemptionTicket,
|
||||
decodeAuctionManager,
|
||||
decodeBidRedemptionTicket,
|
||||
getAuctionManagerKey,
|
||||
getBidderKeys,
|
||||
MetaplexKey,
|
||||
} from '../models/metaplex';
|
||||
|
||||
|
@ -60,6 +65,7 @@ export interface MetaContextState {
|
|||
ParsedAccount<SafetyDepositBox>
|
||||
>;
|
||||
bidderPotsByAuctionAndBidder: Record<string, ParsedAccount<BidderPot>>;
|
||||
bidRedemptions: Record<string, ParsedAccount<BidRedemptionTicket>>;
|
||||
}
|
||||
|
||||
const MetaContext = React.createContext<MetaContextState>({
|
||||
|
@ -74,10 +80,17 @@ const MetaContext = React.createContext<MetaContextState>({
|
|||
bidderMetadataByAuctionAndBidder: {},
|
||||
safetyDepositBoxesByVaultAndIndex: {},
|
||||
bidderPotsByAuctionAndBidder: {},
|
||||
bidRedemptions: {},
|
||||
});
|
||||
|
||||
export function MetaProvider({ children = null as any }) {
|
||||
const connection = useConnection();
|
||||
const { userAccounts } = useUserAccounts();
|
||||
const accountByMint = userAccounts.reduce((prev, acc) => {
|
||||
prev.set(acc.info.mint.toBase58(), acc);
|
||||
return prev;
|
||||
}, new Map<string, TokenAccount>());
|
||||
|
||||
const [metadata, setMetadata] = useState<ParsedAccount<Metadata>[]>([]);
|
||||
const [metadataByMint, setMetadataByMint] = useState<
|
||||
Record<string, ParsedAccount<Metadata>>
|
||||
|
@ -94,6 +107,9 @@ export function MetaProvider({ children = null as any }) {
|
|||
const [auctionManagers, setAuctionManagers] = useState<
|
||||
Record<string, ParsedAccount<AuctionManager>>
|
||||
>({});
|
||||
const [bidRedemptions, setBidRedemptions] = useState<
|
||||
Record<string, ParsedAccount<BidRedemptionTicket>>
|
||||
>({});
|
||||
const [auctions, setAuctions] = useState<
|
||||
Record<string, ParsedAccount<AuctionData>>
|
||||
>({});
|
||||
|
@ -123,6 +139,11 @@ export function MetaProvider({ children = null as any }) {
|
|||
auction.resource,
|
||||
a.pubkey,
|
||||
);
|
||||
const payerAcct = accountByMint.get(auction.tokenMint.toBase58());
|
||||
if (payerAcct)
|
||||
auction.bidRedemptionKey = (
|
||||
await getBidderKeys(a.pubkey, payerAcct.pubkey)
|
||||
).bidRedemption;
|
||||
const account: ParsedAccount<AuctionData> = {
|
||||
pubkey: a.pubkey,
|
||||
account: a.account,
|
||||
|
@ -206,7 +227,7 @@ export function MetaProvider({ children = null as any }) {
|
|||
return () => {
|
||||
dispose();
|
||||
};
|
||||
}, [connection, setAuctions]);
|
||||
}, [connection, setAuctions, userAccounts]);
|
||||
|
||||
useEffect(() => {
|
||||
let dispose = () => {};
|
||||
|
@ -270,7 +291,7 @@ export function MetaProvider({ children = null as any }) {
|
|||
return () => {
|
||||
dispose();
|
||||
};
|
||||
}, [connection, setSafetyDepositBoxesByVaultAndIndex]);
|
||||
}, [connection, setSafetyDepositBoxesByVaultAndIndex, setVaults]);
|
||||
|
||||
useEffect(() => {
|
||||
let dispose = () => {};
|
||||
|
@ -288,6 +309,17 @@ export function MetaProvider({ children = null as any }) {
|
|||
...e,
|
||||
[a.pubkey.toBase58()]: account,
|
||||
}));
|
||||
} else if (a.account.data[0] == MetaplexKey.BidRedemptionTicketV1) {
|
||||
const ticket = await decodeBidRedemptionTicket(a.account.data);
|
||||
const account: ParsedAccount<BidRedemptionTicket> = {
|
||||
pubkey: a.pubkey,
|
||||
account: a.account,
|
||||
info: ticket,
|
||||
};
|
||||
setBidRedemptions(e => ({
|
||||
...e,
|
||||
[a.pubkey.toBase58()]: account,
|
||||
}));
|
||||
}
|
||||
} catch {
|
||||
// ignore errors
|
||||
|
@ -323,7 +355,7 @@ export function MetaProvider({ children = null as any }) {
|
|||
return () => {
|
||||
dispose();
|
||||
};
|
||||
}, [connection, setAuctionManagers]);
|
||||
}, [connection, setAuctionManagers, setBidRedemptions]);
|
||||
|
||||
useEffect(() => {
|
||||
let dispose = () => {};
|
||||
|
@ -452,6 +484,7 @@ export function MetaProvider({ children = null as any }) {
|
|||
bidderMetadataByAuctionAndBidder,
|
||||
bidderPotsByAuctionAndBidder,
|
||||
vaults,
|
||||
bidRedemptions,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
|
|
|
@ -27,6 +27,7 @@ export const useAuction = (id: string) => {
|
|||
bidderPotsByAuctionAndBidder,
|
||||
masterEditions,
|
||||
nameSymbolTuples,
|
||||
bidRedemptions,
|
||||
vaults,
|
||||
} = useMeta();
|
||||
|
||||
|
@ -39,6 +40,7 @@ export const useAuction = (id: string) => {
|
|||
safetyDepositBoxesByVaultAndIndex,
|
||||
metadataByMint,
|
||||
nameSymbolTuples,
|
||||
bidRedemptions,
|
||||
bidderMetadataByAuctionAndBidder,
|
||||
bidderPotsByAuctionAndBidder,
|
||||
masterEditions,
|
||||
|
@ -61,6 +63,7 @@ export const useAuction = (id: string) => {
|
|||
vaults,
|
||||
nameSymbolTuples,
|
||||
masterEditions,
|
||||
bidRedemptions,
|
||||
userAccounts,
|
||||
]);
|
||||
return existingAuctionView;
|
||||
|
|
|
@ -15,7 +15,7 @@ import {
|
|||
} from '@oyster/common';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useMeta } from '../contexts';
|
||||
import { AuctionManager } from '../models/metaplex';
|
||||
import { AuctionManager, BidRedemptionTicket } from '../models/metaplex';
|
||||
|
||||
export enum AuctionViewState {
|
||||
Live = '0',
|
||||
|
@ -41,6 +41,7 @@ export interface AuctionView {
|
|||
thumbnail: AuctionViewItem;
|
||||
myBidderMetadata?: ParsedAccount<BidderMetadata>;
|
||||
myBidderPot?: ParsedAccount<BidderPot>;
|
||||
myBidRedemption?: ParsedAccount<BidRedemptionTicket>;
|
||||
vault: ParsedAccount<Vault>;
|
||||
totallyComplete: boolean;
|
||||
}
|
||||
|
@ -71,6 +72,7 @@ export const useAuctions = (state: AuctionViewState) => {
|
|||
vaults,
|
||||
nameSymbolTuples,
|
||||
masterEditions,
|
||||
bidRedemptions,
|
||||
} = useMeta();
|
||||
|
||||
useEffect(() => {
|
||||
|
@ -84,6 +86,7 @@ export const useAuctions = (state: AuctionViewState) => {
|
|||
safetyDepositBoxesByVaultAndIndex,
|
||||
metadataByMint,
|
||||
nameSymbolTuples,
|
||||
bidRedemptions,
|
||||
bidderMetadataByAuctionAndBidder,
|
||||
bidderPotsByAuctionAndBidder,
|
||||
masterEditions,
|
||||
|
@ -108,6 +111,7 @@ export const useAuctions = (state: AuctionViewState) => {
|
|||
vaults,
|
||||
nameSymbolTuples,
|
||||
masterEditions,
|
||||
bidRedemptions,
|
||||
]);
|
||||
|
||||
return Object.values(auctionViews).filter(v => v) as AuctionView[];
|
||||
|
@ -122,6 +126,7 @@ export function processAccountsIntoAuctionView(
|
|||
>,
|
||||
metadataByMint: Record<string, ParsedAccount<Metadata>>,
|
||||
nameSymbolTuples: Record<string, ParsedAccount<NameSymbolTuple>>,
|
||||
bidRedemptions: Record<string, ParsedAccount<BidRedemptionTicket>>,
|
||||
bidderMetadataByAuctionAndBidder: Record<
|
||||
string,
|
||||
ParsedAccount<BidderMetadata>
|
||||
|
@ -159,6 +164,14 @@ export function processAccountsIntoAuctionView(
|
|||
auctionManagers[auction.info.auctionManagerKey?.toBase58() || ''];
|
||||
if (auctionManager) {
|
||||
const boxesExpected = auctionManager.info.state.winningConfigsValidated;
|
||||
|
||||
let bidRedemption:
|
||||
| ParsedAccount<BidRedemptionTicket>
|
||||
| undefined = undefined;
|
||||
if (auction.info.bidRedemptionKey?.toBase58()) {
|
||||
bidRedemption = bidRedemptions[auction.info.bidRedemptionKey?.toBase58()];
|
||||
}
|
||||
|
||||
const bidderMetadata =
|
||||
bidderMetadataByAuctionAndBidder[
|
||||
auction.pubkey.toBase58() + '-' + myPayingAccount?.pubkey.toBase58()
|
||||
|
@ -173,6 +186,7 @@ export function processAccountsIntoAuctionView(
|
|||
// and only update the two things that could possibly change
|
||||
existingAuctionView.myBidderPot = bidderPot;
|
||||
existingAuctionView.myBidderMetadata = bidderMetadata;
|
||||
existingAuctionView.myBidRedemption = bidRedemption;
|
||||
for (let i = 0; i < existingAuctionView.items.length; i++) {
|
||||
let curr = existingAuctionView.items[i];
|
||||
if (!curr.metadata) {
|
||||
|
@ -256,16 +270,27 @@ export function processAccountsIntoAuctionView(
|
|||
],
|
||||
safetyDeposit:
|
||||
boxes[auctionManager.info.settings.openEditionConfig],
|
||||
masterEdition:
|
||||
masterEditions[
|
||||
metadataByMint[
|
||||
boxes[
|
||||
auctionManager.info.settings.openEditionConfig
|
||||
].info.tokenMint.toBase58()
|
||||
]?.info.masterEdition?.toBase58() || ''
|
||||
],
|
||||
}
|
||||
: undefined,
|
||||
myBidderMetadata: bidderMetadata,
|
||||
myBidderPot: bidderPot,
|
||||
myBidRedemption: bidRedemption,
|
||||
};
|
||||
|
||||
view.thumbnail = (view.items || [])[0] || view.openEditionItem;
|
||||
view.totallyComplete = !!(
|
||||
view.thumbnail &&
|
||||
boxesExpected == (view.items || []).length &&
|
||||
boxesExpected ==
|
||||
(view.items || []).length +
|
||||
(auctionManager.info.settings.openEditionConfig == null ? 0 : 1) &&
|
||||
(auctionManager.info.settings.openEditionConfig == null ||
|
||||
(auctionManager.info.settings.openEditionConfig != null &&
|
||||
view.openEditionItem)) &&
|
||||
|
|
|
@ -145,6 +145,14 @@ export const decodeAuctionManager = (buffer: Buffer) => {
|
|||
return deserializeBorsh(SCHEMA, AuctionManager, buffer) as AuctionManager;
|
||||
};
|
||||
|
||||
export const decodeBidRedemptionTicket = (buffer: Buffer) => {
|
||||
return deserializeBorsh(
|
||||
SCHEMA,
|
||||
BidRedemptionTicket,
|
||||
buffer,
|
||||
) as BidRedemptionTicket;
|
||||
};
|
||||
|
||||
export class WinningConfigState {
|
||||
amountMinted: number = 0;
|
||||
validated: boolean = false;
|
||||
|
@ -362,6 +370,7 @@ export async function getBidderKeys(
|
|||
await PublicKey.findProgramAddress(
|
||||
[
|
||||
Buffer.from(AUCTION_PREFIX),
|
||||
PROGRAM_IDS.auction.toBuffer(),
|
||||
auctionKey.toBuffer(),
|
||||
bidder.toBuffer(),
|
||||
Buffer.from(METADATA),
|
||||
|
|
|
@ -86,7 +86,7 @@ export async function redeemBid(
|
|||
},
|
||||
{
|
||||
pubkey: bidder,
|
||||
isSigner: true,
|
||||
isSigner: false,
|
||||
isWritable: false,
|
||||
},
|
||||
{
|
||||
|
|
|
@ -99,7 +99,7 @@ export async function redeemLimitedEditionBid(
|
|||
},
|
||||
{
|
||||
pubkey: bidder,
|
||||
isSigner: true,
|
||||
isSigner: false,
|
||||
isWritable: false,
|
||||
},
|
||||
{
|
||||
|
|
|
@ -94,7 +94,7 @@ export async function redeemMasterEditionBid(
|
|||
},
|
||||
{
|
||||
pubkey: bidder,
|
||||
isSigner: true,
|
||||
isSigner: false,
|
||||
isWritable: false,
|
||||
},
|
||||
{
|
||||
|
|
|
@ -37,7 +37,6 @@ export async function redeemOpenEditionBid(
|
|||
auctionKey,
|
||||
bidder,
|
||||
);
|
||||
|
||||
const masterMetadata: PublicKey = await getMetadata(tokenMint);
|
||||
|
||||
const masterEdition: PublicKey = await getEdition(tokenMint);
|
||||
|
@ -92,8 +91,8 @@ export async function redeemOpenEditionBid(
|
|||
},
|
||||
{
|
||||
pubkey: bidder,
|
||||
isSigner: true,
|
||||
isWritable: false,
|
||||
isSigner: false,
|
||||
isWritable: true,
|
||||
},
|
||||
{
|
||||
pubkey: payer,
|
||||
|
@ -138,7 +137,7 @@ export async function redeemOpenEditionBid(
|
|||
{
|
||||
pubkey: masterMint,
|
||||
isSigner: false,
|
||||
isWritable: false,
|
||||
isWritable: true,
|
||||
},
|
||||
{
|
||||
pubkey: masterEdition,
|
||||
|
|
Loading…
Reference in New Issue