### Start Docs Development Server Source: https://github.com/metaplex-foundation/metaplex-program-library/blob/master/hydra/program/README.md Navigates to the documentation package directory and starts the development server for the project's documentation. ```shell cd packages/docs yarn start ``` -------------------------------- ### Generate SDK and Start Local Validator Source: https://github.com/metaplex-foundation/metaplex-program-library/blob/master/hydra/program/README.md Generates the SDK from the Anchor IDL and starts a local validator. This command also implicitly runs 'anchor build'. ```shell yarn run api:gen yarn run amman:start ``` -------------------------------- ### Start Local Validator and Run Tests Source: https://github.com/metaplex-foundation/metaplex-program-library/blob/master/hydra/program/README.md Starts the local validator and then runs the project tests. This is a convenient command if the validator is not already running. ```shell yarn run amman:start yarn test ``` -------------------------------- ### Install JS Dependencies Source: https://github.com/metaplex-foundation/metaplex-program-library/blob/master/hydra/program/README.md Installs all JavaScript dependencies for the project using Yarn 3. Ensure you have Node.js and Yarn installed. ```shell yarn ``` -------------------------------- ### Run Local Tests Source: https://github.com/metaplex-foundation/metaplex-program-library/blob/master/hydra/js/README.md Execute these commands to run tests locally. This involves starting Amman, building the project, and then running the tests. ```bash yarn amman:start yarn build yarn test ``` -------------------------------- ### Initialize Fanout, Add Members, and Distribute Revenue Source: https://context7.com/metaplex-foundation/metaplex-program-library/llms.txt Initializes a fanout, adds members with specified share allocations, simulates a revenue deposit, and distributes revenue to a member. Requires a Solana connection and wallet setup. ```typescript import { Connection, Keypair, LAMPORTS_PER_SOL, PublicKey } from '@solana/web3.js'; import { FanoutClient, MembershipModel, Fanout, FanoutMembershipVoucher } from '@metaplex-foundation/mpl-hydra'; import { NodeWallet } from '@project-serum/common'; import { Account } from '@solana/web3.js'; const connection = new Connection('https://api.devnet.solana.com', 'confirmed'); const authority = Keypair.generate(); await connection.requestAirdrop(authority.publicKey, LAMPORTS_PER_SOL * 10); const wallet = new NodeWallet(new Account(authority.secretKey)); const fanoutSdk = new FanoutClient(connection, wallet); // Initialize fanout const { fanout, nativeAccount } = await fanoutSdk.initializeFanout({ totalShares: 100, name: `RevenueSplit${Date.now()}`, membershipModel: MembershipModel.Wallet, }); // Add members with share allocations const member1 = Keypair.generate(); const member2 = Keypair.generate(); const member3 = Keypair.generate(); await fanoutSdk.addMemberWallet({ fanout, fanoutNativeAccount: nativeAccount, membershipKey: member1.publicKey, shares: 50, // 50% share }); await fanoutSdk.addMemberWallet({ fanout, fanoutNativeAccount: nativeAccount, membershipKey: member2.publicKey, shares: 30, // 30% share }); await fanoutSdk.addMemberWallet({ fanout, fanoutNativeAccount: nativeAccount, membershipKey: member3.publicKey, shares: 20, // 20% share }); // Verify fanout state const fanoutAccount = await fanoutSdk.fetch(fanout, Fanout); console.log('Members added:', fanoutAccount.totalMembers.toString()); // "3" console.log('Available shares:', fanoutAccount.totalAvailableShares.toString()); // "0" // Simulate revenue deposit to the fanout holding account const depositAmount = 10 * LAMPORTS_PER_SOL; await connection.requestAirdrop(fanoutAccount.accountKey, depositAmount); // Distribute revenue to member1 (50% = 5 SOL) const distributionBot = Keypair.generate(); await connection.requestAirdrop(distributionBot.publicKey, LAMPORTS_PER_SOL); const distResult = await fanoutSdk.distributeWalletMemberInstructions({ distributeForMint: false, member: member1.publicKey, fanout, payer: distributionBot.publicKey, }); await fanoutSdk.sendInstructions( distResult.instructions, [distributionBot], distributionBot.publicKey ); // Check member1 balance const member1Balance = await connection.getBalance(member1.publicKey); console.log(`Member1 received: ${member1Balance / LAMPORTS_PER_SOL} SOL`); // Output: Member1 received: 5 SOL ``` -------------------------------- ### Install mpl-nft-packs Package Source: https://github.com/metaplex-foundation/metaplex-program-library/blob/master/nft-packs/js/README.md Install the mpl-nft-packs package using npm. This command adds the package as a dependency to your project. ```shell npm install @metaplex-foundation/mpl-nft-packs --save ``` -------------------------------- ### Create Fixed Price Sale Store and Market Source: https://context7.com/metaplex-foundation/metaplex-program-library/llms.txt Use this to create a store and a market for selling NFTs at a fixed price. Ensure you have the necessary connection and payer setup. ```typescript import { Connection, Keypair, PublicKey, Transaction, LAMPORTS_PER_SOL } from '@solana/web3.js'; import { NATIVE_MINT } from '@solana/spl-token'; import { createCreateStoreInstruction, createCreateMarketInstruction, CreateStoreInstructionArgs, CreateMarketInstructionArgs, } from '@metaplex-foundation/mpl-fixed-price-sale'; const connection = new Connection('https://api.devnet.solana.com', 'confirmed'); const payer = Keypair.generate(); const store = Keypair.generate(); const market = Keypair.generate(); // Create store const storeArgs: CreateStoreInstructionArgs = { name: 'My NFT Store', description: 'A store for selling digital art', }; const storeInstruction = createCreateStoreInstruction( { admin: payer.publicKey, store: store.publicKey, }, storeArgs ); const storeTransaction = new Transaction().add(storeInstruction); storeTransaction.feePayer = payer.publicKey; storeTransaction.recentBlockhash = (await connection.getRecentBlockhash()).blockhash; storeTransaction.sign(payer, store); await connection.sendRawTransaction(storeTransaction.serialize()); console.log(`Store created: ${store.publicKey.toBase58()}`); // Create market with fixed price const sellingResource = new PublicKey('SELLING_RESOURCE_ADDRESS'); const treasuryHolder = Keypair.generate(); const FIXED_PRICE_SALE_PROGRAM_ID = new PublicKey('SaLeTjyUa5wXHnGuewUSyJ5JWZaHwz3TxqUntCE9czo'); const [treasuryOwner, treasuryOwnerBump] = await PublicKey.findProgramAddress( [ Buffer.from('holder'), NATIVE_MINT.toBuffer(), sellingResource.toBuffer(), ], FIXED_PRICE_SALE_PROGRAM_ID ); const marketArgs: CreateMarketInstructionArgs = { treasuryOwnerBump, name: 'Limited Edition Drop', description: 'Exclusive NFT collection', mutable: true, price: BigInt(2 * LAMPORTS_PER_SOL), // 2 SOL per NFT piecesInOneWallet: 3n, // Max 3 per wallet startDate: BigInt(Math.floor(Date.now() / 1000)), // Start now endDate: BigInt(Math.floor(Date.now() / 1000) + 86400 * 7), // End in 7 days gatingConfig: null, }; const marketInstruction = createCreateMarketInstruction( { market: market.publicKey, store: store.publicKey, sellingResourceOwner: payer.publicKey, sellingResource, mint: NATIVE_MINT, treasuryHolder: treasuryHolder.publicKey, owner: treasuryOwner, }, marketArgs ); const marketTransaction = new Transaction().add(marketInstruction); marketTransaction.feePayer = payer.publicKey; marketTransaction.recentBlockhash = (await connection.getRecentBlockhash()).blockhash; marketTransaction.sign(payer, market); await connection.sendRawTransaction(marketTransaction.serialize()); console.log(`Market created: ${market.publicKey.toBase58()}`); ``` -------------------------------- ### Generate API SDK Source: https://github.com/metaplex-foundation/metaplex-program-library/blob/master/nft-packs/js/README.md Run this command to update the generated SDK when the Rust contract has been updated. Ensure you have yarn installed. ```shell yarn gen:api ``` -------------------------------- ### Build Program and Generate SDK Source: https://github.com/metaplex-foundation/metaplex-program-library/blob/master/hydra/program/README.md A streamlined workflow to build the Hydra program, generate the SDK, and start the local validator. 'anchor build' is optional as 'yarn run api:gen' includes it. ```shell anchor build //Optional as the next commant runs anchor build for you yarn run api:gen yarn run amman:start ``` -------------------------------- ### Watch SDK Changes Source: https://github.com/metaplex-foundation/metaplex-program-library/blob/master/hydra/program/README.md Starts a watcher that automatically rebuilds the SDK when changes are detected in the 'packages/sdk' folder. This is useful for continuous SDK development. ```shell yarn run watch ``` -------------------------------- ### Run Mega Test Command Source: https://github.com/metaplex-foundation/metaplex-program-library/blob/master/hydra/program/README.md A shortcut command that starts the local validator and runs all tests in a single step, designed for maximum efficiency. ```shell yarn run mega-test ``` -------------------------------- ### Mint NFT with Candy Machine Source: https://context7.com/metaplex-foundation/metaplex-program-library/llms.txt Mints an NFT from a Candy Machine. Requires setup of connection, payer, and program IDs. Derives PDAs for candy machine creator, metadata, and master edition. Sends a raw transaction to mint the NFT. ```typescript import { Connection, Keypair, PublicKey, Transaction, SYSVAR_CLOCK_PUBKEY, SYSVAR_RECENT_BLOCKHASHES_PUBKEY, SYSVAR_INSTRUCTIONS_PUBKEY } from '@solana/web3.js'; import { createMintNftInstruction, MintNftInstructionArgs, } from '@metaplex-foundation/mpl-candy-machine'; const connection = new Connection('https://api.devnet.solana.com', 'confirmed'); const payer = Keypair.generate(); const mint = Keypair.generate(); const CANDY_MACHINE_PROGRAM_ID = new PublicKey('cndy3Z4yapfJBmL3ShUp5exZKqR3z33thTzeNMm2gRZ'); const TOKEN_METADATA_PROGRAM_ID = new PublicKey('metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s'); const candyMachine = new PublicKey('CANDY_MACHINE_ADDRESS'); const wallet = new PublicKey('TREASURY_WALLET_ADDRESS'); // Derive PDAs const [candyMachineCreator, creatorBump] = await PublicKey.findProgramAddress( [Buffer.from('candy_machine'), candyMachine.toBuffer()], CANDY_MACHINE_PROGRAM_ID ); const [metadata] = await PublicKey.findProgramAddress( [Buffer.from('metadata'), TOKEN_METADATA_PROGRAM_ID.toBuffer(), mint.publicKey.toBuffer()], TOKEN_METADATA_PROGRAM_ID ); const [masterEdition] = await PublicKey.findProgramAddress( [ Buffer.from('metadata'), TOKEN_METADATA_PROGRAM_ID.toBuffer(), mint.publicKey.toBuffer(), Buffer.from('edition'), ], TOKEN_METADATA_PROGRAM_ID ); const args: MintNftInstructionArgs = { creatorBump, }; const instruction = createMintNftInstruction( { candyMachine, candyMachineCreator, payer: payer.publicKey, wallet, metadata, mint: mint.publicKey, mintAuthority: payer.publicKey, updateAuthority: payer.publicKey, masterEdition, tokenMetadataProgram: TOKEN_METADATA_PROGRAM_ID, clock: SYSVAR_CLOCK_PUBKEY, recentBlockhashes: SYSVAR_RECENT_BLOCKHASHES_PUBKEY, instructionSysvarAccount: SYSVAR_INSTRUCTIONS_PUBKEY, }, args ); const transaction = new Transaction().add(instruction); transaction.feePayer = payer.publicKey; transaction.recentBlockhash = (await connection.getRecentBlockhash()).blockhash; transaction.sign(payer, mint); const signature = await connection.sendRawTransaction(transaction.serialize()); console.log(`NFT minted: ${mint.publicKey.toBase58()}`); // Output: NFT minted: 7nE1GmnMm... ``` -------------------------------- ### Create a Store Source: https://github.com/metaplex-foundation/metaplex-program-library/blob/master/fixed-price-sale/cli/README.md Command to create a new store for fixed-price sales. Requires a name and description. ```bash ~ $: ./mpl-fixed-price-sale-cli create-store --name example1 --description example2 ``` -------------------------------- ### Build All Programs Source: https://github.com/metaplex-foundation/metaplex-program-library/blob/master/README.md Execute this script with 'all' to build all available programs. ```bash ./build.sh all ``` -------------------------------- ### Initialize Selling Resource Source: https://github.com/metaplex-foundation/metaplex-program-library/blob/master/fixed-price-sale/cli/README.md Command to initialize a selling resource. Requires the store address, resource mint, and resource token addresses. ```bash ~ $: ./mpl-fixed-price-sale-cli init-selling-resource --store 'STORE_ADDRESS' --resource_mint 'EDITION_MINT' --resource_token 'EDITION_TOKEN' ``` -------------------------------- ### Build Token Metadata Source: https://github.com/metaplex-foundation/metaplex-program-library/blob/master/auction-house/program/README.md Builds the token-metadata program to generate the mpl-token-metadata.so file required for testing. ```bash cargo build-bpf --bpf-out-dir ../../test-programs/ ``` -------------------------------- ### Create Fixed Price Market Source: https://github.com/metaplex-foundation/metaplex-program-library/blob/master/fixed-price-sale/cli/README.md Command to create a fixed-price sale market. Requires the selling resource address, name, description, and price. The market can be mutable or immutable. ```bash ~ $: ./mpl-fixed-price-sale-cli create-market --selling_resource 'SELLING_RESOURCE_ADDRESS' --name example3 --description example4 --mutable false --price 1.0 ``` -------------------------------- ### Transfer Shares Between Fanout Members Source: https://context7.com/metaplex-foundation/metaplex-program-library/llms.txt Transfers a specified number of shares from one fanout member to another, updating their respective revenue distribution ratios. Requires a Solana connection and wallet setup. ```typescript import { Connection, Keypair, LAMPORTS_PER_SOL } from '@solana/web3.js'; import { FanoutClient, MembershipModel, FanoutMembershipVoucher } from '@metaplex-foundation/mpl-hydra'; import { NodeWallet } from '@project-serum/common'; import { Account } from '@solana/web3.js'; const connection = new Connection('https://api.devnet.solana.com', 'confirmed'); const authority = Keypair.generate(); await connection.requestAirdrop(authority.publicKey, LAMPORTS_PER_SOL * 10); const wallet = new NodeWallet(new Account(authority.secretKey)); const fanoutSdk = new FanoutClient(connection, wallet); // Setup fanout with members const { fanout, nativeAccount } = await fanoutSdk.initializeFanout({ totalShares: 100, name: `ShareTransfer${Date.now()}`, membershipModel: MembershipModel.Wallet, }); const member1 = Keypair.generate(); const member2 = Keypair.generate(); await fanoutSdk.addMemberWallet({ fanout, fanoutNativeAccount: nativeAccount, membershipKey: member1.publicKey, shares: 60, }); await fanoutSdk.addMemberWallet({ fanout, fanoutNativeAccount: nativeAccount, membershipKey: member2.publicKey, shares: 40, }); // Transfer 20 shares from member1 to member2 await fanoutSdk.transferShares({ fanout, fromMember: member1.publicKey, toMember: member2.publicKey, shares: 20, }); // Verify updated shares const [member1Voucher] = await FanoutClient.membershipVoucher(fanout, member1.publicKey); const [member2Voucher] = await FanoutClient.membershipVoucher(fanout, member2.publicKey); const member1Data = await fanoutSdk.fetch( member1Voucher, FanoutMembershipVoucher ); const member2Data = await fanoutSdk.fetch( member2Voucher, FanoutMembershipVoucher ); console.log(`Member1 shares: ${member1Data.shares.toString()}`); // "40" console.log(`Member2 shares: ${member2Data.shares.toString()}`); // "60" ``` -------------------------------- ### Create Buy Order/Bid Instruction Source: https://context7.com/metaplex-foundation/metaplex-program-library/llms.txt Use this snippet to create a buy order for an NFT. Ensure all account addresses and program IDs are correctly set. The buyer's funds are deposited into an escrow account. ```typescript import { Connection, Keypair, PublicKey, Transaction, LAMPORTS_PER_SOL } from '@solana/web3.js'; import { NATIVE_MINT, getAssociatedTokenAddress } from '@solana/spl-token'; import { createBuyInstruction, BuyInstructionArgs, BuyInstructionAccounts } from '@metaplex-foundation/mpl-auction-house'; const connection = new Connection('https://api.devnet.solana.com', 'confirmed'); const buyer = Keypair.generate(); const AUCTION_HOUSE_PROGRAM_ID = new PublicKey('hausS13jsjafwWwGqZTUQRmWyvyxn9EQpqMwV1PBBmk'); // NFT and auction house details const nftMint = new PublicKey('NFT_MINT_ADDRESS'); const sellerTokenAccount = new PublicKey('SELLER_TOKEN_ACCOUNT'); const auctionHouse = new PublicKey('AUCTION_HOUSE_ADDRESS'); const auctionHouseFeeAccount = new PublicKey('FEE_ACCOUNT_ADDRESS'); const authority = new PublicKey('AUCTION_HOUSE_AUTHORITY'); const treasuryMint = NATIVE_MINT; // Derive metadata PDA const TOKEN_METADATA_PROGRAM_ID = new PublicKey('metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s'); const [metadata] = await PublicKey.findProgramAddress( [Buffer.from('metadata'), TOKEN_METADATA_PROGRAM_ID.toBuffer(), nftMint.toBuffer()], TOKEN_METADATA_PROGRAM_ID ); // Bid price in lamports (1 SOL) const buyerPrice = BigInt(1 * LAMPORTS_PER_SOL); const tokenSize = 1n; // Derive escrow payment account const [escrowPaymentAccount, escrowPaymentBump] = await PublicKey.findProgramAddress( [ Buffer.from('auction_house'), auctionHouse.toBuffer(), buyer.publicKey.toBuffer(), ], AUCTION_HOUSE_PROGRAM_ID ); // Derive buyer trade state const [buyerTradeState, tradeStateBump] = await PublicKey.findProgramAddress( [ Buffer.from('auction_house'), buyer.publicKey.toBuffer(), auctionHouse.toBuffer(), sellerTokenAccount.toBuffer(), treasuryMint.toBuffer(), nftMint.toBuffer(), Buffer.from(buyerPrice.toString(16).padStart(16, '0'), 'hex'), Buffer.from(tokenSize.toString(16).padStart(16, '0'), 'hex'), ], AUCTION_HOUSE_PROGRAM_ID ); const accounts: BuyInstructionAccounts = { wallet: buyer.publicKey, paymentAccount: buyer.publicKey, transferAuthority: buyer.publicKey, treasuryMint, tokenAccount: sellerTokenAccount, metadata, escrowPaymentAccount, authority, auctionHouse, auctionHouseFeeAccount, buyerTradeState, }; const args: BuyInstructionArgs = { tradeStateBump, escrowPaymentBump, buyerPrice, tokenSize, }; const instruction = createBuyInstruction(accounts, args); const transaction = new Transaction().add(instruction); transaction.feePayer = buyer.publicKey; transaction.recentBlockhash = (await connection.getRecentBlockhash()).blockhash; transaction.sign(buyer); const signature = await connection.sendRawTransaction(transaction.serialize()); console.log(`Bid placed: ${signature}`); ``` -------------------------------- ### Initialize Candy Machine V2 Source: https://context7.com/metaplex-foundation/metaplex-program-library/llms.txt Creates a new Candy Machine V2 with configurable parameters. Ensure the payer has sufficient SOL for transaction fees and the treasury wallet is correctly set. ```typescript import { Connection, Keypair, PublicKey, Transaction, LAMPORTS_PER_SOL } from '@solana/web3.js'; import { createInitializeCandyMachineInstruction, InitializeCandyMachineInstructionArgs, CandyMachineData, } from '@metaplex-foundation/mpl-candy-machine'; const connection = new Connection('https://api.devnet.solana.com', 'confirmed'); const payer = Keypair.generate(); const authority = payer; const candyMachine = Keypair.generate(); const wallet = payer.publicKey; // Treasury wallet const candyMachineData: CandyMachineData = { uuid: 'abc123', // 6 character identifier price: BigInt(0.5 * LAMPORTS_PER_SOL), // 0.5 SOL per mint symbol: 'CNDY', sellerFeeBasisPoints: 500, // 5% royalty maxSupply: 10000n, isMutable: true, retainAuthority: true, goLiveDate: BigInt(Math.floor(Date.now() / 1000) + 3600), // 1 hour from now endSettings: null, creators: [ { address: authority.publicKey, verified: false, share: 100, }, ], hiddenSettings: null, whitelistMintSettings: null, itemsAvailable: 10000n, gatekeeper: null, }; const args: InitializeCandyMachineInstructionArgs = { data: candyMachineData, }; const instruction = createInitializeCandyMachineInstruction( { candyMachine: candyMachine.publicKey, wallet, authority: authority.publicKey, payer: payer.publicKey, }, args ); const transaction = new Transaction().add(instruction); transaction.feePayer = payer.publicKey; transaction.recentBlockhash = (await connection.getRecentBlockhash()).blockhash; transaction.sign(payer, candyMachine); const signature = await connection.sendRawTransaction(transaction.serialize()); await connection.confirmTransaction(signature); console.log(`Candy Machine initialized: ${candyMachine.publicKey.toBase58()}`); // Output: Candy Machine initialized: 5K8NduwnU... ``` -------------------------------- ### Initialize NFT Pack Source: https://context7.com/metaplex-foundation/metaplex-program-library/llms.txt Use this to create an NFT pack with randomized cards. Requires a pre-existing store account and specifies distribution and redemption parameters. ```typescript import { Connection, Keypair, PublicKey, Transaction, SYSVAR_CLOCK_PUBKEY } from '@solana/web3.js'; import { createInitPackInstruction, InitPackInstructionArgs, InitPackSetArgs, } from '@metaplex-foundation/mpl-nft-packs'; const connection = new Connection('https://api.devnet.solana.com', 'confirmed'); const payer = Keypair.generate(); const packSet = Keypair.generate(); const NFT_PACKS_PROGRAM_ID = new PublicKey('packFeFNZzMfD9aVWL7QbGz1WcU7R9zpf6pvNsw2BLu'); // Store account for the pack (previously created) const store = new PublicKey('STORE_ADDRESS'); const initPackSetArgs: InitPackSetArgs = { name: Array.from(Buffer.alloc(32).fill(0)).map((_, i) => i < 'Mystery Box'.length ? 'Mystery Box'.charCodeAt(i) : 0 ), description: 'A mystery box containing rare collectibles', uri: 'https://example.com/pack-metadata.json', mutable: true, distributionType: 0, // MaxSupply distribution allowedAmountToRedeem: 5, // Cards per pack opening redeemStartDate: BigInt(Math.floor(Date.now() / 1000)), redeemEndDate: null, // No end date }; const args: InitPackInstructionArgs = { initPackSetArgs, }; const instruction = createInitPackInstruction( { packSet: packSet.publicKey, authority: payer.publicKey, store, clock: SYSVAR_CLOCK_PUBKEY, }, args ); const transaction = new Transaction().add(instruction); transaction.feePayer = payer.publicKey; transaction.recentBlockhash = (await connection.getRecentBlockhash()).blockhash; transaction.sign(payer); const signature = await connection.sendRawTransaction(transaction.serialize()); console.log(`Pack initialized: ${packSet.publicKey.toBase58()}`); // Output: Pack initialized: 8Kn2tF4... ``` -------------------------------- ### Version and Publish NPM Package Source: https://github.com/metaplex-foundation/metaplex-program-library/blob/master/README.md Commands to version and publish an NPM package. Ensure you are on the master branch before executing. ```bash npm version ``` ```bash npm publish ``` -------------------------------- ### Initialize Hydra Fanout Wallet Source: https://context7.com/metaplex-foundation/metaplex-program-library/llms.txt Creates a Hydra fanout wallet for splitting revenue. Requires connection, authority keypair, and airdropped SOL. Initializes a FanoutClient and creates a fanout with configurable shares and name. Fetches and logs fanout details. ```typescript import { Connection, Keypair, LAMPORTS_PER_SOL } from '@solana/web3.js'; import { FanoutClient, MembershipModel, Fanout } from '@metaplex-foundation/mpl-hydra'; import { NodeWallet } from '@project-serum/common'; import { Account } from '@solana/web3.js'; const connection = new Connection('https://api.devnet.solana.com', 'confirmed'); const authority = Keypair.generate(); // Airdrop some SOL for testing await connection.requestAirdrop(authority.publicKey, LAMPORTS_PER_SOL * 10); // Initialize FanoutClient with wallet const wallet = new NodeWallet(new Account(authority.secretKey)); const fanoutSdk = new FanoutClient(connection, wallet); // Create a wallet-based fanout with 100 total shares const { fanout, nativeAccount } = await fanoutSdk.initializeFanout({ totalShares: 100, name: `MyRevenueSplit${Date.now()}`, membershipModel: MembershipModel.Wallet, }); console.log(`Fanout created: ${fanout.toBase58()}`); console.log(`Native holding account: ${nativeAccount.toBase58()}`); // Fetch and verify the fanout account const fanoutAccount = await fanoutSdk.fetch(fanout, Fanout); console.log('Fanout details:', { membershipModel: MembershipModel[fanoutAccount.membershipModel], totalShares: fanoutAccount.totalShares.toString(), totalAvailableShares: fanoutAccount.totalAvailableShares.toString(), totalMembers: fanoutAccount.totalMembers.toString(), }); // Output: // Fanout details: { // membershipModel: 'Wallet', // totalShares: '100', // totalAvailableShares: '100', // totalMembers: '0' // } ``` -------------------------------- ### Create Auction House Instance - TypeScript Source: https://context7.com/metaplex-foundation/metaplex-program-library/llms.txt Use this snippet to create a new auction house instance. It requires setting up a Solana connection, payer, and authority keypairs, and deriving PDA addresses for the auction house program. Ensure the `AUCTION_HOUSE_PROGRAM_ID` is correctly set for your environment. ```typescript import { Connection, Keypair, PublicKey, Transaction } from '@solana/web3.js'; import { NATIVE_MINT } from '@solana/spl-token'; import { createCreateAuctionHouseInstruction, CreateAuctionHouseInstructionArgs, CreateAuctionHouseInstructionAccounts, } from '@metaplex-foundation/mpl-auction-house'; // Setup connection and keypairs const connection = new Connection('https://api.devnet.solana.com', 'confirmed'); const payer = Keypair.generate(); const authority = payer; // Derive auction house PDA addresses const AUCTION_HOUSE_PROGRAM_ID = new PublicKey('hausS13jsjafwWwGqZTUQRmWyvyxn9EQpqMwV1PBBmk'); const treasuryMint = NATIVE_MINT; // Use SOL as payment const [auctionHouse, bump] = await PublicKey.findProgramAddress( [ Buffer.from('auction_house'), authority.publicKey.toBuffer(), treasuryMint.toBuffer(), ], AUCTION_HOUSE_PROGRAM_ID ); const [auctionHouseFeeAccount, feePayerBump] = await PublicKey.findProgramAddress( [Buffer.from('auction_house'), auctionHouse.toBuffer(), Buffer.from('fee_payer')], AUCTION_HOUSE_PROGRAM_ID ); const [auctionHouseTreasury, treasuryBump] = await PublicKey.findProgramAddress( [Buffer.from('auction_house'), auctionHouse.toBuffer(), Buffer.from('treasury')], AUCTION_HOUSE_PROGRAM_ID ); const accounts: CreateAuctionHouseInstructionAccounts = { treasuryMint, payer: payer.publicKey, authority: authority.publicKey, feeWithdrawalDestination: payer.publicKey, treasuryWithdrawalDestination: payer.publicKey, treasuryWithdrawalDestinationOwner: payer.publicKey, auctionHouse, auctionHouseFeeAccount, auctionHouseTreasury, }; const args: CreateAuctionHouseInstructionArgs = { bump, feePayerBump, treasuryBump, sellerFeeBasisPoints: 200, // 2% marketplace fee requiresSignOff: false, // No authority signature required for trades canChangeSalePrice: false, // Seller price is final }; const instruction = createCreateAuctionHouseInstruction(accounts, args); const transaction = new Transaction().add(instruction); transaction.feePayer = payer.publicKey; transaction.recentBlockhash = (await connection.getRecentBlockhash()).blockhash; transaction.sign(payer); const signature = await connection.sendRawTransaction(transaction.serialize()); await connection.confirmTransaction(signature); console.log(`Auction House created: ${auctionHouse.toBase58()}`); // Output: Auction House created: 7nE1GmnMmDKiycFkpHF7mKtxt356FQzVonZqBWsTWL33 ``` -------------------------------- ### Build Token Metadata Program Source: https://github.com/metaplex-foundation/metaplex-program-library/blob/master/hydra/program/README.md Compiles the Metaplex Token Metadata program using Cargo and outputs the BPF shared object file to the test-programs directory. ```shell cd metaplex-program-library/token-metadata/program cargo build-bpf --bpf-out-dir ../../test-programs/ ``` -------------------------------- ### Build Shared Object for Auction House Program Source: https://github.com/metaplex-foundation/metaplex-program-library/blob/master/README.md Use this script to build the shared object for the auction-house program. The output is placed in the 'test-programs' directory. ```bash ./build.sh auction-house ``` -------------------------------- ### List NFT for Sale using Auction House Source: https://context7.com/metaplex-foundation/metaplex-program-library/llms.txt Use this function to create a sell listing for an NFT. Ensure all required accounts and program IDs are correctly derived and passed. The listing price is specified in lamports. ```typescript import { Connection, Keypair, PublicKey, Transaction } from '@solana/web3.js'; import { getAssociatedTokenAddress } from '@solana/spl-token'; import { createSellInstruction, SellInstructionArgs, SellInstructionAccounts, } from '@metaplex-foundation/mpl-auction-house'; const connection = new Connection('https://api.devnet.solana.com', 'confirmed'); const seller = Keypair.generate(); const AUCTION_HOUSE_PROGRAM_ID = new PublicKey('hausS13jsjafwWwGqZTUQRmWyvyxn9EQpqMwV1PBBmk'); // NFT and auction house details const nftMint = new PublicKey('NFT_MINT_ADDRESS'); const auctionHouse = new PublicKey('AUCTION_HOUSE_ADDRESS'); const auctionHouseFeeAccount = new PublicKey('FEE_ACCOUNT_ADDRESS'); const authority = new PublicKey('AUCTION_HOUSE_AUTHORITY'); // Get seller's token account for the NFT const tokenAccount = await getAssociatedTokenAddress(nftMint, seller.publicKey); // Derive metadata PDA const TOKEN_METADATA_PROGRAM_ID = new PublicKey('metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s'); const [metadata] = await PublicKey.findProgramAddress( [Buffer.from('metadata'), TOKEN_METADATA_PROGRAM_ID.toBuffer(), nftMint.toBuffer()], TOKEN_METADATA_PROGRAM_ID ); // Listing price in lamports (1 SOL) const buyerPrice = 1_000_000_000n; const tokenSize = 1n; // Derive trade state PDAs const [sellerTradeState, tradeStateBump] = await PublicKey.findProgramAddress( [ Buffer.from('auction_house'), seller.publicKey.toBuffer(), auctionHouse.toBuffer(), tokenAccount.toBuffer(), new PublicKey('So11111111111111111111111111111111111111112').toBuffer(), // Treasury mint nftMint.toBuffer(), Buffer.from(buyerPrice.toString(16).padStart(16, '0'), 'hex'), Buffer.from(tokenSize.toString(16).padStart(16, '0'), 'hex'), ], AUCTION_HOUSE_PROGRAM_ID ); const [freeSellerTradeState, freeTradeStateBump] = await PublicKey.findProgramAddress( [ Buffer.from('auction_house'), seller.publicKey.toBuffer(), auctionHouse.toBuffer(), tokenAccount.toBuffer(), new PublicKey('So11111111111111111111111111111111111111112').toBuffer(), nftMint.toBuffer(), Buffer.alloc(8), // Zero price for free trade state Buffer.from(tokenSize.toString(16).padStart(16, '0'), 'hex'), ], AUCTION_HOUSE_PROGRAM_ID ); const [programAsSigner, programAsSignerBump] = await PublicKey.findProgramAddress( [Buffer.from('auction_house'), Buffer.from('signer')], AUCTION_HOUSE_PROGRAM_ID ); const accounts: SellInstructionAccounts = { wallet: seller.publicKey, tokenAccount, metadata, authority, auctionHouse, auctionHouseFeeAccount, sellerTradeState, freeSellerTradeState, programAsSigner, }; const args: SellInstructionArgs = { tradeStateBump, freeTradeStateBump, programAsSignerBump, buyerPrice, tokenSize, }; const instruction = createSellInstruction(accounts, args); const transaction = new Transaction().add(instruction); transaction.feePayer = seller.publicKey; transaction.recentBlockhash = (await connection.getRecentBlockhash()).blockhash; transaction.sign(seller); const signature = await connection.sendRawTransaction(transaction.serialize()); console.log(`NFT listed for sale: ${signature}`); ``` -------------------------------- ### Generate SDK from IDL Source: https://github.com/metaplex-foundation/metaplex-program-library/blob/master/fixed-price-sale/js/README.md Run this command to update the generated SDK when the Rust contract is updated. Currently, this only generates the IDL JSON file but will later generate TypeScript definitions and SDK code. ```bash yarn api:gen ``` -------------------------------- ### Create Listing API Source: https://github.com/metaplex-foundation/metaplex-program-library/blob/master/auctioneer/js/idl/auctioneer.txt This endpoint allows for the creation of a new listing within the Auction House. It requires various parameters to define the sale, including price, duration, and associated accounts. ```APIDOC ## POST /listings ### Description Creates a new listing for an item in the Auction House. ### Method POST ### Endpoint /listings ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body - **tradeStateBump** (u8) - Required - The bump seed for the trade state. - **freeTradeStateBump** (u8) - Required - The bump seed for the free trade state. - **programAsSignerBump** (u8) - Required - The bump seed for the program as signer. - **buyerPrice** (u64) - Required - The price the buyer is offering. - **tokenSize** (u64) - Required - The size of the token being listed. - **startTime** (UnixTimestamp) - Required - The start time of the listing. - **endTime** (UnixTimestamp) - Required - The end time of the listing. ### Request Example ```json { "tradeStateBump": 1, "freeTradeStateBump": 2, "programAsSignerBump": 3, "buyerPrice": 1000000000, "tokenSize": 1, "startTime": 1678886400, "endTime": 1679886400 } ``` ### Response #### Success Response (200) - **listingConfig** (ListingConfig) - Details of the created listing configuration. #### Response Example ```json { "listingConfig": { "startTime": 1678886400, "endTime": 1679886400, "highestBid": { "amount": 0, "buyerTradeState": "11111111111111111111111111111111" }, "bump": 4 } } ``` ``` -------------------------------- ### Run Tests Source: https://github.com/metaplex-foundation/metaplex-program-library/blob/master/hydra/program/README.md Executes all project tests using the configured test runner. Ensure the local validator is running before executing. ```shell yarn test ``` -------------------------------- ### Define Creators for Sale Source: https://github.com/metaplex-foundation/metaplex-program-library/blob/master/fixed-price-sale/cli/README.md JSON schema for defining creator addresses and their share percentages when setting up sales. ```json [ { "address": "...", "share": 30, } ] ``` -------------------------------- ### Configure Gating for Sales Source: https://github.com/metaplex-foundation/metaplex-program-library/blob/master/fixed-price-sale/cli/README.md JSON schema for configuring gating options, specifying a collection and whether the gate expires on use. ```json { "collection": "...", "expire_on_use": false, "gating_time": null } ``` -------------------------------- ### Create Entangled NFT Pair with Token Entangler Source: https://context7.com/metaplex-foundation/metaplex-program-library/llms.txt Use this snippet to create an entangled pair of NFTs. It derives necessary PDAs, constructs the instruction, and sends a transaction to the Solana network. Ensure you have the correct program IDs and NFT mint addresses. ```typescript import { Connection, Keypair, PublicKey, Transaction, LAMPORTS_PER_SOL } from '@solana/web3.js'; import { NATIVE_MINT, getAssociatedTokenAddress } from '@solana/spl-token'; import { createCreateEntangledPairInstruction, CreateEntangledPairInstructionArgs, } from '@metaplex-foundation/mpl-token-entangler'; const connection = new Connection('https://api.devnet.solana.com', 'confirmed'); const payer = Keypair.generate(); const authority = payer; const TOKEN_ENTANGLER_PROGRAM_ID = new PublicKey('qntmGodpGkrM42mN68VCZHXnKqDCT8rdY23wFcXCLPd'); const TOKEN_METADATA_PROGRAM_ID = new PublicKey('metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s'); // Two NFTs to entangle const mintA = new PublicKey('NFT_A_MINT'); const mintB = new PublicKey('NFT_B_MINT'); // Derive metadata PDAs const [metadataA] = await PublicKey.findProgramAddress( [Buffer.from('metadata'), TOKEN_METADATA_PROGRAM_ID.toBuffer(), mintA.toBuffer()], TOKEN_METADATA_PROGRAM_ID ); const [metadataB] = await PublicKey.findProgramAddress( [Buffer.from('metadata'), TOKEN_METADATA_PROGRAM_ID.toBuffer(), mintB.toBuffer()], TOKEN_METADATA_PROGRAM_ID ); // Derive edition PDAs const [editionA] = await PublicKey.findProgramAddress( [Buffer.from('metadata'), TOKEN_METADATA_PROGRAM_ID.toBuffer(), mintA.toBuffer(), Buffer.from('edition')], TOKEN_METADATA_PROGRAM_ID ); const [editionB] = await PublicKey.findProgramAddress( [Buffer.from('metadata'), TOKEN_METADATA_PROGRAM_ID.toBuffer(), mintB.toBuffer(), Buffer.from('edition')], TOKEN_METADATA_PROGRAM_ID ); // Derive entangled pair PDAs const [entangledPair, bump] = await PublicKey.findProgramAddress( [Buffer.from('token_entangler'), mintA.toBuffer(), mintB.toBuffer()], TOKEN_ENTANGLER_PROGRAM_ID ); const [reverseEntangledPair, reverseBump] = await PublicKey.findProgramAddress( [Buffer.from('token_entangler'), mintB.toBuffer(), mintA.toBuffer()], TOKEN_ENTANGLER_PROGRAM_ID ); // Derive escrow accounts const [tokenAEscrow, tokenAEscrowBump] = await PublicKey.findProgramAddress( [Buffer.from('token_entangler'), entangledPair.toBuffer(), Buffer.from('escrow_a')], TOKEN_ENTANGLER_PROGRAM_ID ); const [tokenBEscrow, tokenBEscrowBump] = await PublicKey.findProgramAddress( [Buffer.from('token_entangler'), entangledPair.toBuffer(), Buffer.from('escrow_b')], TOKEN_ENTANGLER_PROGRAM_ID ); const tokenB = await getAssociatedTokenAddress(mintB, payer.publicKey); const args: CreateEntangledPairInstructionArgs = { bump, reverseBump, tokenAEscrowBump, tokenBEscrowBump, price: BigInt(0.1 * LAMPORTS_PER_SOL), // 0.1 SOL swap fee paysEveryTime: true, // Fee charged on every swap }; const instruction = createCreateEntangledPairInstruction( { treasuryMint: NATIVE_MINT, payer: payer.publicKey, transferAuthority: payer.publicKey, authority: authority.publicKey, mintA, metadataA, editionA, mintB, metadataB, editionB, tokenB, tokenAEscrow, tokenBEscrow, entangledPair, reverseEntangledPair, }, args ); const transaction = new Transaction().add(instruction); transaction.feePayer = payer.publicKey; transaction.recentBlockhash = (await connection.getRecentBlockhash()).blockhash; transaction.sign(payer); const signature = await connection.sendRawTransaction(transaction.serialize()); console.log(`Entangled pair created: ${entangledPair.toBase58()}`); ``` -------------------------------- ### Run Auction House Tests Source: https://github.com/metaplex-foundation/metaplex-program-library/blob/master/auction-house/program/README.md Executes the Auction House program tests using cargo test-bpf. Ensure RUST_LOG is set to debug for detailed logs and filter out CounterPoint messages. ```bash clear && RUST_LOG=debug cargo test-bpf --bpf-out-dir ../../test-programs/ 2>&1 | grep -v CounterPoint ``` -------------------------------- ### Sell Source: https://github.com/metaplex-foundation/metaplex-program-library/blob/master/auctioneer/js/idl/auctioneer.txt Initiates a sell order on the Auction House. This prepares an item for sale by creating the necessary trade state accounts. ```APIDOC ## POST /sell ### Description Initiates a sell order for an item on the Auction House. This involves setting up the seller's trade state and associated accounts. ### Method POST ### Endpoint /sell ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None (This is typically an instruction to a program, not a direct HTTP request body) ### Accounts - **auctionHouseProgram** (Program) - The Auction House program ID. - **listingConfig** (Mutable Account) - Configuration account for the listing. - **wallet** (Mutable Account) - The seller's wallet address. - **tokenAccount** (Mutable Account) - The token account of the item to be sold. - **metadata** (Account) - The metadata account for the token. - **authority** (Account) - The authority account. - **auctionHouse** (Account) - The Auction House account. - **auctionHouseFeeAccount** (Mutable Account) - The Auction House fee account. - **sellerTradeState** (Mutable Account) - The seller's trade state account. - **freeSellerTradeState** (Mutable Account) - The free seller trade state account. - **auctioneerAuthority** (Account) - The Auctioneer authority account (optional). - **ahAuctioneerPda** (Account) - The PDA for the Auctioneer. - **programAsSigner** (Account) - Program as signer account. - **tokenProgram** (Program) - The Token program ID. ### Request Example ```json { "instruction": "sell", "args": { // Arguments for the sell instruction would be here, e.g., price, expiry }, "accounts": [ // ... account addresses ... ] } ``` ### Response #### Success Response (200) - **signature** (string) - Transaction signature for the sell order initiation. #### Response Example ```json { "signature": "TxSignature67890..." } ``` ``` -------------------------------- ### Auctioneer Program Instructions Source: https://github.com/metaplex-foundation/metaplex-program-library/blob/master/auctioneer/js/idl/auctioneer.txt This section details the available instructions for the Metaplex Auctioneer Program. ```APIDOC ## POST /auctioneer/withdraw ### Description Allows a user to withdraw funds from the auction house escrow account. ### Method POST ### Endpoint /auctioneer/withdraw ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body - **escrowPaymentBump** (u8) - Required - The bump seed for the escrow payment account. - **amount** (u64) - Required - The amount to withdraw. ### Request Example ```json { "escrowPaymentBump": 1, "amount": 1000000000 } ``` ### Response #### Success Response (200) - **signature** (string) - The transaction signature for the withdraw operation. #### Response Example ```json { "signature": "" } ``` ## POST /auctioneer/deposit ### Description Allows a user to deposit funds into the auction house escrow account. ### Method POST ### Endpoint /auctioneer/deposit ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body - **escrowPaymentBump** (u8) - Required - The bump seed for the escrow payment account. - **amount** (u64) - Required - The amount to deposit. ### Request Example ```json { "escrowPaymentBump": 1, "amount": 1000000000 } ``` ### Response #### Success Response (200) - **signature** (string) - The transaction signature for the deposit operation. #### Response Example ```json { "signature": "" } ``` ## POST /auctioneer/cancel ### Description Allows a user to cancel a trade or an auction listing. ### Method POST ### Endpoint /auctioneer/cancel ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body - **buyerPrice** (u64) - Required - The price of the buyer. ### Request Example ```json { "buyerPrice": 1000000000 } ``` ### Response #### Success Response (200) - **signature** (string) - The transaction signature for the cancel operation. #### Response Example ```json { "signature": "" } ``` ```