Merge pull request #30 from metaplex-foundation/feature/init-store

Init store
This commit is contained in:
B 2021-06-10 23:30:20 -05:00 committed by GitHub
commit 4903342e57
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 138 additions and 50 deletions

View File

@ -64,25 +64,23 @@ export const PROGRAM_IDS = [
]; ];
const getStoreID = async () => { const getStoreID = async () => {
console.log(`STORE_OWNER_ADDRESS: ${STORE_OWNER_ADDRESS}`); console.log(`STORE_OWNER_ADDRESS: ${STORE_OWNER_ADDRESS?.toBase58()}`);
if (!STORE_OWNER_ADDRESS) { if (!STORE_OWNER_ADDRESS) {
return DEFAULT_STORE; return undefined;
} }
if (!STORE) { const programs = await PublicKey.findProgramAddress(
STORE = ( [
await PublicKey.findProgramAddress( Buffer.from('metaplex'),
[ METAPLEX_ID.toBuffer(),
Buffer.from('metaplex'), STORE_OWNER_ADDRESS.toBuffer(),
METAPLEX_ID.toBuffer(), ],
STORE_OWNER_ADDRESS.toBuffer(), METAPLEX_ID,
], );
METAPLEX_ID, const CUSTOM = programs[0];
) console.log(`CUSTOM STORE: ${CUSTOM.toBase58()}`);
)[0];
}
return STORE; return CUSTOM;
}; };
export const setProgramIds = async (envName: string) => { export const setProgramIds = async (envName: string) => {
@ -91,14 +89,12 @@ export const setProgramIds = async (envName: string) => {
return; return;
} }
STORE = await getStoreID(); if (!STORE) {
STORE = await getStoreID();
}
}; };
const DEFAULT_STORE = new PublicKey( let STORE: PublicKey | undefined;
'7KwpjEy7KBpZTBErE3niBUNxWGAQTPo9kZzkgEoP6dfR',
);
let STORE: PublicKey;
export const programIds = () => { export const programIds = () => {
return { return {

1
js/packages/web/.env Normal file
View File

@ -0,0 +1 @@
REACT_APP_STORE_OWNER_ADDRESS_ADDRESS=

View File

@ -1 +1 @@
GENERATE_SOURCEMAP = false GENERATE_SOURCEMAP=false

View File

@ -3,7 +3,6 @@ const CracoAlias = require('craco-alias');
const CracoBabelLoader = require('craco-babel-loader'); const CracoBabelLoader = require('craco-babel-loader');
const path = require('path'); const path = require('path');
const fs = require('fs'); const fs = require('fs');
//console.log('qualified', pnp.resolveRequest('@babel/preset-typescript'), path.resolve(__dirname, '/') + 'src/'); //console.log('qualified', pnp.resolveRequest('@babel/preset-typescript'), path.resolve(__dirname, '/') + 'src/');
// Handle relative paths to sibling packages // Handle relative paths to sibling packages

View File

@ -438,6 +438,11 @@ async function setupAuctionManagerInstructions(
signers: Keypair[]; signers: Keypair[];
auctionManager: PublicKey; auctionManager: PublicKey;
}> { }> {
let store = programIds().store;
if (!store) {
throw new Error('Store not initialized');
}
let signers: Keypair[] = []; let signers: Keypair[] = [];
let instructions: TransactionInstruction[] = []; let instructions: TransactionInstruction[] = [];
@ -457,7 +462,7 @@ async function setupAuctionManagerInstructions(
wallet.publicKey, wallet.publicKey,
wallet.publicKey, wallet.publicKey,
acceptPayment, acceptPayment,
programIds().store, store,
settings, settings,
instructions, instructions,
); );
@ -492,6 +497,11 @@ async function validateParticipationHelper(
participationSafetyDepositDraft: SafetyDepositDraft, participationSafetyDepositDraft: SafetyDepositDraft,
accountRentExempt: number, accountRentExempt: number,
): Promise<{ instructions: TransactionInstruction[]; signers: Keypair[] }> { ): Promise<{ instructions: TransactionInstruction[]; signers: Keypair[] }> {
const store = programIds().store;
if (!store) {
throw new Error('Store not initialized');
}
let instructions: TransactionInstruction[] = []; let instructions: TransactionInstruction[] = [];
let signers: Keypair[] = []; let signers: Keypair[] = [];
const whitelistedCreator = participationSafetyDepositDraft.metadata.info.data const whitelistedCreator = participationSafetyDepositDraft.metadata.info.data
@ -521,7 +531,7 @@ async function validateParticipationHelper(
printingTokenHoldingAccount, printingTokenHoldingAccount,
wallet.publicKey, wallet.publicKey,
whitelistedCreator, whitelistedCreator,
programIds().store, store,
await getSafetyDepositBoxAddress( await getSafetyDepositBoxAddress(
vault, vault,
participationSafetyDepositDraft.masterEdition.info participationSafetyDepositDraft.masterEdition.info
@ -568,6 +578,11 @@ async function validateBoxes(
instructions: TransactionInstruction[][]; instructions: TransactionInstruction[][];
signers: Keypair[][]; signers: Keypair[][];
}> { }> {
const store = programIds().store;
if (!store) {
throw new Error('Store not initialized');
}
let signers: Keypair[][] = []; let signers: Keypair[][] = [];
let instructions: TransactionInstruction[][] = []; let instructions: TransactionInstruction[][] = [];
@ -628,7 +643,7 @@ async function validateBoxes(
tokenInstructions, tokenInstructions,
edition, edition,
whitelistedCreator, whitelistedCreator,
programIds().store, store,
safetyDeposits[i].draft.masterEdition?.info.printingMint, safetyDeposits[i].draft.masterEdition?.info.printingMint,
safetyDeposits[i].draft.masterEdition ? wallet.publicKey : undefined, safetyDeposits[i].draft.masterEdition ? wallet.publicKey : undefined,
); );

View File

@ -2,7 +2,7 @@ import React, { useMemo } from 'react';
import './index.less'; import './index.less';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import { Button, Dropdown, Menu } from 'antd'; import { Button, Dropdown, Menu } from 'antd';
import { ConnectButton, CurrentUserBadge, useWallet } from '@oyster/common'; import { ConnectButton, CurrentUserBadge, useConnection, useWallet } from '@oyster/common';
import { Notifications } from '../Notifications'; import { Notifications } from '../Notifications';
import useWindowDimensions from '../../utils/layout'; import useWindowDimensions from '../../utils/layout';
import { MenuOutlined } from '@ant-design/icons'; import { MenuOutlined } from '@ant-design/icons';

View File

@ -207,7 +207,7 @@ export function MetaProvider({ children = null as any }) {
auctions: {}, auctions: {},
vaults: {}, vaults: {},
payoutTickets: {}, payoutTickets: {},
store: {}, store: undefined,
whitelistedCreatorsByCreator: {}, whitelistedCreatorsByCreator: {},
bidderMetadataByAuctionAndBidder: {}, bidderMetadataByAuctionAndBidder: {},
bidderPotsByAuctionAndBidder: {}, bidderPotsByAuctionAndBidder: {},
@ -295,7 +295,9 @@ export function MetaProvider({ children = null as any }) {
setAuctionManagersByAuction(tempCache.auctionManagersByAuction); setAuctionManagersByAuction(tempCache.auctionManagersByAuction);
setBidRedemptions(tempCache.bidRedemptions); setBidRedemptions(tempCache.bidRedemptions);
setPayoutTickets(tempCache.payoutTickets); setPayoutTickets(tempCache.payoutTickets);
setStore(tempCache.store as any); if (tempCache.store) {
setStore(tempCache.store as any);
}
setWhitelistedCreatorsByCreator(tempCache.whitelistedCreatorsByCreator); setWhitelistedCreatorsByCreator(tempCache.whitelistedCreatorsByCreator);
setIsLoading(false); setIsLoading(false);
@ -645,7 +647,7 @@ const processMetaplexAccounts = async (
if (a.account.owner.toBase58() != programIds().metaplex.toBase58()) return; if (a.account.owner.toBase58() != programIds().metaplex.toBase58()) return;
try { try {
const STORE_ID = programIds().store.toBase58(); const STORE_ID = programIds().store?.toBase58() || '';
if ( if (
a.account.data[0] === MetaplexKey.AuctionManagerV1 || a.account.data[0] === MetaplexKey.AuctionManagerV1 ||
@ -692,7 +694,6 @@ const processMetaplexAccounts = async (
})); }));
} else if (a.account.data[0] === MetaplexKey.StoreV1) { } else if (a.account.data[0] === MetaplexKey.StoreV1) {
const store = decodeStore(a.account.data); const store = decodeStore(a.account.data);
console.log('Found store', store);
const account: ParsedAccount<Store> = { const account: ParsedAccount<Store> = {
pubkey: a.pubkey, pubkey: a.pubkey,
account: a.account, account: a.account,

View File

@ -17,6 +17,10 @@ export async function claimBid(
instructions: TransactionInstruction[], instructions: TransactionInstruction[],
) { ) {
const PROGRAM_IDS = programIds(); const PROGRAM_IDS = programIds();
const store = PROGRAM_IDS.store;
if (!store) {
throw new Error('Store not initialized');
}
const { auctionKey, auctionManagerKey } = await getAuctionKeys(vault); const { auctionKey, auctionManagerKey } = await getAuctionKeys(vault);
@ -72,7 +76,7 @@ export async function claimBid(
isWritable: false, isWritable: false,
}, },
{ {
pubkey: PROGRAM_IDS.store, pubkey: store,
isSigner: false, isSigner: false,
isWritable: false, isWritable: false,
}, },

View File

@ -26,6 +26,10 @@ export async function emptyPaymentAccount(
instructions: TransactionInstruction[], instructions: TransactionInstruction[],
) { ) {
const PROGRAM_IDS = programIds(); const PROGRAM_IDS = programIds();
const store = PROGRAM_IDS.store;
if (!store) {
throw new Error('Store not initialized');
}
const value = new EmptyPaymentAccountArgs({ const value = new EmptyPaymentAccountArgs({
winningConfigIndex, winningConfigIndex,
@ -83,7 +87,7 @@ export async function emptyPaymentAccount(
isWritable: false, isWritable: false,
}, },
{ {
pubkey: PROGRAM_IDS.store, pubkey: store,
isSigner: false, isSigner: false,
isWritable: false, isWritable: false,
}, },

View File

@ -690,12 +690,17 @@ export async function getOriginalAuthority(
export async function getWhitelistedCreator(creator: PublicKey) { export async function getWhitelistedCreator(creator: PublicKey) {
const PROGRAM_IDS = programIds(); const PROGRAM_IDS = programIds();
const store = PROGRAM_IDS.store;
if (!store) {
throw new Error('Store not initialized');
}
return ( return (
await PublicKey.findProgramAddress( await PublicKey.findProgramAddress(
[ [
Buffer.from(METAPLEX_PREFIX), Buffer.from(METAPLEX_PREFIX),
PROGRAM_IDS.metaplex.toBuffer(), PROGRAM_IDS.metaplex.toBuffer(),
PROGRAM_IDS.store.toBuffer(), store.toBuffer(),
creator.toBuffer(), creator.toBuffer(),
], ],
PROGRAM_IDS.metaplex, PROGRAM_IDS.metaplex,

View File

@ -25,6 +25,10 @@ export async function populateParticipationPrintingAccount(
instructions: TransactionInstruction[], instructions: TransactionInstruction[],
) { ) {
const PROGRAM_IDS = programIds(); const PROGRAM_IDS = programIds();
const store = PROGRAM_IDS.store;
if (!store) {
throw new Error('Store not initialized');
}
const transferAuthority: PublicKey = ( const transferAuthority: PublicKey = (
await PublicKey.findProgramAddress( await PublicKey.findProgramAddress(
@ -115,7 +119,7 @@ export async function populateParticipationPrintingAccount(
isWritable: false, isWritable: false,
}, },
{ {
pubkey: PROGRAM_IDS.store, pubkey: store,
isSigner: false, isSigner: false,
isWritable: false, isWritable: false,
}, },

View File

@ -23,6 +23,10 @@ export async function redeemBid(
instructions: TransactionInstruction[], instructions: TransactionInstruction[],
) { ) {
const PROGRAM_IDS = programIds(); const PROGRAM_IDS = programIds();
const store = PROGRAM_IDS.store;
if (!store) {
throw new Error('Store not initialized');
}
const { auctionKey, auctionManagerKey } = await getAuctionKeys(vault); const { auctionKey, auctionManagerKey } = await getAuctionKeys(vault);
@ -116,7 +120,7 @@ export async function redeemBid(
isWritable: false, isWritable: false,
}, },
{ {
pubkey: PROGRAM_IDS.store, pubkey: store,
isSigner: false, isSigner: false,
isWritable: false, isWritable: false,
}, },

View File

@ -27,6 +27,10 @@ export async function redeemFullRightsTransferBid(
newAuthority: PublicKey, newAuthority: PublicKey,
) { ) {
const PROGRAM_IDS = programIds(); const PROGRAM_IDS = programIds();
const store = PROGRAM_IDS.store;
if (!store) {
throw new Error('Store not initialized');
}
const { auctionKey, auctionManagerKey } = await getAuctionKeys(vault); const { auctionKey, auctionManagerKey } = await getAuctionKeys(vault);
@ -120,7 +124,7 @@ export async function redeemFullRightsTransferBid(
isWritable: false, isWritable: false,
}, },
{ {
pubkey: PROGRAM_IDS.store, pubkey: store,
isSigner: false, isSigner: false,
isWritable: false, isWritable: false,
}, },

View File

@ -30,6 +30,10 @@ export async function redeemParticipationBid(
tokenPaymentAccount: PublicKey, tokenPaymentAccount: PublicKey,
) { ) {
const PROGRAM_IDS = programIds(); const PROGRAM_IDS = programIds();
const store = PROGRAM_IDS.store;
if (!store) {
throw new Error('Store not initialized');
}
const { auctionKey, auctionManagerKey } = await getAuctionKeys(vault); const { auctionKey, auctionManagerKey } = await getAuctionKeys(vault);
@ -111,7 +115,7 @@ export async function redeemParticipationBid(
isWritable: false, isWritable: false,
}, },
{ {
pubkey: PROGRAM_IDS.store, pubkey: store,
isSigner: false, isSigner: false,
isWritable: false, isWritable: false,
}, },

View File

@ -15,13 +15,17 @@ export async function setStore(
instructions: TransactionInstruction[], instructions: TransactionInstruction[],
) { ) {
const PROGRAM_IDS = programIds(); const PROGRAM_IDS = programIds();
const store = PROGRAM_IDS.store;
if (!store) {
throw new Error('Store not initialized');
}
const value = new SetStoreArgs({ public: isPublic }); const value = new SetStoreArgs({ public: isPublic });
const data = Buffer.from(serialize(SCHEMA, value)); const data = Buffer.from(serialize(SCHEMA, value));
const keys = [ const keys = [
{ {
pubkey: PROGRAM_IDS.store, pubkey: store,
isSigner: false, isSigner: false,
isWritable: true, isWritable: true,
}, },

View File

@ -16,6 +16,10 @@ export async function setWhitelistedCreator(
instructions: TransactionInstruction[], instructions: TransactionInstruction[],
) { ) {
const PROGRAM_IDS = programIds(); const PROGRAM_IDS = programIds();
const store = PROGRAM_IDS.store;
if (!store) {
throw new Error('Store not initialized');
}
const whitelistedCreatorPDAKey = await getWhitelistedCreator(creator); const whitelistedCreatorPDAKey = await getWhitelistedCreator(creator);
@ -44,7 +48,7 @@ export async function setWhitelistedCreator(
isWritable: false, isWritable: false,
}, },
{ {
pubkey: PROGRAM_IDS.store, pubkey: store,
isSigner: false, isSigner: false,
isWritable: false, isWritable: false,
}, },

View File

@ -14,6 +14,10 @@ export async function startAuction(
instructions: TransactionInstruction[], instructions: TransactionInstruction[],
) { ) {
const PROGRAM_IDS = programIds(); const PROGRAM_IDS = programIds();
const store = PROGRAM_IDS.store;
if (!store) {
throw new Error('Store not initialized');
}
const { auctionKey, auctionManagerKey } = await getAuctionKeys(vault); const { auctionKey, auctionManagerKey } = await getAuctionKeys(vault);
@ -37,7 +41,7 @@ export async function startAuction(
isWritable: false, isWritable: false,
}, },
{ {
pubkey: PROGRAM_IDS.store, pubkey: store,
isSigner: false, isSigner: false,
isWritable: false, isWritable: false,
}, },

View File

@ -7,7 +7,7 @@ import {
} from '@solana/web3.js'; } from '@solana/web3.js';
import { serialize } from 'borsh'; import { serialize } from 'borsh';
import { getAuctionKeys, SCHEMA, ValidateParticipationArgs } from '.'; import { SCHEMA, ValidateParticipationArgs } from '.';
export async function validateParticipation( export async function validateParticipation(
auctionManager: PublicKey, auctionManager: PublicKey,

View File

@ -117,11 +117,16 @@ function InnerAdminView({
connection: Connection; connection: Connection;
wallet: WalletAdapter; wallet: WalletAdapter;
}) { }) {
const [newStore, setNewStore] = useState(new Store(store.info)); const [newStore, setNewStore] = useState(store && store.info && new Store(store.info));
const [updatedCreators, setUpdatedCreators] = useState< const [updatedCreators, setUpdatedCreators] = useState<
Record<string, WhitelistedCreator> Record<string, WhitelistedCreator>
>({}); >({});
if (!store || !newStore) {
return <p>Store is not defined</p>;
}
const uniqueCreators = Object.values(whitelistedCreatorsByCreator).reduce( const uniqueCreators = Object.values(whitelistedCreatorsByCreator).reduce(
(acc: Record<string, WhitelistedCreator>, e) => { (acc: Record<string, WhitelistedCreator>, e) => {
acc[e.info.address.toBase58()] = e.info; acc[e.info.address.toBase58()] = e.info;

View File

@ -9,7 +9,6 @@ import {
Statistic, Statistic,
Progress, Progress,
Spin, Spin,
InputNumber,
Radio, Radio,
Card, Card,
Select, Select,
@ -42,7 +41,6 @@ import {
WinningConstraint, WinningConstraint,
ParticipationConfig, ParticipationConfig,
WinningConfigItem, WinningConfigItem,
WinningConfigState,
} from '../../models/metaplex'; } from '../../models/metaplex';
import moment from 'moment'; import moment from 'moment';
import { import {
@ -59,7 +57,6 @@ import { PlusCircleOutlined } from '@ant-design/icons';
const { Option } = Select; const { Option } = Select;
const { Step } = Steps; const { Step } = Steps;
const { TextArea } = Input;
export enum AuctionCategory { export enum AuctionCategory {
Limited, Limited,

View File

@ -1,5 +1,5 @@
import React, { useState, useMemo } from 'react'; import React, { useState, useMemo } from 'react';
import { Layout, Row, Col, Tabs } from 'antd'; import { Layout, Row, Col, Tabs, Button } from 'antd';
import Masonry from 'react-masonry-css'; import Masonry from 'react-masonry-css';
import { PreSaleBanner } from '../../components/PreSaleBanner'; import { PreSaleBanner } from '../../components/PreSaleBanner';
@ -7,10 +7,13 @@ import { AuctionViewState, useAuctions } from '../../hooks';
import './index.less'; import './index.less';
import { AuctionRenderCard } from '../../components/AuctionRenderCard'; import { AuctionRenderCard } from '../../components/AuctionRenderCard';
import { Link } from 'react-router-dom'; import { Link, useHistory } from 'react-router-dom';
import { CardLoader } from '../../components/MyLoader'; import { CardLoader } from '../../components/MyLoader';
import { useMeta } from '../../contexts'; import { useMeta } from '../../contexts';
import BN from 'bn.js'; import BN from 'bn.js';
import { programIds, useConnection, useWallet } from '@oyster/common';
import { saveAdmin } from '../../actions/saveAdmin';
import { WhitelistedCreator } from '../../models/metaplex';
const { TabPane } = Tabs; const { TabPane } = Tabs;
@ -18,7 +21,11 @@ const { Content } = Layout;
export const HomeView = () => { export const HomeView = () => {
const auctions = useAuctions(AuctionViewState.Live); const auctions = useAuctions(AuctionViewState.Live);
const auctionsEnded = useAuctions(AuctionViewState.Ended); const auctionsEnded = useAuctions(AuctionViewState.Ended);
const { isLoading } = useMeta(); const { isLoading, store } = useMeta();
const [isInitalizingStore, setIsInitalizingStore] = useState(false);
const connection = useConnection();
const history = useHistory();
const { wallet, connect } = useWallet();
const breakpointColumnsObj = { const breakpointColumnsObj = {
default: 4, default: 4,
1100: 3, 1100: 3,
@ -87,8 +94,34 @@ export const HomeView = () => {
</Masonry> </Masonry>
); );
const CURRENT_STORE = programIds().store;
return ( return (
<Layout style={{ margin: 0, marginTop: 30 }}> <Layout style={{ margin: 0, marginTop: 30, alignItems: 'center' }}>
{!store && !isLoading && <>
{!CURRENT_STORE && <p>Store has not been configured please set <em>REACT_APP_STORE_OWNER_ADDRESS_ADDRESS</em> to admin wallet inside <em>packages/web/.env</em> and restart yarn</p>}
{CURRENT_STORE && !wallet?.publicKey && <p><Button type="primary" className="app-btn" onClick={connect}>Connect</Button> to configure store.</p>}
{CURRENT_STORE && wallet?.publicKey && <>
<p>Initializing store will allow you to control list of creators.</p>
<Button className="app-btn" type="primary" loading={isInitalizingStore} disabled={!CURRENT_STORE} onClick={async () => {
if(!wallet?.publicKey) {
return;
}
setIsInitalizingStore(true);
await saveAdmin(connection, wallet, false, [new WhitelistedCreator({
address: wallet?.publicKey,
activated: true,
})]);
history.push('/admin');
window.location.reload();
}}>Init Store</Button>
</>}
</>}
<PreSaleBanner auction={heroAuction} /> <PreSaleBanner auction={heroAuction} />
<Layout> <Layout>
<Content style={{ display: 'flex', flexWrap: 'wrap' }}> <Content style={{ display: 'flex', flexWrap: 'wrap' }}>