This part details the step-by-step algorithm for implementing a Solidity Solang program for NFT minting and transfer, where the NFT mint authority is a Program Derived Address (PDA).
illustration
b
Build, Deploy And Test NFT Program
  • Build the pda-mint-authority program.
  • Deploy and test the minter program on Solana's Devnet.

To begin, navigate to your anchor.toml file and switch the cluster to devnet. Then, in your project's root directory, execute the following command to build the program:

anchor build

This command generates a target folder in the project root and compiles the Solana program, enabling client-side interaction through RPC methods.

First, check your configuration:

solana config get

You should see an output similar to this:

Config File: ~/.config/solana/cli/config.yml
RPC URL: https://api.devnet.solana.com
WebSocket URL: wss://api.devnet.solana.com/ (computed)
Keypair Path: ~/.config/solana/id.json
Commitment: confirmed

If needed, set your cluster to devnet:

solana config set --url https://api.devnet.solana.com

Then, generate a new keypair for your wallet:

solana-keygen new

Verify your wallet address and balance:

solana address
solana balance

If you need Devnet SOL, airdrop tokens:

solana airdrop 4

To deploy, start a devnet cluster:

solana-test-validator

Then deploy your program:

anchor deploy

You should see a confirmation like this:

cpiinvokesigned git:(master) ✗ anchor deploy
Deploying cluster: https://api.devnet.solana.com
Upgrade authority: /Users/shivamsoni/.config/solana/id.json
Deploying program "pda_mint_authority"...
Program path: /Users/shivamsoni/Desktop/superteam/grant-program/solidityForsolana/content/module-5-pda/pda/cpitransferpda/cpiinvokesigned/target/deploy/pda_mint_authority.so...
Program Id: CEsT9vBsrx3GcYPpVPk9EaRKZpvLRs2iWbyUWy6fu1zo

Deploy success

After deploying, update the program IDs in both your Solidity file and anchor.toml to match the newly deployed programs. The updated anchor.toml should look like this:

[features]
seeds = false
skip-lint = false

[programs.devnet]
pda_mint_authority = "CEsT9vBsrx3GcYPpVPk9EaRKZpvLRs2iWbyUWy6fu1zo"

[registry]
url = "https://api.apr.dev"

[provider]
cluster = "Devnet"
wallet = "~/.config/solana/id.json"

[scripts]
test = "yarn run ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts"

[[test.validator.clone]]
address = "metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s"

Rebuild the program:

anchor build

Ensure all dependencies are installed:

yarn install
npm install

Finally, run tests:

anchor test

Find your program's wallet address using Solana address and view its details on Solana Explorer

  • Find your Minted NFT by creating an NFT TX signature

nft-mint

Now we are moving to transfer the NFT to another user or buyer for this

Add this test case

Here mint is our minted NFT mint account, buyer is a cli-generated file system wallet.

Here we are getting a public key of the buyer using this created method

import * as anchor from "@coral-xyz/anchor"
import fs from 'mz/fs'

export async function createKeypairFromFile(
 filePath: string,
): Promise<anchor.web3.Keypair> {
    const secretKeyString = await fs.readFile(filePath, {encoding: 'utf8'});
    const secretKey = Uint8Array.from(JSON.parse(secretKeyString));
    return anchor.web3.Keypair.fromSecretKey(secretKey);
}
it("transfer the NFT to another wallet!", async () => {
 // const mint: anchor.web3.PublicKey = new anchor.web3.PublicKey(
 //   "EgKQwGsYksnD5GuAkdUozmMi692iFHFEJUfZuTr5uMjq"
 // );

 const buyer: anchor.web3.Keypair = await createKeypairFromFile(__dirname + "/keypairs/newowner.json");
 console.log(`Buyer public key: ${buyer.publicKey}`);

 const sellerTokenAccount = await getOrCreateAssociatedTokenAccount(
   connection,
   wallet.payer, // payer
   mint, // mint account
   wallet.publicKey // owner account
 );

 console.log("seller token  account", sellerTokenAccount);

 // Derive wallet's associated token account address for mint
 const buyerTokenAccount = await getOrCreateAssociatedTokenAccount(
   connection,
   wallet.payer, // payer
   mint, // mint account
   buyer.publicKey // owner account
 );

 console.log("buyerTokenAccount", buyerTokenAccount);

 const tx = await program.methods
   .transferNft()
   .accounts({
     owner: wallet.publicKey,
     from: sellerTokenAccount.address,
     to: buyerTokenAccount.address,
   })
   .signers([wallet.payer])
   .rpc();
 console.log("Your transaction signature", tx);

 const buyerTokenAccountAmount = (
   await getAccount(connection, buyerTokenAccount.address)
 ).amount;
 console.log("buyerTokenAccountAmount", buyerTokenAccountAmount);
});

In this test case we are fetching a mint account and a buyer account Next we create seller and buyer token accounts with this mint then transfer the nft using cpi to spl token program

  • Now comment on the mint test case and run the transfer nft test case(because a pda is derived only once for a program)
anchor test
Your transaction signature 4eNJrw3zqFBUaL7hw2TQZ79Xt5mhzSpqggzHA2GSWh5oBkxUC6CXELAvvsTFto4urN3UuBiSraVEGPUAjE2PWrwb
buyerTokenAccountAmount 1n
    ✔ transfer the NFT to another wallet! (5384ms)


  1 passing (5s)

You have successfully built, deployed, and tested a Solidity-based NFT minting program on Solana's Devnet. This process included setting up the development environment, managing wallet and cluster configurations, and deploying the program. By running tests and verifying the results on Solana Explorer, you have gained practical experience in blockchain development with Solana and Solidity. This marks an important step in your journey as a blockchain developer, paving the way for more advanced applications and dApp integrations. Congratulations on your progress!