Skip to content

Commit

Permalink
feat(actions): add redeem and claim bid actions (#55)
Browse files Browse the repository at this point in the history
* feat: add redeem bid action

* feat: add claim bid action
  • Loading branch information
kurpav authored Nov 8, 2021
1 parent 90acbb6 commit b4f13f3
Show file tree
Hide file tree
Showing 5 changed files with 314 additions and 2 deletions.
112 changes: 112 additions & 0 deletions src/actions/claimBid.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
import { PublicKey } from '@solana/web3.js';
import { Wallet } from '../wallet';
import { Connection } from '../Connection';
import { sendTransaction } from './transactions';
import { Auction, AuctionExtended, BidderPot } from '../programs/auction';
import { TransactionsBatch } from '../utils/transactions-batch';
import { AuctionManager, ClaimBid } from '../programs/metaplex';

interface IClaimBidParams {
connection: Connection;
wallet: Wallet;
auction: PublicKey;
store: PublicKey;
bidderPotToken: PublicKey;
}

interface IClaimBidResponse {
txId: string;
}

export const claimBid = async ({
connection,
wallet,
store,
auction,
bidderPotToken,
}: IClaimBidParams): Promise<IClaimBidResponse> => {
// get data for transactions
const bidder = wallet.publicKey;
const auctionManager = await AuctionManager.getPDA(auction);
const manager = await AuctionManager.load(connection, auctionManager);
const vault = new PublicKey(manager.data.vault);
const {
data: { tokenMint },
} = await Auction.load(connection, auction);
const acceptPayment = new PublicKey(manager.data.acceptPayment);
const auctionExtended = await AuctionExtended.getPDA(vault);
const auctionTokenMint = new PublicKey(tokenMint);
const bidderPot = await BidderPot.getPDA(auction, bidder);
////

const txBatch = await getClaimBidTransactions({
auctionTokenMint,
bidder,
store,
vault,
auction,
auctionExtended,
auctionManager,
acceptPayment,
bidderPot,
bidderPotToken,
});

const txId = await sendTransaction({
connection,
wallet,
txs: txBatch.toTransactions(),
signers: txBatch.signers,
});

return { txId };
};

interface IClaimBidTransactionsParams {
bidder: PublicKey;
bidderPotToken?: PublicKey;
bidderPot: PublicKey;
auction: PublicKey;
auctionExtended: PublicKey;
auctionTokenMint: PublicKey;
vault: PublicKey;
store: PublicKey;
auctionManager: PublicKey;
acceptPayment: PublicKey;
}

export const getClaimBidTransactions = async ({
bidder,
auctionTokenMint,
store,
vault,
auction,
auctionManager,
auctionExtended,
acceptPayment,
bidderPot,
bidderPotToken,
}: IClaimBidTransactionsParams) => {
const txBatch = new TransactionsBatch({ transactions: [] });

// create claim bid
const claimBidTransaction = new ClaimBid(
{ feePayer: bidder },
{
store,
vault,
auction,
auctionExtended,
auctionManager,
bidder,
tokenMint: auctionTokenMint,
acceptPayment,
bidderPot,
bidderPotToken,
},
);
txBatch.addTransaction(claimBidTransaction);
////

return txBatch;
};
2 changes: 2 additions & 0 deletions src/actions/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,5 @@ export * from './initStore';
export * from './mintNFT';
export * from './cancelBid';
export * from './placeBid';
export * from './redeemBid';
export * from './claimBid';
184 changes: 184 additions & 0 deletions src/actions/redeemBid.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
import { Keypair, PublicKey } from '@solana/web3.js';
import { AccountLayout } from '@solana/spl-token';
import { Wallet } from '../wallet';
import { Connection } from '../Connection';
import { sendTransaction } from './transactions';
import { AuctionExtended, BidderMetadata } from '../programs/auction';
import { TransactionsBatch } from '../utils/transactions-batch';
import {
AuctionManager,
MetaplexProgram,
RedeemBid,
SafetyDepositConfig,
} from '../programs/metaplex';
import { CreateTokenAccount } from '../programs';
import { Vault } from '../programs/vault';
import { Metadata, UpdatePrimarySaleHappenedViaToken } from '../programs/metadata';

interface IRedeemBidParams {
connection: Connection;
wallet: Wallet;
auction: PublicKey;
store: PublicKey;
}

interface IRedeemBidResponse {
txId: string;
}

export const redeemBid = async ({
connection,
wallet,
store,
auction,
}: IRedeemBidParams): Promise<IRedeemBidResponse> => {
// get data for transactions
const bidder = wallet.publicKey;
const accountRentExempt = await connection.getMinimumBalanceForRentExemption(AccountLayout.span);
const auctionManager = await AuctionManager.getPDA(auction);
const manager = await AuctionManager.load(connection, auctionManager);
const vault = await Vault.load(connection, manager.data.vault);
const fractionMint = new PublicKey(vault.data.fractionMint);
const auctionExtended = await AuctionExtended.getPDA(vault.pubkey);
// assuming we have 1 item
const [safetyDepositBox] = await vault.getSafetyDepositBoxes(connection);
const tokenMint = new PublicKey(safetyDepositBox.data.tokenMint);
const safetyDepositTokenStore = new PublicKey(safetyDepositBox.data.store);
const bidderMeta = await BidderMetadata.getPDA(auction, bidder);
// TODO: probably should be moved to a class
const bidRedemption = (
await PublicKey.findProgramAddress(
[Buffer.from(MetaplexProgram.PREFIX), auction.toBuffer(), bidderMeta.toBuffer()],
MetaplexProgram.PUBKEY,
)
)[0];
const safetyDepositConfig = await SafetyDepositConfig.getPDA(
auctionManager,
safetyDepositBox.pubkey,
);
const transferAuthority = await Vault.getPDA(vault.pubkey);
const metadata = await Metadata.getPDA(tokenMint);
////

const txBatch = await getRedeemBidTransactions({
accountRentExempt,
tokenMint,
bidder,
bidderMeta,
store,
vault: vault.pubkey,
auction,
auctionExtended,
auctionManager,
fractionMint,
safetyDepositTokenStore,
safetyDeposit: safetyDepositBox.pubkey,
bidRedemption,
safetyDepositConfig,
transferAuthority,
metadata,
});

const txId = await sendTransaction({
connection,
wallet,
txs: txBatch.toTransactions(),
signers: txBatch.signers,
});

return { txId };
};

interface IRedeemBidTransactionsParams {
bidder: PublicKey;
accountRentExempt: number;
bidderPotToken?: PublicKey;
bidderMeta: PublicKey;
auction: PublicKey;
auctionExtended: PublicKey;
tokenMint: PublicKey;
vault: PublicKey;
store: PublicKey;
auctionManager: PublicKey;
bidRedemption: PublicKey;
safetyDepositTokenStore: PublicKey;
safetyDeposit: PublicKey;
fractionMint: PublicKey;
safetyDepositConfig: PublicKey;
transferAuthority: PublicKey;
metadata: PublicKey;
}

export const getRedeemBidTransactions = async ({
accountRentExempt,
bidder,
tokenMint,
store,
vault,
auction,
auctionManager,
auctionExtended,
bidRedemption,
bidderMeta: bidMetadata,
safetyDepositTokenStore,
safetyDeposit,
fractionMint,
safetyDepositConfig,
transferAuthority,
metadata,
}: IRedeemBidTransactionsParams) => {
const txBatch = new TransactionsBatch({ transactions: [] });

// create a new account for redeeming
const account = Keypair.generate();
const createDestinationTransaction = new CreateTokenAccount(
{ feePayer: bidder },
{
newAccountPubkey: account.publicKey,
lamports: accountRentExempt,
mint: tokenMint,
},
);
txBatch.addSigner(account);
txBatch.addTransaction(createDestinationTransaction);
////

// create redeem bid
const redeemBidTransaction = new RedeemBid(
{ feePayer: bidder },
{
store,
vault,
auction,
auctionManager,
bidRedemption,
bidderMeta: bidMetadata,
safetyDepositTokenStore,
destination: account.publicKey,
safetyDeposit,
fractionMint,
bidder,
// set to false for now to setup basic flow
isPrintingType: false,
safetyDepositConfig,
auctionExtended,
transferAuthority,
},
);
txBatch.addTransaction(redeemBidTransaction);
////

// update primary sale happened via token
const updatePrimarySaleHappenedViaTokenTransaction = new UpdatePrimarySaleHappenedViaToken(
{ feePayer: bidder },
{
metadata,
owner: bidder,
tokenAccount: account.publicKey,
},
);
txBatch.addTransaction(updatePrimarySaleHappenedViaTokenTransaction);
////

return txBatch;
};
7 changes: 7 additions & 0 deletions src/programs/metaplex/transactions/ClaimBid.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export class ClaimBidArgs extends Borsh.Data {
type ClaimBidParams = {
vault: PublicKey;
auction: PublicKey;
auctionExtended: PublicKey;
auctionManager: PublicKey;
acceptPayment: PublicKey;
bidder: PublicKey;
Expand All @@ -35,6 +36,7 @@ export class ClaimBid extends Transaction {
store,
vault,
auction,
auctionExtended,
auctionManager,
bidder,
bidderPot,
Expand Down Expand Up @@ -109,6 +111,11 @@ export class ClaimBid extends Transaction {
isSigner: false,
isWritable: false,
},
{
pubkey: auctionExtended,
isSigner: false,
isWritable: false,
},
],
programId: MetaplexProgram.PUBKEY,
data,
Expand Down
11 changes: 9 additions & 2 deletions src/programs/metaplex/transactions/RedeemBid.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,14 +44,15 @@ type RedeemBidParams = {
auction: PublicKey;
auctionManager: PublicKey;
bidRedemption: PublicKey;
bidMetadata: PublicKey;
bidderMeta: PublicKey;
safetyDepositTokenStore: PublicKey;
destination: PublicKey;
safetyDeposit: PublicKey;
fractionMint: PublicKey;
bidder: PublicKey;
isPrintingType: boolean;
safetyDepositConfig: PublicKey;
auctionExtended: PublicKey;
transferAuthority: PublicKey;
masterEdition?: PublicKey;
reservationList?: PublicKey;
Expand All @@ -69,9 +70,10 @@ export class RedeemBid extends Transaction {
store,
vault,
auction,
auctionExtended,
auctionManager,
bidRedemption,
bidMetadata,
bidderMeta: bidMetadata,
safetyDepositTokenStore,
destination,
safetyDeposit,
Expand Down Expand Up @@ -190,6 +192,11 @@ export class RedeemBid extends Transaction {
isSigner: false,
isWritable: false,
},
{
pubkey: auctionExtended,
isSigner: false,
isWritable: false,
},
...(isPrintingType && masterEdition && reservationList
? [
{
Expand Down

0 comments on commit b4f13f3

Please sign in to comment.