//lib.rs code
use anchor_lang::prelude::*;
pub mod mint;
pub mod sell;
//pub mod swap;
use mint::*;
use sell::*;
//use swap::*;
declare_id!("H5sYvvHMEVSJb2QEwrhCmxGKsMHuntiWz3bmVfxUcBnt");
#[program]
pub mod nft {
use super::*;
pub fn mint(
ctx: Context<MintNft>,
creator_key: Pubkey,
metadata_title: String,
metadata_symbol: String,
metadata_uri: String,
) -> Result<()> {
mint::mint(ctx, creator_key, metadata_title, metadata_symbol, metadata_uri)
}
pub fn sell(ctx: Context<SellNft>, sale_lamports: u64) -> Result<()> {
sell::sell(ctx, sale_lamports)
}
}
// mint.rs code
use {
anchor_lang::{
prelude::*,
solana_program::program::invoke,
system_program,
},
anchor_spl::{
associated_token,
token,
token::{Token, InitializeMint, MintTo, Transfer},
},
mpl_token_metadata::{
ID as TOKEN_METADATA_ID,
instruction as token_instruction,
instruction:: {create_metadata_accounts_v3}
},
};
pub fn mint(
ctx: Context<MintNft>,
creator_key: Pubkey,
metadata_title: String,
metadata_symbol: String,
metadata_uri: String,
) -> Result<()> {
msg!("Creating mint account...");
msg!("Mint: {}", &ctx.accounts.mint.key());
system_program::create_account(
CpiContext::new(
ctx.accounts.token_program.to_account_info(),
system_program::CreateAccount {
from: ctx.accounts.mint_authority.to_account_info(),
to: ctx.accounts.mint.to_account_info(),
},
),
10000000,
82,
&ctx.accounts.token_program.key(),
)?;
msg!("Initializing mint account...");
msg!("Mint: {}", &ctx.accounts.mint.key());
token::initialize_mint(
CpiContext::new(
ctx.accounts.token_program.to_account_info(),
token::InitializeMint {
mint: ctx.accounts.mint.to_account_info(),
rent: ctx.accounts.rent.to_account_info(),
},
),
0,
&ctx.accounts.mint_authority.key(),
Some(&ctx.accounts.mint_authority.key()),
)?;
msg!("Creating token account...");
msg!("Token Address: {}", &ctx.accounts.token_account.key());
associated_token::create(
CpiContext::new(
ctx.accounts.associated_token_program.to_account_info(),
associated_token::Create {
payer: ctx.accounts.mint_authority.to_account_info(),
associated_token: ctx.accounts.token_account.to_account_info(),
authority: ctx.accounts.mint_authority.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(),
},
),
)?;
msg!("Minting token to token account...");
msg!("Mint: {}", &ctx.accounts.mint.to_account_info().key());
msg!("Token Address: {}", &ctx.accounts.token_account.key());
token::mint_to(
CpiContext::new(
ctx.accounts.token_program.to_account_info(),
token::MintTo {
mint: ctx.accounts.mint.to_account_info(),
to: ctx.accounts.token_account.to_account_info(),
authority: ctx.accounts.mint_authority.to_account_info(),
},
),
1,
)?;
msg!("Creating metadata account...");
msg!("Metadata account address: {}", &ctx.accounts.metadata.to_account_info().key());
let creator = vec![
mpl_token_metadata::state::Creator {
address: creator_key,
verified: false,
share: 100,
},
mpl_token_metadata::state::Creator {
address: ctx.accounts.mint_authority.key(),
verified: false,
share: 0,
},
];
invoke(
&create_metadata_accounts_v3(
TOKEN_METADATA_ID,
ctx.accounts.metadata.key(),
ctx.accounts.mint.key(),
ctx.accounts.mint_authority.key(),
ctx.accounts.mint_authority.key(),
ctx.accounts.mint_authority.key(),
metadata_title,
metadata_symbol,
metadata_uri,
Some(creator),
1,
true,
false,
None,
None,
None,
),
&[
ctx.accounts.metadata.to_account_info(),
ctx.accounts.mint.to_account_info(),
ctx.accounts.token_account.to_account_info(),
ctx.accounts.mint_authority.to_account_info(),
ctx.accounts.rent.to_account_info(),
],
)?;
msg!("Creating master edition metadata account...");
msg!("Master edition metadata account address: {}", &ctx.accounts.master_edition.to_account_info().key());
invoke(
&token_instruction::create_master_edition_v3(
TOKEN_METADATA_ID,
ctx.accounts.master_edition.key(),
ctx.accounts.mint.key(),
ctx.accounts.mint_authority.key(),
ctx.accounts.mint_authority.key(),
ctx.accounts.metadata.key(),
ctx.accounts.mint_authority.key(),
Some(0),
),
&[
ctx.accounts.master_edition.to_account_info(),
ctx.accounts.metadata.to_account_info(),
ctx.accounts.mint.to_account_info(),
ctx.accounts.token_account.to_account_info(),
ctx.accounts.mint_authority.to_account_info(),
ctx.accounts.rent.to_account_info(),
],
)?;
msg!("Token mint process completed successfully.");
Ok(())
}
#[derive(Accounts)]
pub struct MintNft<'info> {
/// CHECK: We're about to create this with Metaplex
#[account(mut)]
pub metadata: UncheckedAccount<'info>,
/// CHECK: We're about to create this with Metaplex
#[account(mut)]
pub master_edition: UncheckedAccount<'info>,
#[account(mut)]
pub mint: Signer<'info>,
/// CHECK: We're about to create this with Anchor
#[account(mut)]
pub token_account: UncheckedAccount<'info>,
#[account(mut)]
pub mint_authority: Signer<'info>,
pub rent: Sysvar<'info, Rent>,
pub system_program: Program<'info, System>,
pub token_program: Program<'info, token::Token>,
pub associated_token_program: Program<'info, associated_token::AssociatedToken>,
/// CHECK: Metaplex will check this
pub token_metadata_program: UncheckedAccount<'info>,
}
//test-mint code
import * as anchor from "@coral-xyz/anchor";
import { Nft } from "../target/types/nft";
import { assert } from "chai";
describe("nft", async () => {
const testNftTitle = "Chai";
const testNftSymbol = "Gulab";
const testNftUri = "https://github.com/Coding-and-Crypto/Rust-Solana-Tutorial/blob/master/nfts/mint-nft/assets/example.json";
const provider = anchor.AnchorProvider.env()
const wallet = provider.wallet as anchor.Wallet;
anchor.setProvider(provider);
const program = anchor.workspace.Nft as anchor.Program<Nft>;
const TOKEN_METADATA_PROGRAM_ID = new anchor.web3.PublicKey(
"metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s"
);
const mintFungibleAmount = 1 * anchor.web3.LAMPORTS_PER_SOL;
let associatedTokenAccount = undefined;
it("Mint!", async () => {
// Derive the mint address and the associated token account address
const mintKeypair: anchor.web3.Keypair = anchor.web3.Keypair.generate();
const tokenAddress = await anchor.utils.token.associatedAddress({
mint: mintKeypair.publicKey,
owner: wallet.publicKey
});
console.log(`New token: ${mintKeypair.publicKey}`);
// Derive the metadata and master edition addresses
const metadataAddress = (await anchor.web3.PublicKey.findProgramAddress(
[
Buffer.from("metadata"),
TOKEN_METADATA_PROGRAM_ID.toBuffer(),
mintKeypair.publicKey.toBuffer(),
],
TOKEN_METADATA_PROGRAM_ID
))[0];
console.log("Metadata initialized");
const masterEditionAddress = (await anchor.web3.PublicKey.findProgramAddress(
[
Buffer.from("metadata"),
TOKEN_METADATA_PROGRAM_ID.toBuffer(),
mintKeypair.publicKey.toBuffer(),
Buffer.from("edition"),
],
TOKEN_METADATA_PROGRAM_ID
))[0];
console.log("Master edition metadata initialized");
// Transact with the "mint" function in our on-chain program
try {
const tx = await program.methods.mint(
mintKeypair.publicKey, testNftTitle, testNftSymbol, testNftUri
)
.accounts({
masterEdition: masterEditionAddress,
metadata: metadataAddress,
mint: mintKeypair.publicKey,
tokenAccount: tokenAddress,
mintAuthority: wallet.publicKey,
tokenMetadataProgram: TOKEN_METADATA_PROGRAM_ID,
})
.signers([mintKeypair])
.rpc({
skipPreflight: true,
});
} catch (error) {
console.error("error",error)
}
})
})
/// dependencies
anchor-lang = { version = "0.26.0", features = ["init-if-needed"]} anchor-spl = {version = "0.26.0",features = ["metadata"]} mpl-token-metadata = { version = "=1.9.0", features = ["no-entrypoint"] } solana-program = "=1.14.13" winnow="=0.4.1" toml_datetime="=0.6.1" spl-token-swap = { version="3.0.0", features = [ "no-entrypoint" ] }
/// test script test-mint = "yarn run ts-mocha -p ./tsconfig.json -t 1000000 tests/**/test-mint.ts"
i run with anchor run test-mint