Skip to content

Commit

Permalink
feat: add redeem printing v2 action and update instant sale (#91)
Browse files Browse the repository at this point in the history
* feat: add instruction for redeem printing v2 bid

* feat: update redeem printing v2 bid params

* feat: minor refactoring

* feat: add redeem printing v2 action

add redeem printing v2 action and update instant sale to support it

* feat: update readme

* test: add test for transaction

* refactor: fix formatting

* refactor: fix code review comments
kurpav authored Dec 6, 2021

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
1 parent 02712f8 commit fd4a3b3
Showing 14 changed files with 620 additions and 80 deletions.
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -95,7 +95,8 @@ const rates = await new Coingecko().getRate([Currency.AR, Currency.SOL], Currenc
- [ ] Original Authority Lookup
- [ ] Instructions
- [x] RedeemBid
- [ ] RedeemFullRightsTransferBid
- [x] RedeemFullRightsTransferBid
- [x] RedeemPrintingV2Bid
- [x] StartAuction
- [ ] EndAuction
- [x] ClaimBid
@@ -127,7 +128,8 @@ const rates = await new Coingecko().getRate([Currency.AR, Currency.SOL], Currenc
- [ ] Actions (no standalone actions)
- [x] Cancel Bid
- [x] Place Bid
- [x] Redeem Bid
- [x] Redeem Full Rights Transfer Bid
- [x] Redeem Printing V2 Bid
- [x] Instant Sale
- [ ] Vault
- [ ] Accounts
3 changes: 2 additions & 1 deletion src/Account.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { AccountInfo, Commitment, PublicKey, Connection } from '@solana/web3.js';
import { AnyPublicKey } from '@metaplex/types';
import { Buffer } from 'buffer';
import { ERROR_ACCOUNT_NOT_FOUND } from './errors';

export type AccountConstructor<T> = {
new (pubkey: AnyPublicKey, info: AccountInfo<Buffer>): T;
@@ -38,7 +39,7 @@ export class Account<T = unknown> {
static async getInfo(connection: Connection, pubkey: AnyPublicKey) {
const info = await connection.getAccountInfo(new PublicKey(pubkey));
if (!info) {
throw new Error(`Unable to find account: ${pubkey}`);
throw ERROR_ACCOUNT_NOT_FOUND(pubkey);
}

return { ...info, data: Buffer.from(info?.data) };
3 changes: 2 additions & 1 deletion src/actions/index.ts
Original file line number Diff line number Diff line change
@@ -12,7 +12,8 @@ export * from './signMetadata';
export * from './updateMetadata';
export * from './cancelBid';
export * from './placeBid';
export * from './redeemBid';
export * from './redeemFullRightsTransferBid';
export * from './redeemPrintingV2Bid';
export * from './claimBid';
export * from './instantSale';
export * from './burnToken';
118 changes: 50 additions & 68 deletions src/actions/instantSale.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,15 @@
import { PublicKey } from '@solana/web3.js';
import { AccountLayout } from '@solana/spl-token';
import retry from 'async-retry';
import { Wallet } from '../wallet';
import { Connection } from '../Connection';
import { sendTransaction } from './transactions';
import { Auction, AuctionExtended, BidderPot } from '../programs/auction';
import { AuctionManager, SafetyDepositConfig } from '../programs/metaplex';
import { AuctionExtended } from '../programs/auction';
import { AuctionManager, SafetyDepositConfig, WinningConfigType } from '../programs/metaplex';
import { placeBid } from './placeBid';
import { getClaimBidTransactions } from './claimBid';
import { getRedeemBidTransactions } from './redeemBid';
import { claimBid } from './claimBid';
import { Vault } from '../programs/vault/accounts/Vault';
import { Metadata } from '../programs/metadata';
import { getBidRedemptionPDA } from './redeemBid';
import { redeemFullRightsTransferBid } from './redeemFullRightsTransferBid';
import { Account } from '../Account';
import { redeemPrintingV2Bid } from './redeemPrintingV2Bid';

interface IInstantSaleParams {
connection: Connection;
@@ -22,7 +19,7 @@ interface IInstantSaleParams {
}

interface IInstantSaleResponse {
txId: string;
txIds: string[];
}

export const instantSale = async ({
@@ -31,89 +28,74 @@ export const instantSale = async ({
store,
auction,
}: IInstantSaleParams): Promise<IInstantSaleResponse> => {
const txIds = [];
// 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 auctionManagerPDA = await AuctionManager.getPDA(auction);
const manager = await AuctionManager.load(connection, auctionManagerPDA);
const vault = await Vault.load(connection, manager.data.vault);
const {
data: { tokenMint },
} = await Auction.load(connection, auction);
const auctionExtended = await AuctionExtended.getPDA(vault.pubkey);
const acceptPayment = new PublicKey(manager.data.acceptPayment);
const auctionExtendedPDA = await AuctionExtended.getPDA(vault.pubkey);
const {
data: { instantSalePrice },
} = await AuctionExtended.load(connection, auctionExtended);
const auctionTokenMint = new PublicKey(tokenMint);
const bidderPot = await BidderPot.getPDA(auction, bidder);
const fractionMint = new PublicKey(vault.data.fractionMint);
// assuming we have 1 item
} = await AuctionExtended.load(connection, auctionExtendedPDA);
const [safetyDepositBox] = await vault.getSafetyDepositBoxes(connection);
const metadataTokenMint = new PublicKey(safetyDepositBox.data.tokenMint);
const safetyDepositTokenStore = new PublicKey(safetyDepositBox.data.store);
const safetyDepositConfig = await SafetyDepositConfig.getPDA(
auctionManager,
const safetyDepositConfigPDA = await SafetyDepositConfig.getPDA(
auctionManagerPDA,
safetyDepositBox.pubkey,
);
const transferAuthority = await Vault.getPDA(vault.pubkey);
const metadata = await Metadata.getPDA(metadataTokenMint);
const {
data: { winningConfigType },
} = await SafetyDepositConfig.load(connection, safetyDepositConfigPDA);
////

const { bidderPotToken, bidderMeta } = await placeBid({
const {
txId: placeBidTxId,
bidderPotToken,
bidderMeta,
} = await placeBid({
connection,
wallet,
amount: instantSalePrice,
auction,
});
txIds.push(placeBidTxId);

// workaround to wait for bidderMeta to be created
await retry(async (bail) => {
await Account.getInfo(connection, bidderMeta);
});
const bidRedemption = await getBidRedemptionPDA(auction, bidderMeta);

const redeemBatch = await getRedeemBidTransactions({
accountRentExempt,
tokenMint: metadataTokenMint,
bidder,
bidderMeta,
store,
vault: vault.pubkey,
auction,
auctionExtended,
auctionManager,
fractionMint,
safetyDepositTokenStore,
safetyDeposit: safetyDepositBox.pubkey,
bidRedemption,
safetyDepositConfig,
transferAuthority,
metadata,
});
// NOTE: it's divided into 3 transactions since transaction size is restricted
switch (winningConfigType) {
case WinningConfigType.FullRightsTransfer:
const { txId: redeemFullRightsTransferBidTxId } = await redeemFullRightsTransferBid({
connection,
wallet,
store,
auction,
});
txIds.push(redeemFullRightsTransferBidTxId);
break;
case WinningConfigType.PrintingV2:
const { txId: redeemPrintingV2BidTxId } = await redeemPrintingV2Bid({
connection,
wallet,
store,
auction,
});
txIds.push(redeemPrintingV2BidTxId);
break;
default:
throw new Error(`${winningConfigType} winning type isn't supported yet`);
}

const claimBatch = await getClaimBidTransactions({
auctionTokenMint,
bidder,
const { txId: claimBidTxId } = await claimBid({
connection,
wallet,
store,
vault: vault.pubkey,
auction,
auctionExtended,
auctionManager,
acceptPayment,
bidderPot,
bidderPotToken,
});
txIds.push(claimBidTxId);

const txs = [...redeemBatch.toTransactions(), ...claimBatch.toTransactions()];
const signers = [...redeemBatch.signers, ...claimBatch.signers];

const txId = await sendTransaction({
connection,
wallet,
txs,
signers,
});

return { txId };
return { txIds: [placeBidTxId] };
};
Original file line number Diff line number Diff line change
@@ -26,7 +26,7 @@ interface IRedeemBidResponse {
txId: string;
}

export const redeemBid = async ({
export const redeemFullRightsTransferBid = async ({
connection,
wallet,
store,
@@ -54,7 +54,7 @@ export const redeemBid = async ({
const metadata = await Metadata.getPDA(tokenMint);
////

const txBatch = await getRedeemBidTransactions({
const txBatch = await getRedeemFRTBidTransactions({
accountRentExempt,
tokenMint,
bidder,
@@ -103,7 +103,7 @@ interface IRedeemBidTransactionsParams {
metadata: PublicKey;
}

export const getRedeemBidTransactions = async ({
export const getRedeemFRTBidTransactions = async ({
accountRentExempt,
bidder,
tokenMint,
Loading

0 comments on commit fd4a3b3

Please sign in to comment.