### Run Next.js Development Server (Bash) Source: https://github.com/solana-developers/program-examples/blob/main/tokens/token-2022/nft-meta-data-pointer/anchor-example/app/README.md Commands to start the Next.js development server using npm, yarn, or pnpm. This allows for hot-reloading and immediate feedback during development. No external dependencies are required beyond the project's Node.js environment. ```bash npm run dev # or yarn dev # or pnpm dev ``` -------------------------------- ### Install and Run JS Client Source: https://github.com/solana-developers/program-examples/blob/main/tokens/token-2022/nft-meta-data-pointer/anchor-example/README.md Installs project dependencies and starts the JavaScript client for the Solana program. This client is used to interact with and mint NFTs created by the program. It requires Node.js and Yarn to be installed. ```shell cd app yarn install yarn dev ``` -------------------------------- ### Install Anchor CLI for Solana Development Source: https://github.com/solana-developers/program-examples/blob/main/tokens/token-2022/nft-meta-data-pointer/anchor-example/README.md This command installs the Anchor CLI, a framework for writing Solana programs. Follow the official Anchor documentation for the most up-to-date installation instructions and version compatibility notes. ```bash sh -c "$(curl -sSfL https://release.solana.com/v1.16.18/install)" ``` -------------------------------- ### Run Anchor Tests Source: https://github.com/solana-developers/program-examples/blob/main/tokens/token-2022/nft-meta-data-pointer/anchor-example/README.md Executes the integration tests for the Anchor program. This command ensures the program's core logic functions as expected before deployment or further development. It requires the Anchor framework to be installed. ```shell cd program anchor test --detach ``` -------------------------------- ### Steel CLI Installation and Usage Source: https://github.com/solana-developers/program-examples/blob/main/CONTRIBUTING.md Commands for installing and using the Steel CLI, a recommended tool for building and testing Steel framework programs. This includes project creation, building, and running tests. ```bash # Install Steel CLI (one-time setup) curl --proto '=https' --tlsv1.2 -sSf https://raw.githubusercontent.com/regolith-labs/steel/main/install.sh | sh # Create a new Steel project steel new # Build the program steel build # Run tests steel test ``` -------------------------------- ### Setup Extra Account Metas - CLI (Default) Source: https://github.com/solana-developers/program-examples/blob/main/tokens/token-2022/transfer-hook/pblock-list/pinocchio/readme.md Sets up the necessary extra account metas for the Transfer Hook extension. This is the default setup when the blocked wallet counter is non-zero, typically enabling source wallet checking. ```bash target/debug/block-list-cli setup-extra-metas ``` -------------------------------- ### Generate Unity client code using Solana.Unity.Anchor.Tool Source: https://github.com/solana-developers/program-examples/blob/main/tokens/token-2022/nft-meta-data-pointer/anchor-example/README.md This bash command sequence is used to generate C# client code for a Solana program when working with the Unity game engine. It requires the dotnet SDK and the Solana.Unity.Anchor.Tool to be installed. ```bash cd program dotnet tool install Solana.Unity.Anchor.Tool <- run once dotnet anchorgen -i target/idl/extension_nft.json -o target/idl/ExtensionNft.cs ``` -------------------------------- ### Solita Configuration File (.solitarc.js) Source: https://github.com/solana-developers/program-examples/blob/main/tools/shank-and-solita/native/README.md Example configuration file for Solita, specifying directories for the program, IDL, generated SDK, and binary installations. It also defines the IDL generator and program name. ```javascript const path = require('path'); const programDir = path.join(__dirname, 'program'); const idlDir = path.join(programDir, 'idl'); const sdkDir = path.join(__dirname, 'tests', 'generated'); const binaryInstallDir = path.join(__dirname, '.crates'); module.exports = { idlGenerator: 'shank', programName: 'car_rental_service', idlDir, sdkDir, binaryInstallDir, programDir, }; ``` -------------------------------- ### Generate C# Client from Anchor IDL for Unity Source: https://github.com/solana-developers/program-examples/blob/main/tokens/token-2022/nft-meta-data-pointer/anchor-example/README.md This command generates a C# client library for your Solana Anchor program, which can be used within a Unity project. It requires the Anchor IDL JSON file and outputs a C# file. Ensure you have the Solana.Unity.Anchor.Tool installed globally. ```bash dotnet tool install Solana.Unity.Anchor.Tool dotnet anchorgen -i target/idl/extension_nft.json -o target/idl/ExtensionNft.cs ``` -------------------------------- ### Initialize Block List - CLI Source: https://github.com/solana-developers/program-examples/blob/main/tokens/token-2022/transfer-hook/pblock-list/pinocchio/readme.md Initializes the Block List program, setting the authority that controls the block list. This is a setup step executed via the CLI. ```bash target/debug/block-list-cli init ``` -------------------------------- ### Shank CLI Installation and Usage Source: https://github.com/solana-developers/program-examples/blob/main/tools/shank-and-solita/native/README.md Commands to install the Shank CLI using Cargo and its basic usage, primarily focusing on the `idl` subcommand for generating the Interface Definition Language. ```shell cargo install shank-cli ``` ```shell USAGE: shank OPTIONS: -h, --help Print help information SUBCOMMANDS: help Print this message or the help of the given subcommand(s) idl ``` -------------------------------- ### Rust Initialize Fundraiser Logic Source: https://github.com/solana-developers/program-examples/blob/main/tokens/token-fundraiser/anchor/readme.MD Implements the initialization logic for the `Initialize` context. It validates the fundraising amount against a minimum threshold and sets the initial state of the `Fundraiser` account, including the maker, target mint, amount, start time, and duration. Requires `amount`, `duration`, and `bumps` as input. ```rust impl<'info> Initialize<'info> { pub fn initialize(&mut self, amount: u64, duration: u8, bumps: &InitializeBumps) -> Result<()> { // Check if the amount to raise meets the minimum amount required require!( amount > MIN_AMOUNT_TO_RAISE.pow(self.mint_to_raise.decimals as u32), FundraiserError::InvalidAmount ); // Initialize the fundraiser account self.fundraiser.set_inner(Fundraiser { maker: self.maker.key(), mint_to_raise: self.mint_to_raise.key(), amount_to_raise: amount, current_amount: 0, time_started: Clock::get()?.unix_timestamp, duration, bump: bumps.fundraiser }); Ok(()) } } ``` -------------------------------- ### Read Oracle Price Feeds with Pyth Network (Rust) Source: https://context7.com/solana-developers/program-examples/llms.txt Integrates with Pyth Network to read real-time price data on-chain using the pyth-solana-receiver SDK. The program decodes the price update, logs relevant details, and calculates a human-readable price. The client-side example shows how to fetch a price update account and call the program. ```rust use anchor_lang::prelude::*; use pyth_solana_receiver_sdk::price_update::PriceUpdateV2; declare_id!("GUkjQmrLPFXXNK1bFLKt8XQi6g3TjxcHVspbjDoHvMG2"); #[program] pub mod anchor_test { use super::*; pub fn read_price(ctx: Context) -> Result<()> { let price_update = &ctx.accounts.price_update; msg!("Price feed id: {:?}", price_update.price_message.feed_id); msg!("Price: {:?}", price_update.price_message.price); msg!("Confidence: {:?}", price_update.price_message.conf); msg!("Exponent: {:?}", price_update.price_message.exponent); msg!("Publish Time: {:?}", price_update.price_message.publish_time); // Calculate human-readable price let price = price_update.price_message.price; let exponent = price_update.price_message.exponent; let actual_price = (price as f64) * 10f64.powi(exponent); msg!("Actual price: ${}", actual_price); Ok(()) } } #[derive(Accounts)] pub struct ReadPrice <'info> { pub price_update: Account<'info, PriceUpdateV2>, } // Client usage import { PythSolanaReceiver } from "@pythnetwork/pyth-solana-receiver"; const pythReceiver = new PythSolanaReceiver({ connection, wallet }); const priceFeedId = "0xe62df6c8b4a85fe1a67db44dc12de5db330f7ac66b72dc658afedf0f4a415b43"; // BTC/USD const priceUpdateAccount = await pythReceiver.fetchPriceUpdateAccount(priceFeedId); await program.methods .readPrice() .accounts({ priceUpdate: priceUpdateAccount, }) .rpc(); ``` -------------------------------- ### Close Solana Account and Recover Rent (Rust) Source: https://context7.com/solana-developers/program-examples/llms.txt Closes a program account and returns its rent lamports to the signer. Requires Anchor framework and specifies account constraints for mutability and PDA seeds. The client-side example shows how to find the PDA, call the close function, and calculate recovered rent. ```rust use anchor_lang::prelude::*; #[derive(Accounts)] pub struct CloseUserContext <'info> { #[account(mut)] pub user: Signer<'info>, #[account( mut, seeds = [b"USER", user.key().as_ref()], bump = user_account.bump, close = user, // close account and return lamports to user )] pub user_account: Account<'info, UserState>, } pub fn close_user(_ctx: Context) -> Result<()> { Ok(()) } #[account] #[derive(InitSpace)] pub struct UserState { pub name: String, pub bump: u8, } // Client usage const [userPda, bump] = anchor.web3.PublicKey.findProgramAddressSync( [Buffer.from("USER"), user.publicKey.toBuffer()], program.programId ); const balanceBefore = await provider.connection.getBalance(user.publicKey); await program.methods .closeUser() .accounts({ user: user.publicKey, userAccount: userPda, }) .rpc(); const balanceAfter = await provider.connection.getBalance(user.publicKey); const rentRecovered = (balanceAfter - balanceBefore) / anchor.web3.LAMPORTS_PER_SOL; console.log(`Rent recovered: ${rentRecovered} SOL`); ``` -------------------------------- ### Generate SDKs (pnpm) Source: https://github.com/solana-developers/program-examples/blob/main/tokens/token-2022/transfer-hook/pblock-list/readme.md Generates Rust and TypeScript SDKs for interacting with the Block List smart contract. This command uses pnpm to execute the SDK generation script. ```shell pnpm run generate-sdks ``` -------------------------------- ### Solana Program Setup: Clone Metaplex Metadata Program Source: https://github.com/solana-developers/program-examples/blob/main/tokens/nft-operations/anchor/readme.MD Configures the test validator to clone the Metaplex Token Metadata program from Solana mainnet. This is necessary for performing Cross-Program Invocations (CPIs) to create NFT metadata and edition accounts. ```toml [test.validator] url = "https://api.mainnet-beta.solana.com" [[test.validator.clone]] address = "metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s" ``` -------------------------------- ### Rust Fundraiser Account Structure Source: https://github.com/solana-developers/program-examples/blob/main/tokens/token-fundraiser/anchor/readme.MD Defines the on-chain data structure for a fundraiser account. It includes details like the maker's public key, the target token mint, fundraising goal, current donations, start time, duration, and PDA bump. Uses `InitSpace` derive macro for space calculation. ```rust #[account] #[derive(InitSpace)] pub struct Fundraiser { pub maker: Pubkey, pub mint_to_raise: Pubkey, pub amount_to_raise: u64, pub current_amount: u64, pub time_started: i64, pub duration: u8, pub bump: u8, } ``` -------------------------------- ### Create SPL Token Mint with Metadata (JavaScript) Source: https://context7.com/solana-developers/program-examples/llms.txt This JavaScript snippet demonstrates how to interact with the Solana program to create an SPL token mint with metadata. It utilizes the `@solana/web3.js` and Anchor client libraries. It requires a payer account and a generated Keypair for the new mint, and calls the `createTokenMint` method on the program. ```javascript // Client usage const mintKeypair = Keypair.generate(); await program.methods .createTokenMint( 9, // decimals "My Token", "MTK", "https://example.com/token-metadata.json" ) .accounts({ payer: payer.publicKey, mintAccount: mintKeypair.publicKey, }) .signers([payer, mintKeypair]) .rpc(); console.log(`Token mint created: ${mintKeypair.publicKey.toBase58()}`); ``` -------------------------------- ### Initialize and Increment Counter with Anchor (Rust & TypeScript) Source: https://context7.com/solana-developers/program-examples/llms.txt Demonstrates initializing a global counter using a Program Derived Address (PDA) and incrementing its value. The Rust code defines the program logic and accounts, while the TypeScript code shows client-side interaction for initialization, incrementing, and fetching the count. This example showcases basic state management in Solana programs. ```rust use anchor_lang::prelude::* declare_id!("BmDHboaj1kBUoinJKKSRqKfMeRKJqQqEbUj1VgzeQe4A"); #[program] pub mod counter_anchor { use super::* pub fn initialize_counter(_ctx: Context) -> Result<()> { Ok(()) } pub fn increment(ctx: Context) -> Result<()> { ctx.accounts.counter.count = ctx.accounts.counter.count.checked_add(1).unwrap(); Ok(()) } } #[derive(Accounts)] pub struct InitializeCounter<'info> { #[account(mut)] pub payer: Signer<'info>, #[account( init, space = 8 + Counter::INIT_SPACE, payer = payer )] pub counter: Account<'info, Counter>, pub system_program: Program<'info, System>, } #[derive(Accounts)] pub struct Increment<'info> { #[account(mut)] pub counter: Account<'info, Counter>, } #[account] #[derive(InitSpace)] pub struct Counter { count: u64, } ``` ```typescript import * as anchor from '@coral-xyz/anchor'; import { Keypair } from '@solana/web3.js'; const provider = anchor.AnchorProvider.env(); anchor.setProvider(provider); const program = anchor.workspace.CounterAnchor; const counterKeypair = new Keypair(); // Initialize await program.methods .initializeCounter() .accounts({ counter: counterKeypair.publicKey, payer: provider.wallet.publicKey, }) .signers([counterKeypair]) .rpc(); // Increment await program.methods .increment() .accounts({ counter: counterKeypair.publicKey }) .rpc(); // Fetch current count const currentCount = await program.account.counter.fetch(counterKeypair.publicKey); console.log(`Count: ${currentCount.count.toNumber()}`); ``` -------------------------------- ### Initialize Player Account in Solana Program (Rust) Source: https://github.com/solana-developers/program-examples/blob/main/tokens/token-2022/nft-meta-data-pointer/anchor-example/README.md Initializes a player account on Solana, setting initial energy, last login timestamp, and authority. It also initializes game data if needed. This function requires the `InitPlayer` context which includes signer and system program dependencies. ```rust pub fn init_player(ctx: Context) -> Result<()> { ctx.accounts.player.energy = MAX_ENERGY; ctx.accounts.player.last_login = Clock::get()?.unix_timestamp; ctx.accounts.player.authority = ctx.accounts.signer.key(); Ok(()) } #[derive(Accounts)] pub struct InitPlayer<'info> { #[account( init, payer = signer, space = 1000, // 8+32+x+1+8+8+8 But taking 1000 to have space to expand easily. seeds = [b"player".as_ref(), signer.key().as_ref()], bump, )] pub player: Account<'info, PlayerData>, #[account( init_if_needed, payer = signer, space = 1000, // 8 + 8 for anchor account discriminator and the u64. Using 1000 to have space to expand easily. seeds = [b"gameData".as_ref()], bump, )] pub game_data: Account<'info, GameData>, #[account(mut)] pub signer: Signer<'info>, pub system_program: Program<'info, System>, } ``` -------------------------------- ### Rust Initialize Fundraiser Context Source: https://github.com/solana-developers/program-examples/blob/main/tokens/token-fundraiser/anchor/readme.MD Defines the accounts required for initializing a new fundraiser. Includes the maker (signer), target mint, the fundraiser state account, a vault for donations, and necessary system programs. Uses Anchor's `Accounts` derive macro. ```rust #[derive(Accounts)] pub struct Initialize<'info> { #[account(mut)] pub maker: Signer<'info>, pub mint_to_raise: Account<'info, Mint>, #[account( init, payer = maker, seeds = [b"fundraiser", maker.key().as_ref()], bump, space = ANCHOR_DISCRIMINATOR + Fundraiser::INIT_SPACE, )] pub fundraiser: Account<'info, Fundraiser>, #[account( init, payer = maker, associated_token::mint = mint_to_raise, associated_token::authority = fundraiser, )] pub vault: Account<'info, TokenAccount>, pub system_program: Program<'info, System>, pub token_program: Program<'info, Token>, pub associated_token_program: Program<'info, AssociatedToken>, } ``` -------------------------------- ### Burn Compressed NFTs using Metaplex Bubblegum (TypeScript) Source: https://context7.com/solana-developers/program-examples/llms.txt This TypeScript client-side code demonstrates how to burn a compressed NFT using the Metaplex Bubblegum program. It requires fetching the asset proof from an indexer and then calling the `burnCnft` method on the program with the necessary account information and transaction details. This example assumes the use of Anchor client. ```typescript // Client usage - requires merkle proof from indexer const assetProof = await getAssetProof(assetId); // from Digital Asset Standard API await program.methods .burnCnft( Array.from(Buffer.from(assetProof.root, "base64")), Array.from(Buffer.from(dataHash)), Array.from(Buffer.from(creatorHash)), nonce, index ) .accounts({ leafOwner: owner.publicKey, treeAuthority: treeAuthority, merkleTree: merkleTree, }) .remainingAccounts(proofPath) .rpc(); ``` -------------------------------- ### Solita JavaScript SDK Installation Source: https://github.com/solana-developers/program-examples/blob/main/tools/shank-and-solita/native/README.md Command to add the Solita JavaScript SDK as a development dependency to your project using Yarn. ```shell yarn add -D @metaplex-foundation/solita ``` -------------------------------- ### Transfer SPL Tokens Between Users in Rust and JavaScript Source: https://context7.com/solana-developers/program-examples/llms.txt Demonstrates how to transfer SPL tokens between two users. It includes automatic creation of associated token accounts for the recipient if they don't exist. This example requires Anchor framework for Rust and provides client-side JavaScript usage. ```rust use anchor_lang::prelude::*; use anchor_spl:: associated_token::AssociatedToken, token::{transfer, Mint, Token, TokenAccount, Transfer}; #[derive(Accounts)] pub struct TransferTokens<'info> { #[account(mut)] pub sender: Signer<'info>, pub recipient: SystemAccount<'info>, #[account(mut)] pub mint_account: Account<'info, Mint>, #[account( mut, associated_token::mint = mint_account, associated_token::authority = sender, )] pub sender_token_account: Account<'info, TokenAccount>, #[account( init_if_needed, payer = sender, associated_token::mint = mint_account, associated_token::authority = recipient, )] pub recipient_token_account: Account<'info, TokenAccount>, pub token_program: Program<'info, Token>, pub associated_token_program: Program<'info, AssociatedToken>, pub system_program: Program<'info, System>, } pub fn transfer_tokens(ctx: Context, amount: u64) -> Result<()> { msg!("Transferring tokens..."); msg!("Mint: {}", &ctx.accounts.mint_account.to_account_info().key()); msg!("From Token Address: {}", &ctx.accounts.sender_token_account.key()); msg!("To Token Address: {}", &ctx.accounts.recipient_token_account.key()); transfer( CpiContext::new( ctx.accounts.token_program.to_account_info(), Transfer { from: ctx.accounts.sender_token_account.to_account_info(), to: ctx.accounts.recipient_token_account.to_account_info(), authority: ctx.accounts.sender.to_account_info(), }, ), amount * 10u64.pow(ctx.accounts.mint_account.decimals as u32), )?; msg!("Tokens transferred successfully."); Ok(()) } ``` ```javascript // Client usage const senderAta = await getAssociatedTokenAddress(mint, sender.publicKey); const recipientAta = await getAssociatedTokenAddress(mint, recipient.publicKey); await program.methods .transferTokens(new anchor.BN(50)) .accounts({ sender: sender.publicKey, recipient: recipient.publicKey, mintAccount: mint, senderTokenAccount: senderAta, recipientTokenAccount: recipientAta, }) .signers([sender]) .rpc(); const senderBalance = await provider.connection.getTokenAccountBalance(senderAta); const recipientBalance = await provider.connection.getTokenAccountBalance(recipientAta); console.log(`Sender balance: ${senderBalance.value.uiAmount}`); console.log(`Recipient balance: ${recipientBalance.value.uiAmount}`); ``` -------------------------------- ### Setup Extra Account Metas - CLI (Check Both) Source: https://github.com/solana-developers/program-examples/blob/main/tokens/token-2022/transfer-hook/pblock-list/pinocchio/readme.md Configures the Transfer Hook's extra account metas to check both source and destination wallets for block list compliance. This is an optional behavior for enhanced blocking. ```bash target/debug/block-list-cli setup-extra-metas --check-both-wallets ``` -------------------------------- ### Initialize Unity Instance in JavaScript Source: https://github.com/solana-developers/program-examples/blob/main/tokens/token-2022/nft-meta-data-pointer/anchor-example/unity/ExtensionNft/Assets/WebGLTemplates/xNFT/index.html This JavaScript code configures and initializes a Unity game instance within an HTML page. It handles element selection, loading progress display, and error reporting. Dependencies include the Unity Loader script and specific build files. The output is a running Unity instance within the specified canvas element. ```javascript var container = document.querySelector("#unity-container"); var canvas = document.querySelector("#unity-canvas"); var loadingBar = document.querySelector("#unity-loading-bar"); var progressBarFull = document.querySelector("#unity-progress-bar-full"); var fullscreenButton = document.querySelector("#unity-fullscreen-button"); var warningBanner = document.querySelector("#unity-warning"); function unityShowBanner(msg, type) { function updateBannerVisibility() { warningBanner.style.display = warningBanner.children.length ? 'block' : 'none'; } var div = document.createElement('div'); div.innerHTML = msg; warningBanner.appendChild(div); if (type == 'error') div.style = 'background: red; padding: 10px;'; else { if (type == 'warning') div.style = 'background: yellow; padding: 10px;'; setTimeout(function() { warningBanner.removeChild(div); updateBannerVisibility(); }, 5000); } updateBannerVisibility(); } var buildUrl = "Build"; var loaderUrl = buildUrl + "/{{{ LOADER_FILENAME }}}"; var config = { dataUrl: "Build/{{{ DATA_FILENAME }}}", frameworkUrl: "Build/{{{ FRAMEWORK_FILENAME }}}", #if USE_WASM codeUrl: "Build/{{{ CODE_FILENAME }}}", #endif #if MEMORY_FILENAME memoryUrl: "Build/{{{ MEMORY_FILENAME }}}", #endif #if SYMBOLS_FILENAME symbolsUrl: "Build/{{{ SYMBOLS_FILENAME }}}", #endif streamingAssetsUrl: "StreamingAssets", companyName: {{{ JSON.stringify(COMPANY_NAME) }}}, productName: {{{ JSON.stringify(PRODUCT_NAME) }}}, productVersion: {{{ JSON.stringify(PRODUCT_VERSION) }}}, showBanner: unityShowBanner, }; var meta = document.createElement('meta'); meta.name = 'viewport'; meta.content = 'width=device-width, height=device-height, initial-scale=1.0, user-scalable=no, shrink-to-fit=yes'; document.getElementsByTagName('head')[0].appendChild(meta); var canvas = document.querySelector("#unity-canvas"); canvas.style.width = "100%"; canvas.style.height = "100%"; canvas.style.position = "fixed"; document.body.style.textAlign = "left"; loadingBar.style.display = "block"; var script = document.createElement("script"); script.src = loaderUrl; script.onload = () => { createUnityInstance(canvas, config, (progress) => { progressBarFull.style.width = 100 * progress + "%" }).then((unityInstance) => { loadingBar.style.display = "none"; }).catch((message) => { alert(message); }); }; document.body.appendChild(script); ``` -------------------------------- ### Create User Account with Anchor (Rust) Source: https://github.com/solana-developers/program-examples/blob/main/basics/close-account/anchor/README.md This Rust code snippet uses Anchor's #[account] macro to initialize a new user account. It defines the account's seeds, payer, space, and bump for its creation. ```rust #[account( init, seeds=[User::PREFIX.as_bytes(), user.key().as_ref()], payer=user, space=User::SIZE, bump )] pub user_account: Box> ``` -------------------------------- ### Rust: Define Accounts for Creating NFT Collection Source: https://github.com/solana-developers/program-examples/blob/main/tokens/nft-operations/anchor/readme.MD Defines the necessary accounts for the `CreateCollection` instruction in a Solana program. This struct specifies accounts for the user, mint, authorities, metadata, master edition, destination token account, and required system programs. ```rust #[derive(Accounts)] pub struct CreateCollection<'info> { #[account(mut)] user: Signer<'info>, #[account( init, payer = user, mint::decimals = 0, mint::authority = mint_authority, mint::freeze_authority = mint_authority, )] mint: Account<'info, Mint>, #[account( seeds = [b"authority"], bump, )] /// CHECK: This account is not initialized and is being used for signing purposes only pub mint_authority: UncheckedAccount<'info>, #[account(mut)] /// CHECK: This account will be initialized by the metaplex program metadata: UncheckedAccount<'info>, #[account(mut)] /// CHECK: This account will be initialized by the metaplex program master_edition: UncheckedAccount<'info>, #[account( init, payer = user, associated_token::mint = mint, associated_token::authority = user )] destination: Account<'info, TokenAccount>, system_program: Program<'info, System>, token_program: Program<'info, Token>, associated_token_program: Program<'info, AssociatedToken>, token_metadata_program: Program<'info, Metadata>, } ``` -------------------------------- ### Mint Tokens to Associated Token Account (JavaScript) Source: https://context7.com/solana-developers/program-examples/llms.txt This JavaScript code demonstrates how to interact with the Solana program to mint tokens. It uses the `@solana/spl-token` library to derive the associated token account address and then calls the `mintToken` method on the Anchor program. It also shows how to fetch the token balance after minting. ```javascript import { getAssociatedTokenAddress } from '@solana/spl-token'; const recipientAta = await getAssociatedTokenAddress( mintKeypair.publicKey, recipient.publicKey ); await program.methods .mintToken(new anchor.BN(100)) .accounts({ mintAuthority: authority.publicKey, recipient: recipient.publicKey, mintAccount: mintKeypair.publicKey, associatedTokenAccount: recipientAta, }) .signers([authority]) .rpc(); const tokenBalance = await provider.connection.getTokenAccountBalance(recipientAta); console.log(`Token balance: ${tokenBalance.value.uiAmount}`); ``` -------------------------------- ### Regular NFT Metadata Configuration (Rust) Source: https://github.com/solana-developers/program-examples/blob/main/tokens/nft-operations/anchor/readme.MD Defines the arguments for creating a metadata account for a regular NFT. It specifies the name, symbol, URI, and seller fee basis points. Unlike collection NFTs, it does not include the 'collection_details' field, differentiating it for marketplaces and applications. ```rust CreateMetadataAccountV3InstructionArgs { data: DataV2 { name: "Mint Test".to_string(), symbol: "YAY".to_string(), uri: "".to_string(), seller_fee_basis_points: 0, ``` -------------------------------- ### Collection NFT Metadata Configuration (Rust) Source: https://github.com/solana-developers/program-examples/blob/main/tokens/nft-operations/anchor/readme.MD Defines the arguments for creating a metadata account for a collection NFT. This includes setting the name, symbol, URI, creator details, and importantly, the 'collection_details' field to specify it as a collection. This configuration is used within the Token Metadata Program. ```rust CreateMetadataAccountV3InstructionArgs { data: DataV2 { name: "DummyCollection".to_owned(), symbol: "DC".to_owned(), uri: "".to_owned(), seller_fee_basis_points: 0, creators: Some(creator), collection: None, uses: None, }, is_mutable: true, collection_details: Some( CollectionDetails::V1 { size: 0 } ) } ``` -------------------------------- ### Mint NFT using Solana CPIs (Rust) Source: https://github.com/solana-developers/program-examples/blob/main/tokens/nft-operations/anchor/readme.MD Implements the minting of an NFT using Cross-Program Invocations (CPIs) to the Token Program and Token Metadata Program. This involves minting a token, creating its metadata account with specified details, and establishing a master edition for the NFT. It requires the necessary account information and signer seeds for authenticating CPIs. ```rust impl<'info> MintNFT<'info> { pub fn mint_nft(&mut self, bumps: &MintNFTBumps) -> Result<()> { let metadata = &self.metadata.to_account_info(); let master_edition = &self.master_edition.to_account_info(); let mint = &self.mint.to_account_info(); let authority = &self.mint_authority.to_account_info(); let payer = &self.owner.to_account_info(); let system_program = &self.system_program.to_account_info(); let spl_token_program = &self.token_program.to_account_info(); let spl_metadata_program = &self.token_metadata_program.to_account_info(); let seeds = &[ &b"authority"[..], &[bumps.mint_authority] ]; let signer_seeds = &[&seeds[..]]; let cpi_program = self.token_program.to_account_info(); let cpi_accounts = MintTo { mint: self.mint.to_account_info(), to: self.destination.to_account_info(), authority: self.mint_authority.to_account_info(), }; let cpi_ctx = CpiContext::new_with_signer(cpi_program, cpi_accounts, signer_seeds); mint_to(cpi_ctx, 1)?; msg!("Collection NFT minted!"); let creator = vec![ Creator { address: self.mint_authority.key(), verified: true, share: 100, }, ]; let metadata_account = CreateMetadataAccountV3Cpi::new( spl_metadata_program, CreateMetadataAccountV3CpiAccounts { metadata, mint, mint_authority: authority, payer, update_authority: (authority, true), system_program, rent: None, }, CreateMetadataAccountV3InstructionArgs { data: DataV2 { name: "Mint Test".to_string(), symbol: "YAY".to_string(), uri: "".to_string(), seller_fee_basis_points: 0, creators: Some(creator), collection: Some(Collection { verified: false, key: self.collection_mint.key(), }), uses: None }, is_mutable: true, collection_details: None, } ); metadata_account.invoke_signed(signer_seeds)?; let master_edition_account = CreateMasterEditionV3Cpi::new( spl_metadata_program, CreateMasterEditionV3CpiAccounts { edition: master_edition, update_authority: authority, mint_authority: authority, mint, payer, metadata, token_program: spl_token_program, system_program, rent: None, }, CreateMasterEditionV3InstructionArgs { max_supply: Some(0), } ); master_edition_account.invoke_signed(signer_seeds)?; Ok(()) } } ``` -------------------------------- ### Mint Tokens and Freeze Authority with Solana Token 2022 Source: https://github.com/solana-developers/program-examples/blob/main/tokens/token-2022/nft-meta-data-pointer/anchor-example/README.md This code snippet demonstrates how to mint tokens and then freeze the mint authority to make it non-transferable, effectively creating an NFT. It uses the CPI (Cross-Program Invocation) context for interacting with the token_2022 program. Ensure the necessary accounts and signer are correctly configured. ```rust token_2022::mint_to( CpiContext::new_with_signer( ctx.accounts.token_program.to_account_info(), token_2022::MintTo { mint: ctx.accounts.mint.to_account_info(), to: ctx.accounts.token_account.to_account_info(), authority: ctx.accounts.nft_authority.to_account_info(), }, signer ), 1, )?; // Freeze the mint authority so no more tokens can be minted to make it an NFT token_2022::set_authority( CpiContext::new_with_signer( ctx.accounts.token_program.to_account_info(), token_2022::SetAuthority { current_authority: ctx.accounts.nft_authority.to_account_info(), account_or_mint: ctx.accounts.mint.to_account_info(), }, signer ), AuthorityType::MintTokens, None, )?; ``` -------------------------------- ### Create Solana Game Project with Create Solana Game CLI Source: https://github.com/solana-developers/program-examples/blob/main/tokens/token-2022/nft-meta-data-pointer/anchor-example/README.md This command initializes a new Solana game project using the 'create-solana-game' CLI tool. It's a starter template for on-chain games with both JavaScript and Unity clients that communicate with a Solana Anchor program. The preset utilizes gum session keys for transaction auto-approval. ```bash npx create-solana-game gamName ``` -------------------------------- ### Deploy Smart Contract - Solana CLI Source: https://github.com/solana-developers/program-examples/blob/main/tokens/token-2022/transfer-hook/pblock-list/pinocchio/readme.md Deploys the compiled Block List smart contract to the Solana network. This requires a program ID keypair and the path to the compiled program. ```bash solana program deploy --program-id target/deploy/block_list.so ``` -------------------------------- ### Initialize Unity WebGL Build in JavaScript Source: https://github.com/solana-developers/program-examples/blob/main/tokens/token-2022/nft-meta-data-pointer/anchor-example/unity/ExtensionNft/Assets/WebGLTemplates/SolanaWebGlTemplate/index.html This JavaScript code snippet initializes a Unity WebGL build within an HTML page. It configures the build URL, loader, and other necessary assets. It also includes logic for handling mobile and desktop display, managing the loading bar, and enabling fullscreen mode. Dependencies include the Unity engine loader script and the HTML structure with specific IDs for UI elements. ```javascript var container = document.querySelector("#unity-container"); var canvas = document.querySelector("#unity-canvas"); var loadingBar = document.querySelector("#unity-loading-bar"); var progressBarFull = document.querySelector("#unity-progress-bar-full"); var fullscreenButton = document.querySelector("#unity-fullscreen-button"); var warningBanner = document.querySelector("#unity-warning"); function unityShowBanner(msg, type) { function updateBannerVisibility() { warningBanner.style.display = warningBanner.children.length ? 'block' : 'none'; } var div = document.createElement('div'); div.innerHTML = msg; warningBanner.appendChild(div); if (type == 'error') div.style = 'background: red; padding: 10px;'; else { if (type == 'warning') div.style = 'background: yellow; padding: 10px;'; setTimeout(function() { warningBanner.removeChild(div); updateBannerVisibility(); }, 5000); } updateBannerVisibility(); } var buildUrl = "Build"; var loaderUrl = buildUrl + "/{{{ LOADER_FILENAME }}}"; var config = { dataUrl: buildUrl + "/{{{ DATA_FILENAME }}}", frameworkUrl: buildUrl + "/{{{ FRAMEWORK_FILENAME }}}", #if USE_WASM codeUrl: buildUrl + "/{{{ CODE_FILENAME }}}", #endif #if MEMORY_FILENAME memoryUrl: buildUrl + "/{{{ MEMORY_FILENAME }}}", #endif #if SYMBOLS_FILENAME symbolsUrl: buildUrl + "/{{{ SYMBOLS_FILENAME }}}", #endif streamingAssetsUrl: "StreamingAssets", companyName: {{{ JSON.stringify(COMPANY_NAME) }}}, productName: {{{ JSON.stringify(PRODUCT_NAME) }}}, productVersion: {{{ JSON.stringify(PRODUCT_VERSION) }}}, showBanner: unityShowBanner, }; if (/iPhone|iPad|iPod|Android/i.test(navigator.userAgent)) { var meta = document.createElement('meta'); meta.name = 'viewport'; meta.content = 'width=device-width, height=device-height, initial-scale=1.0, user-scalable=no, shrink-to-fit=yes'; document.getElementsByTagName('head')[0].appendChild(meta); container.className = "unity-mobile"; config.devicePixelRatio = 1; canvas.style.width = '100%'; canvas.style.height = '100%'; } else { canvas.style.width = '100%'; canvas.style.height = '100%'; } #if BACKGROUND_FILENAME canvas.style.background = "url('" + buildUrl + "/{{{ BACKGROUND_FILENAME.replace(/'/g, '%27') }}}') center / cover"; #endif loadingBar.style.display = "block"; var script = document.createElement("script"); script.src = loaderUrl; script.onload = () => { createUnityInstance(canvas, config, (progress) => { progressBarFull.style.width = 100 * progress + "%}; }).then((unityInstance) => { window.unityInstance = unityInstance; loadingBar.style.display = "none"; fullscreenButton.onclick = () => { unityInstance.SetFullscreen(1); }; }).catch((message) => { alert(message); }); }; document.body.appendChild(script); ``` -------------------------------- ### Rust: Create and Initialize NFT Mint Account and Metadata Source: https://github.com/solana-developers/program-examples/blob/main/tokens/token-2022/nft-meta-data-pointer/anchor-example/README.md This Rust code snippet demonstrates the creation and initialization of a mint account for an NFT on Solana. It calculates the required space and lamports, creates the account using the system program, assigns it to the token program, and initializes the metadata pointer and the mint account itself. Dependencies include Solana programs like system_program, token_2022, and spl_token_metadata_interface. ```rust let space = ExtensionType::try_calculate_account_len::( &[ExtensionType::MetadataPointer]) .unwrap(); // This is the space required for the metadata account. // We put the meta data into the mint account at the end so we // don't need to create and additional account. let meta_data_space = 250; let lamports_required = (Rent::get()?).minimum_balance(space + meta_data_space); msg!( "Create Mint and metadata account size and cost: {} lamports: {}", space as u64, lamports_required ); system_program::create_account( CpiContext::new( ctx.accounts.token_program.to_account_info(), system_program::CreateAccount { from: ctx.accounts.signer.to_account_info(), to: ctx.accounts.mint.to_account_info(), }, ), lamports_required, space as u64, &ctx.accounts.token_program.key(), )?; // Assign the mint to the token program system_program::assign( CpiContext::new( ctx.accounts.token_program.to_account_info(), system_program::Assign { account_to_assign: ctx.accounts.mint.to_account_info(), }, ), &token_2022::ID, )?; // Initialize the metadata pointer (Need to do this before initializing the mint) let init_meta_data_pointer_ix = spl_token_2022::extension::metadata_pointer::instruction::initialize( &Token2022::id(), &ctx.accounts.mint.key(), Some(ctx.accounts.nft_authority.key()), Some(ctx.accounts.mint.key()), ) .unwrap(); invoke( &init_meta_data_pointer_ix, &[ ctx.accounts.mint.to_account_info(), ctx.accounts.nft_authority.to_account_info() ], )?; // Initialize the mint cpi let mint_cpi_ix = CpiContext::new( ctx.accounts.token_program.to_account_info(), token_2022::InitializeMint2 { mint: ctx.accounts.mint.to_account_info(), }, ); token_2022::initialize_mint2( mint_cpi_ix, 0, &ctx.accounts.nft_authority.key(), None).unwrap(); // We use a PDA as a mint authority for the metadata account because // we want to be able to update the NFT from the program. let seeds = b"nft_authority"; let bump = ctx.bumps.nft_authority; let signer: &[&[&[u8]]] = &[&[seeds, &[bump]]]; msg!("Init metadata {0}", ctx.accounts.nft_authority.to_account_info().key); // Init the metadata account let init_token_meta_data_ix = &spl_token_metadata_interface::instruction::initialize( &spl_token_2022::id(), ctx.accounts.mint.key, ctx.accounts.nft_authority.to_account_info().key, ctx.accounts.mint.key, ctx.accounts.nft_authority.to_account_info().key, "Beaver".to_string(), "BVA".to_string(), "https://arweave.net/MHK3Iopy0GgvDoM7LkkiAdg7pQqExuuWvedApCnzfj0".to_string(), ); invoke_signed( init_token_meta_data_ix, &[ctx.accounts.mint.to_account_info().clone(), ctx.accounts.nft_authority.to_account_info().clone()], signer, )?; // Update the metadata account with an additional metadata field in this case the player level invoke_signed( &spl_token_metadata_interface::instruction::update_field( &spl_token_2022::id(), ctx.accounts.mint.key, ctx.accounts.nft_authority.to_account_info().key, spl_token_metadata_interface::state::Field::Key("level".to_string()), "1".to_string(), ), &[ ctx.accounts.mint.to_account_info().clone(), ctx.accounts.nft_authority.to_account_info().clone(), ], signer )?; // Create the associated token account associated_token::create( CpiContext::new( ctx.accounts.associated_token_program.to_account_info(), associated_token::Create { payer: ctx.accounts.signer.to_account_info(), associated_token: ctx.accounts.token_account.to_account_info(), authority: ctx.accounts.signer.to_account_info(), mint: ctx.accounts.mint.to_account_info(), system_program: ctx.accounts.system_program.to_account_info(), token_program: ctx.accounts.token_program.to_account_info(), }, ))?; // Mint one token to the associated token account of the player ``` -------------------------------- ### Generate SDKs - pnpm Source: https://github.com/solana-developers/program-examples/blob/main/tokens/token-2022/transfer-hook/pblock-list/pinocchio/readme.md Generates Rust and TypeScript SDKs for interacting with the Block List smart contract using pnpm. This command automates the creation of client libraries. ```bash pnpm install pnpm run generate-sdks ``` -------------------------------- ### Cross-Program Invocation (CPI) in Rust Source: https://context7.com/solana-developers/program-examples/llms.txt Illustrates how to invoke instructions on external programs from within your own Solana program using Cross-Program Invocation (CPI). This example involves a 'hand' program invoking a 'lever' program to switch a power status. ```rust use anchor_lang::prelude::*; declare_id!("Bi5N7SUQhpGknVcqPTzdFFVueQoxoUu8YTLz75J6fT8A"); declare_program!(lever); use lever::accounts::PowerStatus; use lever::cpi::accounts::SwitchPower; use lever::cpi::switch_power; use lever::program::Lever; #[program] pub mod hand { use super::*; pub fn pull_lever(ctx: Context, name: String) -> Result<()> { let cpi_ctx = CpiContext::new( ctx.accounts.lever_program.to_account_info(), SwitchPower { power: ctx.accounts.power.to_account_info(), }, ); switch_power(cpi_ctx, name)?; Ok(()) } } #[derive(Accounts)] pub struct PullLever<'info> { #[account(mut)] pub power: Account<'info, PowerStatus>, pub lever_program: Program<'info, Lever>, } // Lever program (target of CPI) #[program] pub mod lever { use super::*; pub fn switch_power(ctx: Context, name: String) -> Result<()> { let power = &mut ctx.accounts.power; power.is_on = !power.is_on; msg!("{} is pulling the power switch!", &name); msg!("The power is now {}!", power.is_on); Ok(()) } } #[derive(Accounts)] pub struct SwitchPower<'info> { #[account(mut)] pub power: Account<'info, PowerStatus>, } #[account] #[derive(InitSpace)] pub struct PowerStatus { pub is_on: bool, } ``` -------------------------------- ### Build CLI - Rust Source: https://github.com/solana-developers/program-examples/blob/main/tokens/token-2022/transfer-hook/pblock-list/pinocchio/readme.md Builds the Rust CLI tool for interacting with the Block List smart contract. This command compiles the command-line interface application. ```bash cd cli cargo build ```