From 5575cd9bcf065e315929df7955982fb2d0c067eb Mon Sep 17 00:00:00 2001 From: Jordan Prince Date: Sun, 25 Apr 2021 23:04:13 -0500 Subject: [PATCH 1/3] I think im ready to start testing --- .../src/views/auctionCreate/index.tsx | 44 ++++++++++++++----- 1 file changed, 32 insertions(+), 12 deletions(-) diff --git a/packages/metavinci/src/views/auctionCreate/index.tsx b/packages/metavinci/src/views/auctionCreate/index.tsx index ab016c5..0f6d9a0 100644 --- a/packages/metavinci/src/views/auctionCreate/index.tsx +++ b/packages/metavinci/src/views/auctionCreate/index.tsx @@ -31,6 +31,8 @@ import { Metadata, ParsedAccount, deserializeBorsh, + WinnerLimit, + WinnerLimitType, } from '@oyster/common'; import { getAssetCostToStore, LAMPORT_MULTIPLIER } from '../../utils/assets'; import { Connection, ParsedAccountData, PublicKey } from '@solana/web3.js'; @@ -49,7 +51,11 @@ import { WinningConstraint, } from '../../models/metaplex'; import { serialize } from 'borsh'; -import { SafetyDepositDraft } from '../../actions/createAuctionManager'; +import { + createAuctionManager, + SafetyDepositDraft, +} from '../../actions/createAuctionManager'; +import BN from 'bn.js'; const { Step } = Steps; const { Option } = Select; @@ -76,9 +82,6 @@ export interface AuctionState { // listed NFTs items: SafetyDepositDraft[]; - - settings: AuctionManagerSettings; - // number of editions for this auction (only applicable to limited edition) editions?: number; @@ -123,13 +126,6 @@ export const AuctionCreateView = () => { items: [], category: AuctionCategory.Open, saleType: 'auction', - settings: { - openEditionWinnerConstraint: WinningConstraint.NoOpenEdition, - openEditionNonWinningConstraint: NonWinningConstraint.NoOpenEdition, - winningConfigs: [], - openEditionConfig: undefined, - openEditionFixedPrice: undefined, - }, }); useEffect(() => { @@ -143,7 +139,31 @@ export const AuctionCreateView = () => { }; const createAuction = async () => { - // TODO: .... + let settings: AuctionManagerSettings; + if (attributes.category == AuctionCategory.Open) { + settings = { + openEditionWinnerConstraint: WinningConstraint.OpenEditionGiven, + openEditionNonWinningConstraint: NonWinningConstraint.GivenForBidPrice, + winningConfigs: [], + openEditionConfig: 0, + openEditionFixedPrice: undefined, + }; + + const winnerLimit = new WinnerLimit({ type: WinnerLimitType.Unlimited }); + + await createAuctionManager( + connection, + wallet, + settings, + winnerLimit, + new BN((attributes.auctionDuration || 1) * 60), + new BN((attributes.gapTime || 1) * 60), + [attributes.items[0]], + new PublicKey('EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v'), + ); + } else { + throw new Error('Not supported'); + } }; const categoryStep = ( From e658d81eedf5fb4a2ff86ffb012b16d264f98ff6 Mon Sep 17 00:00:00 2001 From: Jordan Prince Date: Sun, 25 Apr 2021 23:52:31 -0500 Subject: [PATCH 2/3] Some more changes --- packages/common/src/actions/metadata.ts | 8 +- .../src/components/AuctionCard/index.tsx | 89 ++++++++++--------- .../src/views/auctionCreate/index.tsx | 47 +++++++--- 3 files changed, 86 insertions(+), 58 deletions(-) diff --git a/packages/common/src/actions/metadata.ts b/packages/common/src/actions/metadata.ts index 7fdfac2..7771d86 100644 --- a/packages/common/src/actions/metadata.ts +++ b/packages/common/src/actions/metadata.ts @@ -529,7 +529,7 @@ export async function createMasterEdition( const metadataAccount = ( await PublicKey.findProgramAddress( [ - Buffer.from('metadata'), + Buffer.from(METADATA_PREFIX), metadataProgramId.toBuffer(), mintKey.toBuffer(), ], @@ -540,7 +540,7 @@ export async function createMasterEdition( const nameSymbolAccount = ( await PublicKey.findProgramAddress( [ - Buffer.from('metadata'), + Buffer.from(METADATA_PREFIX), metadataProgramId.toBuffer(), Buffer.from(name), Buffer.from(symbol), @@ -552,10 +552,10 @@ export async function createMasterEdition( const editionAccount = ( await PublicKey.findProgramAddress( [ - Buffer.from('metadata'), + Buffer.from(METADATA_PREFIX), metadataProgramId.toBuffer(), mintKey.toBuffer(), - Buffer.from('edition'), + Buffer.from(EDITION), ], metadataProgramId, ) diff --git a/packages/metavinci/src/components/AuctionCard/index.tsx b/packages/metavinci/src/components/AuctionCard/index.tsx index 6b56139..db5d2e9 100644 --- a/packages/metavinci/src/components/AuctionCard/index.tsx +++ b/packages/metavinci/src/components/AuctionCard/index.tsx @@ -1,39 +1,33 @@ import React, { useEffect, useState } from 'react'; -import { - Row, - Col, - Divider, - Button, - InputNumber -} from 'antd' +import { Row, Col, Divider, Button, InputNumber } from 'antd'; -import { Auction, Presale } from '../../types' +import { Auction, Presale } from '../../types'; -import './index.less' -import { getCountdown } from '../../utils/utils' +import './index.less'; +import { getCountdown } from '../../utils/utils'; import { shortenAddress } from '@oyster/common'; export const AuctionCard = ({ auction }: { auction: Auction }) => { - const [hours, setHours] = useState(23) - const [minutes, setMinutes] = useState(59) - const [seconds, setSeconds] = useState(59) + const [hours, setHours] = useState(23); + const [minutes, setMinutes] = useState(59); + const [seconds, setSeconds] = useState(59); useEffect(() => { const interval = setInterval(() => { - const { hours, minutes, seconds } = getCountdown(auction.endingTS) + const { hours, minutes, seconds } = getCountdown(auction.endingTS); - setHours(hours) - setMinutes(minutes) - setSeconds(seconds) - }, 1000) - return () => clearInterval(interval) - }, []) + setHours(hours); + setMinutes(minutes); + setSeconds(seconds); + }, 1000); + return () => clearInterval(interval); + }, []); return (
STARTING BID
◎40.00
-
+
AUCTION ENDS IN
@@ -49,13 +43,17 @@ export const AuctionCard = ({ auction }: { auction: Auction }) => {
seconds
-
-
- Any bids placed in the last 15 minutes will extend the auction for another 15 minutes. +
+
+ Any bids placed in the last 15 minutes will extend the auction for + another 15 minutes.

-
+
{ // } /> -
+
Your Balance: ◎ {0.0} (${0.0})
- -
- ) -} + ); +}; export const AuctionBidders = (auctionID: string) => { - const bids = []; - return - {bids.map((bid, index) => { - return {index+1}. {shortenAddress(bid.address)} {bi} - })} - + const bids: any = []; + return ( + + {bids.map((bid: any, index: number) => { + return ( + + {index + 1}. {shortenAddress(bid.address)} + + ); + })} + + ); }; diff --git a/packages/metavinci/src/views/auctionCreate/index.tsx b/packages/metavinci/src/views/auctionCreate/index.tsx index 0f6d9a0..6be99c9 100644 --- a/packages/metavinci/src/views/auctionCreate/index.tsx +++ b/packages/metavinci/src/views/auctionCreate/index.tsx @@ -46,6 +46,7 @@ import { AuctionManagerSettings, AuctionManagerState, AuctionManagerStatus, + EditionType, NonWinningConstraint, SCHEMA, WinningConstraint, @@ -140,6 +141,7 @@ export const AuctionCreateView = () => { const createAuction = async () => { let settings: AuctionManagerSettings; + let winnerLimit: WinnerLimit; if (attributes.category == AuctionCategory.Open) { settings = { openEditionWinnerConstraint: WinningConstraint.OpenEditionGiven, @@ -149,21 +151,42 @@ export const AuctionCreateView = () => { openEditionFixedPrice: undefined, }; - const winnerLimit = new WinnerLimit({ type: WinnerLimitType.Unlimited }); - - await createAuctionManager( - connection, - wallet, - settings, - winnerLimit, - new BN((attributes.auctionDuration || 1) * 60), - new BN((attributes.gapTime || 1) * 60), - [attributes.items[0]], - new PublicKey('EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v'), - ); + winnerLimit = new WinnerLimit({ type: WinnerLimitType.Unlimited }); + } else if (attributes.category == AuctionCategory.Single) { + settings = { + openEditionWinnerConstraint: WinningConstraint.NoOpenEdition, + openEditionNonWinningConstraint: NonWinningConstraint.NoOpenEdition, + winningConfigs: [ + { + safetyDepositBoxIndex: 0, + amount: 1, + hasAuthority: false, + editionType: attributes.items[0].masterEdition + ? EditionType.MasterEdition + : EditionType.NA, + }, + ], + openEditionConfig: undefined, + openEditionFixedPrice: undefined, + }; + winnerLimit = new WinnerLimit({ + type: WinnerLimitType.Capped, + usize: new BN(1), + }); } else { throw new Error('Not supported'); } + + await createAuctionManager( + connection, + wallet, + settings, + winnerLimit, + new BN((attributes.auctionDuration || 1) * 60), + new BN((attributes.gapTime || 1) * 60), + [attributes.items[0]], + new PublicKey('EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v'), + ); }; const categoryStep = ( From 4c89a1667ca7d7be5014c3bcde8f24903355f361 Mon Sep 17 00:00:00 2001 From: Jordan Prince Date: Mon, 26 Apr 2021 03:07:46 -0500 Subject: [PATCH 3/3] Pushing what i've got --- packages/common/src/actions/auction.ts | 32 +++++--- packages/common/src/actions/vault.ts | 8 +- packages/common/src/contexts/connection.tsx | 9 ++- ...dTokensToVault.tsx => addTokensToVault.ts} | 0 .../actions/{closeVault.tsx => closeVault.ts} | 26 ++++-- ...ionManager.tsx => createAuctionManager.ts} | 35 +++++--- .../src/actions/createExternalPriceAccount.ts | 81 +++++++++++++++++++ packages/metavinci/src/actions/createVault.ts | 56 ++----------- .../{makeAuction.tsx => makeAuction.ts} | 0 packages/metavinci/src/hooks/useUserArts.tsx | 7 +- .../metavinci/src/models/metaplex/index.ts | 12 +-- .../src/models/metaplex/initAuctionManager.ts | 14 +++- .../src/models/metaplex/redeemBid.ts | 6 +- .../metaplex/redeemLimitedEditionBid.ts | 5 +- .../models/metaplex/redeemMasterEditionBid.ts | 5 +- .../models/metaplex/redeemOpenEditionBid.ts | 5 +- .../src/models/metaplex/startAuction.ts | 6 +- .../metaplex/validateSafetyDepositBox.ts | 12 +-- .../src/views/auctionCreate/index.tsx | 47 ++++------- 19 files changed, 215 insertions(+), 151 deletions(-) rename packages/metavinci/src/actions/{addTokensToVault.tsx => addTokensToVault.ts} (100%) rename packages/metavinci/src/actions/{closeVault.tsx => closeVault.ts} (90%) rename packages/metavinci/src/actions/{createAuctionManager.tsx => createAuctionManager.ts} (90%) create mode 100644 packages/metavinci/src/actions/createExternalPriceAccount.ts rename packages/metavinci/src/actions/{makeAuction.tsx => makeAuction.ts} (100%) diff --git a/packages/common/src/actions/auction.ts b/packages/common/src/actions/auction.ts index 9d07210..fddeff1 100644 --- a/packages/common/src/actions/auction.ts +++ b/packages/common/src/actions/auction.ts @@ -142,27 +142,30 @@ export class WinnerLimit { class CreateAuctionArgs { instruction: number = 0; /// How many winners are allowed for this auction. See AuctionData. - winners: WinnerLimit; + winnerType: number; + winnerAmount: BN | null; /// The resource being auctioned. See AuctionData. resource: PublicKey; /// End time is the cut-off point that the auction is forced to end by. See AuctionData. - endAuctionAt?: BN; + endAuctionAt: BN | null; /// Gap time is how much time after the previous bid where the auction ends. See AuctionData. - endAuctionGap?: BN; + endAuctionGap: BN | null; /// Token mint for the SPL token used for bidding. tokenMint: PublicKey; /// Authority authority: PublicKey; constructor(args: { - winners: WinnerLimit; + winnerType: number; + winnerAmount: BN | null; resource: PublicKey; - endAuctionAt?: BN; - endAuctionGap?: BN; + endAuctionAt: BN | null; + endAuctionGap: BN | null; tokenMint: PublicKey; authority: PublicKey; }) { - this.winners = args.winners; + this.winnerType = args.winnerType; + this.winnerAmount = args.winnerAmount; this.resource = args.resource; this.endAuctionAt = args.endAuctionAt; this.endAuctionGap = args.endAuctionGap; @@ -198,8 +201,8 @@ export const AUCTION_SCHEMA = new Map([ kind: 'struct', fields: [ ['instruction', 'u8'], - ['winnerLimitType', 'u8'], - ['usize', { kind: 'option', type: 'u64' }], + ['winnerType', 'u8'], + ['winnerAmount', { kind: 'option', type: 'u64' }], ['resource', 'pubkey'], ['endAuctionAt', { kind: 'option', type: 'u64' }], ['endAuctionGap', { kind: 'option', type: 'u64' }], @@ -296,8 +299,8 @@ export const decodeAuctionData = (buffer: Buffer) => { export async function createAuction( winners: WinnerLimit, resource: PublicKey, - endAuctionAt: BN | undefined, - endAuctionGap: BN | undefined, + endAuctionAt: BN | null, + endAuctionGap: BN | null, tokenMint: PublicKey, authority: PublicKey, creator: PublicKey, @@ -309,7 +312,8 @@ export async function createAuction( serialize( AUCTION_SCHEMA, new CreateAuctionArgs({ - winners, + winnerType: winners.type, + winnerAmount: winners.usize == undefined ? null : winners.usize, resource, endAuctionAt, endAuctionGap, @@ -319,6 +323,10 @@ export async function createAuction( ), ); + console.log('Winner', winners); + + console.log('Data', data); + const auctionKey: PublicKey = ( await PublicKey.findProgramAddress( [ diff --git a/packages/common/src/actions/vault.ts b/packages/common/src/actions/vault.ts index f67cb7b..f837bd7 100644 --- a/packages/common/src/actions/vault.ts +++ b/packages/common/src/actions/vault.ts @@ -204,10 +204,7 @@ export const VAULT_SCHEMA = new Map([ kind: 'struct', fields: [ ['instruction', 'u8'], - ['key', 'u8'], - ['pricePerShare', 'u64'], - ['priceMint', 'pubkey'], - ['allowToCombine', 'u8'], + ['externalPriceAccount', ExternalPriceAccount], ], }, ], @@ -251,7 +248,7 @@ export const VAULT_SCHEMA = new Map([ ['key', 'u8'], ['pricePerShare', 'u64'], ['priceMint', 'pubkey'], - ['allowToCombine', 'u8'], + ['allowedToCombine', 'u8'], ], }, ], @@ -671,6 +668,7 @@ export async function updateExternalPriceAccount( const value = new UpdateExternalPriceAccountArgs({ externalPriceAccount }); const data = Buffer.from(serialize(VAULT_SCHEMA, value)); + console.log('Data', data); const keys = [ { diff --git a/packages/common/src/contexts/connection.tsx b/packages/common/src/contexts/connection.tsx index 079149e..8fbebe3 100644 --- a/packages/common/src/contexts/connection.tsx +++ b/packages/common/src/contexts/connection.tsx @@ -487,6 +487,11 @@ export async function sendSignedTransaction({ true, ); + if (confirmation.err) { + console.error(confirmation.err); + throw new Error('Transaction failed: Custom instruction error'); + } + slot = confirmation?.slot || 0; } catch (err) { if (err.timeout) { @@ -580,8 +585,10 @@ async function awaitTransactionSignatureConfirmation( confirmations: 0, }; if (result.err) { + console.log('Rejected via websocket', result.err); reject(result.err); } else { + console.log('Resolved via websocket', result); resolve(result); } }, @@ -624,7 +631,7 @@ async function awaitTransactionSignatureConfirmation( } })(); }) - .catch(_ => { + .catch(err => { //@ts-ignore if (connection._signatureSubscriptions[subId]) connection.removeSignatureListener(subId); diff --git a/packages/metavinci/src/actions/addTokensToVault.tsx b/packages/metavinci/src/actions/addTokensToVault.ts similarity index 100% rename from packages/metavinci/src/actions/addTokensToVault.tsx rename to packages/metavinci/src/actions/addTokensToVault.ts diff --git a/packages/metavinci/src/actions/closeVault.tsx b/packages/metavinci/src/actions/closeVault.ts similarity index 90% rename from packages/metavinci/src/actions/closeVault.tsx rename to packages/metavinci/src/actions/closeVault.ts index 95993d3..20d78da 100644 --- a/packages/metavinci/src/actions/closeVault.tsx +++ b/packages/metavinci/src/actions/closeVault.ts @@ -40,12 +40,6 @@ export async function closeVault( ); let signers: Account[] = []; let instructions: TransactionInstruction[] = []; - const vaultAuthority = ( - await PublicKey.findProgramAddress( - [Buffer.from(VAULT_PREFIX), PROGRAM_IDS.vault.toBuffer()], - PROGRAM_IDS.vault, - ) - )[0]; const auctionKey: PublicKey = ( await PublicKey.findProgramAddress( @@ -70,7 +64,7 @@ export async function closeVault( vault, fractionMint, fractionTreasury, - vaultAuthority, + wallet.publicKey, instructions, ); @@ -92,14 +86,30 @@ export async function closeVault( signers, ); + let transferAuthority = new Account(); + // Shouldn't need to pay anything since we activated vault with 0 shares, but we still // need this setup anyway. - const transferAuthority = approve( + approve( instructions, [], payingTokenAccount, wallet.publicKey, 0, + false, + undefined, + transferAuthority, + ); + + approve( + instructions, + [], + outstandingShareAccount, + wallet.publicKey, + 0, + false, + undefined, + transferAuthority, ); signers.push(transferAuthority); diff --git a/packages/metavinci/src/actions/createAuctionManager.tsx b/packages/metavinci/src/actions/createAuctionManager.ts similarity index 90% rename from packages/metavinci/src/actions/createAuctionManager.tsx rename to packages/metavinci/src/actions/createAuctionManager.ts index b4e1a29..c873e0c 100644 --- a/packages/metavinci/src/actions/createAuctionManager.tsx +++ b/packages/metavinci/src/actions/createAuctionManager.ts @@ -31,6 +31,7 @@ import { createVault } from './createVault'; import { closeVault } from './closeVault'; import { addTokensToVault } from './addTokensToVault'; import { makeAuction } from './makeAuction'; +import { createExternalPriceAccount } from './createExternalPriceAccount'; const { createTokenAccount } = actions; interface normalPattern { @@ -51,6 +52,7 @@ interface byType { makeAuction: normalPattern; initAuctionManager: normalPattern; startAuction: normalPattern; + externalPriceAccount: normalPattern; } export interface SafetyDepositDraft { @@ -77,16 +79,21 @@ export async function createAuctionManager( auction: PublicKey; auctionManager: PublicKey; }> { + const { + externalPriceAccount, + priceMint, + instructions: epaInstructions, + signers: epaSigners, + } = await createExternalPriceAccount(connection, wallet); + const { instructions: createVaultInstructions, signers: createVaultSigners, vault, - externalPriceAccount, fractionalMint, redeemTreasury, fractionTreasury, - priceMint, - } = await createVault(connection, wallet); + } = await createVault(connection, wallet, priceMint, externalPriceAccount); const { instructions: makeAuctionInstructions, @@ -131,6 +138,10 @@ export async function createAuctionManager( } = await addTokensToVault(connection, wallet, vault, nftConfigs); let lookup: byType = { + externalPriceAccount: { + instructions: epaInstructions, + signers: epaSigners, + }, createVault: { instructions: createVaultInstructions, signers: createVaultSigners, @@ -159,6 +170,7 @@ export async function createAuctionManager( }; let signers: Account[][] = [ + lookup.externalPriceAccount.signers, lookup.createVault.signers, ...lookup.addTokens.signers, lookup.closeVault.signers, @@ -168,6 +180,7 @@ export async function createAuctionManager( lookup.startAuction.signers, ]; let instructions: TransactionInstruction[][] = [ + lookup.externalPriceAccount.instructions, lookup.createVault.instructions, ...lookup.addTokens.instructions, lookup.closeVault.instructions, @@ -225,13 +238,13 @@ async function setupAuctionManagerInstructions( vault, openEditionSafetyDeposit?.metadata.pubkey, openEditionSafetyDeposit?.nameSymbol?.pubkey, - wallet.pubkey, + wallet.publicKey, openEditionSafetyDeposit?.masterEdition?.pubkey, openEditionSafetyDeposit?.metadata.info.mint, openEditionSafetyDeposit?.masterEdition?.info.masterMint, - wallet.pubkey, - wallet.pubkey, - wallet.pubkey, + wallet.publicKey, + wallet.publicKey, + wallet.publicKey, acceptPayment, settings, instructions, @@ -282,12 +295,12 @@ async function validateBoxes( safetyDepositBox, stores[i], safetyDeposits[i].metadata.info.mint, - wallet.pubkey, - wallet.pubkey, - wallet.pubkey, + wallet.publicKey, + wallet.publicKey, + wallet.publicKey, tokenInstructions, safetyDeposits[i].masterEdition?.info.masterMint, - safetyDeposits[i].masterEdition ? wallet.pubkey : undefined, + safetyDeposits[i].masterEdition ? wallet.publicKey : undefined, ); signers.push(tokenSigners); diff --git a/packages/metavinci/src/actions/createExternalPriceAccount.ts b/packages/metavinci/src/actions/createExternalPriceAccount.ts new file mode 100644 index 0000000..430cf90 --- /dev/null +++ b/packages/metavinci/src/actions/createExternalPriceAccount.ts @@ -0,0 +1,81 @@ +import { + Account, + Connection, + PublicKey, + SystemProgram, + TransactionInstruction, +} from '@solana/web3.js'; +import { utils, actions, createMint, VAULT_SCHEMA } from '@oyster/common'; + +import { MintLayout } from '@solana/spl-token'; +import BN from 'bn.js'; +const { + updateExternalPriceAccount, + ExternalPriceAccount, + MAX_EXTERNAL_ACCOUNT_SIZE, +} = actions; + +// This command creates the external pricing oracle +export async function createExternalPriceAccount( + connection: Connection, + wallet: any, +): Promise<{ + priceMint: PublicKey; + externalPriceAccount: PublicKey; + instructions: TransactionInstruction[]; + signers: Account[]; +}> { + const PROGRAM_IDS = utils.programIds(); + + let signers: Account[] = []; + let instructions: TransactionInstruction[] = []; + + const mintRentExempt = await connection.getMinimumBalanceForRentExemption( + MintLayout.span, + ); + + const epaRentExempt = await connection.getMinimumBalanceForRentExemption( + MAX_EXTERNAL_ACCOUNT_SIZE, + ); + + let externalPriceAccount = new Account(); + + const priceMint = createMint( + instructions, + wallet.publicKey, + mintRentExempt, + 0, + wallet.publicKey, + wallet.publicKey, + signers, + ); + + let epaStruct = new ExternalPriceAccount({ + pricePerShare: new BN(0), + priceMint: priceMint, + allowedToCombine: true, + }); + + const uninitializedEPA = SystemProgram.createAccount({ + fromPubkey: wallet.publicKey, + newAccountPubkey: externalPriceAccount.publicKey, + lamports: epaRentExempt, + space: MAX_EXTERNAL_ACCOUNT_SIZE, + programId: PROGRAM_IDS.vault, + }); + instructions.push(uninitializedEPA); + signers.push(externalPriceAccount); + + await updateExternalPriceAccount( + externalPriceAccount.publicKey, + epaStruct, + instructions, + ); + + return { + externalPriceAccount: externalPriceAccount.publicKey, + priceMint, + instructions, + signers, + }; +} diff --git a/packages/metavinci/src/actions/createVault.ts b/packages/metavinci/src/actions/createVault.ts index 01ef522..8a28bfb 100644 --- a/packages/metavinci/src/actions/createVault.ts +++ b/packages/metavinci/src/actions/createVault.ts @@ -5,32 +5,23 @@ import { SystemProgram, TransactionInstruction, } from '@solana/web3.js'; -import { contexts, utils, actions, createMint } from '@oyster/common'; +import { utils, actions, createMint } from '@oyster/common'; import { AccountLayout, MintLayout } from '@solana/spl-token'; -import BN from 'bn.js'; -const { - createTokenAccount, - initVault, - updateExternalPriceAccount, - ExternalPriceAccount, - MAX_VAULT_SIZE, - VAULT_PREFIX, - MAX_EXTERNAL_ACCOUNT_SIZE, -} = actions; +const { createTokenAccount, initVault, MAX_VAULT_SIZE, VAULT_PREFIX } = actions; // This command creates the external pricing oracle a vault // This gets the vault ready for adding the tokens. export async function createVault( connection: Connection, wallet: any, + priceMint: PublicKey, + externalPriceAccount: PublicKey, ): Promise<{ vault: PublicKey; - externalPriceAccount: PublicKey; fractionalMint: PublicKey; redeemTreasury: PublicKey; fractionTreasury: PublicKey; - priceMint: PublicKey; instructions: TransactionInstruction[]; signers: Account[]; }> { @@ -51,12 +42,7 @@ export async function createVault( MAX_VAULT_SIZE, ); - const epaRentExempt = await connection.getMinimumBalanceForRentExemption( - MAX_EXTERNAL_ACCOUNT_SIZE, - ); - let vault = new Account(); - let externalPriceAccount = new Account(); const vaultAuthority = ( await PublicKey.findProgramAddress( @@ -74,21 +60,6 @@ export async function createVault( vaultAuthority, signers, ); - const priceMint = createMint( - instructions, - wallet.publicKey, - mintRentExempt, - 0, - vaultAuthority, - vaultAuthority, - signers, - ); - - let epaStruct = new ExternalPriceAccount({ - pricePerShare: new BN(0), - priceMint: priceMint, - allowedToCombine: true, - }); const redeemTreasury = createTokenAccount( instructions, @@ -115,23 +86,8 @@ export async function createVault( space: MAX_VAULT_SIZE, programId: PROGRAM_IDS.vault, }); - const uninitializedEPA = SystemProgram.createAccount({ - fromPubkey: wallet.publicKey, - newAccountPubkey: vault.publicKey, - lamports: epaRentExempt, - space: MAX_EXTERNAL_ACCOUNT_SIZE, - programId: PROGRAM_IDS.vault, - }); instructions.push(uninitializedVault); - instructions.push(uninitializedEPA); signers.push(vault); - signers.push(externalPriceAccount); - - await updateExternalPriceAccount( - externalPriceAccount.publicKey, - epaStruct, - instructions, - ); await initVault( true, @@ -140,17 +96,15 @@ export async function createVault( fractionTreasury, vault.publicKey, wallet.publicKey, - externalPriceAccount.publicKey, + externalPriceAccount, instructions, ); return { vault: vault.publicKey, - externalPriceAccount: externalPriceAccount.publicKey, fractionalMint, redeemTreasury, fractionTreasury, - priceMint, signers, instructions, }; diff --git a/packages/metavinci/src/actions/makeAuction.tsx b/packages/metavinci/src/actions/makeAuction.ts similarity index 100% rename from packages/metavinci/src/actions/makeAuction.tsx rename to packages/metavinci/src/actions/makeAuction.ts diff --git a/packages/metavinci/src/hooks/useUserArts.tsx b/packages/metavinci/src/hooks/useUserArts.tsx index cfff151..1ec723c 100644 --- a/packages/metavinci/src/hooks/useUserArts.tsx +++ b/packages/metavinci/src/hooks/useUserArts.tsx @@ -10,8 +10,11 @@ export const useUserArts = (): SafetyDepositDraft[] => { return prev; }, new Map()); - const ownedMetadata = metadata.filter(m => - accountByMint.has(m.info.mint.toBase58()), + const ownedMetadata = metadata.filter( + m => + accountByMint.has(m.info.mint.toBase58()) && + (accountByMint?.get(m.info.mint.toBase58())?.info?.amount?.toNumber() || + 0) > 0, ); const possibleNameSymbols = ownedMetadata.map(m => diff --git a/packages/metavinci/src/models/metaplex/index.ts b/packages/metavinci/src/models/metaplex/index.ts index 9b49821..76ec495 100644 --- a/packages/metavinci/src/models/metaplex/index.ts +++ b/packages/metavinci/src/models/metaplex/index.ts @@ -65,7 +65,7 @@ export class AuctionManager { export class InitAuctionManagerArgs { instruction = 0; - settings?: AuctionManagerSettings; + settings: AuctionManagerSettings; constructor(args: { settings: AuctionManagerSettings }) { this.settings = args.settings; @@ -102,8 +102,8 @@ export class AuctionManagerSettings { openEditionNonWinningConstraint: NonWinningConstraint = NonWinningConstraint.GivenForFixedPrice; winningConfigs: WinningConfig[] = []; - openEditionConfig?: number = 0; - openEditionFixedPrice?: number = 0; + openEditionConfig: number | null = 0; + openEditionFixedPrice: number | null = 0; constructor(args?: AuctionManagerSettings) { Object.assign(this, args); @@ -196,8 +196,8 @@ export const SCHEMA = new Map([ ['tokenMetadataProgram', 'pubkey'], ['tokenProgram', 'pubkey'], ['acceptPayment', 'pubkey'], - ['state', 'AuctionManagerState'], - ['settings', 'AuctionManagerSettings'], + ['state', AuctionManagerState], + ['settings', AuctionManagerSettings], ], }, ], @@ -265,7 +265,7 @@ export const SCHEMA = new Map([ kind: 'struct', fields: [ ['instruction', 'u8'], - ['manager', 'AuctionManagerSettings'], + ['settings', AuctionManagerSettings], ], }, ], diff --git a/packages/metavinci/src/models/metaplex/initAuctionManager.ts b/packages/metavinci/src/models/metaplex/initAuctionManager.ts index 1e90aa1..37d65e1 100644 --- a/packages/metavinci/src/models/metaplex/initAuctionManager.ts +++ b/packages/metavinci/src/models/metaplex/initAuctionManager.ts @@ -1,4 +1,4 @@ -import { programIds, VAULT_SCHEMA } from '@oyster/common'; +import { programIds } from '@oyster/common'; import { PublicKey, SystemProgram, @@ -11,6 +11,7 @@ import { AuctionManagerSettings, getAuctionKeys, InitAuctionManagerArgs, + SCHEMA, } from '.'; export async function initAuctionManager( @@ -35,7 +36,16 @@ export async function initAuctionManager( settings, }); - const data = Buffer.from(serialize(VAULT_SCHEMA, value)); + const data = Buffer.from(serialize(SCHEMA, value)); + console.log( + 'Auction', + auctionManagerKey, + vault, + auctionKey, + auctionManagerAuthority, + payer, + acceptPaymentAccount, + ); const keys = [ { pubkey: auctionManagerKey, diff --git a/packages/metavinci/src/models/metaplex/redeemBid.ts b/packages/metavinci/src/models/metaplex/redeemBid.ts index a607747..a99834d 100644 --- a/packages/metavinci/src/models/metaplex/redeemBid.ts +++ b/packages/metavinci/src/models/metaplex/redeemBid.ts @@ -1,4 +1,4 @@ -import { programIds, VAULT_SCHEMA, VAULT_PREFIX } from '@oyster/common'; +import { programIds, VAULT_PREFIX } from '@oyster/common'; import { PublicKey, SystemProgram, @@ -8,7 +8,7 @@ import { } from '@solana/web3.js'; import { serialize } from 'borsh'; -import { getAuctionKeys, getBidderKeys, RedeemBidArgs } from '.'; +import { getAuctionKeys, getBidderKeys, RedeemBidArgs, SCHEMA } from '.'; export async function redeemBid( vault: PublicKey, @@ -37,7 +37,7 @@ export async function redeemBid( )[0]; const value = new RedeemBidArgs(); - const data = Buffer.from(serialize(VAULT_SCHEMA, value)); + const data = Buffer.from(serialize(SCHEMA, value)); const keys = [ { pubkey: auctionManagerKey, diff --git a/packages/metavinci/src/models/metaplex/redeemLimitedEditionBid.ts b/packages/metavinci/src/models/metaplex/redeemLimitedEditionBid.ts index e8f546f..154d71f 100644 --- a/packages/metavinci/src/models/metaplex/redeemLimitedEditionBid.ts +++ b/packages/metavinci/src/models/metaplex/redeemLimitedEditionBid.ts @@ -1,4 +1,4 @@ -import { getEdition, programIds, VAULT_SCHEMA } from '@oyster/common'; +import { getEdition, programIds } from '@oyster/common'; import { PublicKey, SystemProgram, @@ -14,6 +14,7 @@ import { getMetadata, getOriginalAuthority, RedeemLimitedEditionBidArgs, + SCHEMA, } from '.'; export async function redeemLimitedEditionBid( @@ -50,7 +51,7 @@ export async function redeemLimitedEditionBid( ); const value = new RedeemLimitedEditionBidArgs(); - const data = Buffer.from(serialize(VAULT_SCHEMA, value)); + const data = Buffer.from(serialize(SCHEMA, value)); const keys = [ { pubkey: auctionManagerKey, diff --git a/packages/metavinci/src/models/metaplex/redeemMasterEditionBid.ts b/packages/metavinci/src/models/metaplex/redeemMasterEditionBid.ts index 562529d..89825a2 100644 --- a/packages/metavinci/src/models/metaplex/redeemMasterEditionBid.ts +++ b/packages/metavinci/src/models/metaplex/redeemMasterEditionBid.ts @@ -1,4 +1,4 @@ -import { programIds, VAULT_SCHEMA, VAULT_PREFIX } from '@oyster/common'; +import { programIds, VAULT_PREFIX } from '@oyster/common'; import { PublicKey, SystemProgram, @@ -13,6 +13,7 @@ import { getBidderKeys, getMetadata, RedeemMasterEditionBidArgs, + SCHEMA, } from '.'; export async function redeemMasterEditionBid( @@ -45,7 +46,7 @@ export async function redeemMasterEditionBid( )[0]; const value = new RedeemMasterEditionBidArgs(); - const data = Buffer.from(serialize(VAULT_SCHEMA, value)); + const data = Buffer.from(serialize(SCHEMA, value)); const keys = [ { pubkey: auctionManagerKey, diff --git a/packages/metavinci/src/models/metaplex/redeemOpenEditionBid.ts b/packages/metavinci/src/models/metaplex/redeemOpenEditionBid.ts index 43cd368..aa64329 100644 --- a/packages/metavinci/src/models/metaplex/redeemOpenEditionBid.ts +++ b/packages/metavinci/src/models/metaplex/redeemOpenEditionBid.ts @@ -1,4 +1,4 @@ -import { getEdition, programIds, VAULT_SCHEMA } from '@oyster/common'; +import { getEdition, programIds } from '@oyster/common'; import { PublicKey, SystemProgram, @@ -13,6 +13,7 @@ import { getBidderKeys, getMetadata, RedeemOpenEditionBidArgs, + SCHEMA, } from '.'; export async function redeemOpenEditionBid( @@ -43,7 +44,7 @@ export async function redeemOpenEditionBid( const masterEdition: PublicKey = await getEdition(tokenMint); const value = new RedeemOpenEditionBidArgs(); - const data = Buffer.from(serialize(VAULT_SCHEMA, value)); + const data = Buffer.from(serialize(SCHEMA, value)); const keys = [ { pubkey: auctionManagerKey, diff --git a/packages/metavinci/src/models/metaplex/startAuction.ts b/packages/metavinci/src/models/metaplex/startAuction.ts index 206a0fd..a8820ae 100644 --- a/packages/metavinci/src/models/metaplex/startAuction.ts +++ b/packages/metavinci/src/models/metaplex/startAuction.ts @@ -1,4 +1,4 @@ -import { programIds, VAULT_SCHEMA } from '@oyster/common'; +import { programIds } from '@oyster/common'; import { PublicKey, SYSVAR_CLOCK_PUBKEY, @@ -6,7 +6,7 @@ import { } from '@solana/web3.js'; import { serialize } from 'borsh'; -import { getAuctionKeys, StartAuctionArgs } from '.'; +import { getAuctionKeys, SCHEMA, StartAuctionArgs } from '.'; export async function startAuction( vault: PublicKey, @@ -18,7 +18,7 @@ export async function startAuction( const { auctionKey, auctionManagerKey } = await getAuctionKeys(vault); const value = new StartAuctionArgs(); - const data = Buffer.from(serialize(VAULT_SCHEMA, value)); + const data = Buffer.from(serialize(SCHEMA, value)); const keys = [ { diff --git a/packages/metavinci/src/models/metaplex/validateSafetyDepositBox.ts b/packages/metavinci/src/models/metaplex/validateSafetyDepositBox.ts index 1af2e29..f29a3eb 100644 --- a/packages/metavinci/src/models/metaplex/validateSafetyDepositBox.ts +++ b/packages/metavinci/src/models/metaplex/validateSafetyDepositBox.ts @@ -1,10 +1,4 @@ -import { - programIds, - VAULT_SCHEMA, - METADATA_PREFIX, - EDITION, - getEdition, -} from '@oyster/common'; +import { programIds, getEdition } from '@oyster/common'; import { PublicKey, SystemProgram, @@ -16,7 +10,7 @@ import { serialize } from 'borsh'; import { getAuctionKeys, getOriginalAuthority, - METAPLEX_PREFIX, + SCHEMA, ValidateSafetyDepositBoxArgs, } from '.'; @@ -46,7 +40,7 @@ export async function validateSafetyDepositBox( const edition: PublicKey = await getEdition(tokenMint); const value = new ValidateSafetyDepositBoxArgs(); - const data = Buffer.from(serialize(VAULT_SCHEMA, value)); + const data = Buffer.from(serialize(SCHEMA, value)); const keys = [ { pubkey: auctionManagerKey, diff --git a/packages/metavinci/src/views/auctionCreate/index.tsx b/packages/metavinci/src/views/auctionCreate/index.tsx index 6be99c9..1796c52 100644 --- a/packages/metavinci/src/views/auctionCreate/index.tsx +++ b/packages/metavinci/src/views/auctionCreate/index.tsx @@ -115,6 +115,7 @@ export interface AuctionState { export const AuctionCreateView = () => { const connection = useConnection(); const { env } = useConnectionConfig(); + const items = useUserArts(); const { wallet, connected } = useWallet(); const { step_param }: { step_param: string } = useParams(); const history = useHistory(); @@ -143,17 +144,17 @@ export const AuctionCreateView = () => { let settings: AuctionManagerSettings; let winnerLimit: WinnerLimit; if (attributes.category == AuctionCategory.Open) { - settings = { + settings = new AuctionManagerSettings({ openEditionWinnerConstraint: WinningConstraint.OpenEditionGiven, openEditionNonWinningConstraint: NonWinningConstraint.GivenForBidPrice, winningConfigs: [], openEditionConfig: 0, - openEditionFixedPrice: undefined, - }; + openEditionFixedPrice: null, + }); winnerLimit = new WinnerLimit({ type: WinnerLimitType.Unlimited }); } else if (attributes.category == AuctionCategory.Single) { - settings = { + settings = new AuctionManagerSettings({ openEditionWinnerConstraint: WinningConstraint.NoOpenEdition, openEditionNonWinningConstraint: NonWinningConstraint.NoOpenEdition, winningConfigs: [ @@ -161,14 +162,14 @@ export const AuctionCreateView = () => { safetyDepositBoxIndex: 0, amount: 1, hasAuthority: false, - editionType: attributes.items[0].masterEdition + editionType: items[0].masterEdition ? EditionType.MasterEdition : EditionType.NA, }, ], - openEditionConfig: undefined, - openEditionFixedPrice: undefined, - }; + openEditionConfig: null, + openEditionFixedPrice: null, + }); winnerLimit = new WinnerLimit({ type: WinnerLimitType.Capped, usize: new BN(1), @@ -184,7 +185,7 @@ export const AuctionCreateView = () => { winnerLimit, new BN((attributes.auctionDuration || 1) * 60), new BN((attributes.gapTime || 1) * 60), - [attributes.items[0]], + [items[0]], new PublicKey('EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v'), ); }; @@ -298,6 +299,7 @@ export const AuctionCreateView = () => { ], [AuctionCategory.Single]: [ ['Category', categoryStep], + ['Copies', copiesStep], ['Price', priceStep], ['Initial Phase', initialStep], ['Ending Phase', endingStep], @@ -465,21 +467,6 @@ const CopiesStep = (props: { ); } - const [selectedItems, setSelectedItems] = useState>( - new Set( - props.attributes.items.map(item => item.metadata.pubkey.toBase58()), - ), - ); - - useEffect(() => { - props.setAttributes({ - ...props.attributes, - items: eligibleItems.filter((item: SafetyDepositDraft) => - selectedItems.has(item.metadata.pubkey.toBase58()), - ), - }); - }, [selectedItems]); - return ( <> @@ -491,14 +478,10 @@ const CopiesStep = (props: { - selectedItems.has(item.metadata.pubkey.toBase58()), - )} - setSelected={items => - setSelectedItems( - new Set(items.map(item => item.metadata.pubkey.toBase58())), - ) - } + selected={props.attributes.items} + setSelected={items => { + props.setAttributes({ ...props.attributes, items }); + }} allowMultiple={false} > Select NFT