|
Rahul Maurya Oodles

Rahul Maurya (Backend-Associate Consultant L2- Development)

Experience:1+ yrs

Rahul is a highly skilled Backend Developer with expertise in Node.js, JavaScript, Python, HTML, CSS, React.js, Redux, Git, MySQL, MongoDB, GitHub, Heroku, Vercel, and Render. He has undergone multiple courses to enhance his skill set, including Data Structures & Algorithms. Rahul has invested considerable effort in studying and implementing new concepts in data and development, with a particular focus on leveraging these insights to effectively address existing challenges.

Rahul Maurya Oodles
Rahul Maurya
(Associate Consultant L2- Development)

Rahul is a highly skilled Backend Developer with expertise in Node.js, JavaScript, Python, HTML, CSS, React.js, Redux, Git, MySQL, MongoDB, GitHub, Heroku, Vercel, and Render. He has undergone multiple courses to enhance his skill set, including Data Structures & Algorithms. Rahul has invested considerable effort in studying and implementing new concepts in data and development, with a particular focus on leveraging these insights to effectively address existing challenges.

LanguageLanguages

DotENGLISH

Fluent

DotHINDI

Fluent

Skills
Skills

DotDyanmoDB

80%

DotpBFT (Practical Byzantine Fault Tolerance)

60%

DotEtherscan

60%

DotHyperledger Fabric CA

60%

DotNestJS

80%

DotRAFT

60%

DotNo SQL/Mongo DB

80%

DotNode Js

80%

DotMern Stack

80%

DotRust

80%

DotFullstack

60%

DotSolana Web3.js

80%

DotTelegram Bot

60%

DotMetaMask

60%

DotCoinbase API

80%

DotPostgres

80%

DotSolana

80%
ExpWork Experience / Trainings / Internship

Sep 2023-Present

Intern - Development

Gurugram


Oodles Technologies

Gurugram

Sep 2023-Present

EducationEducation

2020-2023

Dot

Institute of Engineering and Technology

B.tech-Information Technology

Top Blog Posts
Multi-Level Staking Smart Contract on Ethereum with Solidity

Introduction to Multi-Level Staking Smart Contract Development

 

Creating a multi-level staking contract on Ethereum using smart contract development opens up exciting possibilities for decentralized finance projects by enabling layered rewards and incentives for users. Using Solidity, Ethereum's native programming language, developers can build secure and scalable staking solutions that allow participants to earn rewards based on their staking levels. In this guide, we'll walk through the process of developing a multi-level staking contract, covering everything from setup to implementation, so you can leverage Ethereum's blockchain for advanced staking functionality.

 

In this article, we will discuss the basics of staking contracts, and the characteristics of multi-level staking contracts.

 

Prerequisites

 

  • Familiarity with Solidity and the ERC-20 token standard.
  • Understanding of concepts like staking.
  • An ERC-20 token contract deployed on the same network where you'll deploy this staking contract.
  • Familiar with Remix IDE

     

    You may also like | Creating a Token Vesting Contract on Solana Blockchain

     

    What is Staking

     

    To maintain the security of a blockchain network, confirm transactions, and generate rewards, cryptocurrency holders stake or lock up their assets. Staking, particularly on Proof-of-Stake (PoS) blockchains and their variations, entails actively taking part in the network's functioning as opposed to conventional bank savings or investments.

     

    Multi-level staking

     

    Multi-level staking is an advanced staking model where users can earn different levels of rewards based on various criteria, such as the amount of assets they stake or the duration they choose to lock their funds.

     

    Also, Explore | How to Implement a Merkle Tree for Secure Data Verification

     

    Multi-Level Staking Contract on Ethereum Using Solidity

     

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.24;

interface ERC20 {
    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
    function transfer(address recipient, uint256 amount) external returns (bool);
}

contract MultiLevelStaking {

    struct Stake {
        uint256 amount;
        uint256 startTime;
        uint256 level;
    }

   mapping(address => Stake[]) public stakes;
    mapping(uint256 => uint256) public rewardRates;

    uint256 constant LEVEL_ONE_MIN = 10 * 10**18;
    uint256 constant LEVEL_TWO_MIN = 20 * 10**18;
    uint256 constant LEVEL_THREE_MIN = 50 * 10**18;

    address public tokenAddress;

    constructor(address _tokenAddress) {
        tokenAddress = _tokenAddress;

        rewardRates[1] = 5;
        rewardRates[2] = 10;
        rewardRates[3] = 15;
    }

    function stake(uint256 amount) public {
    require(amount > 0, "Amount should be greater than 0");
    require(ERC20(tokenAddress).transferFrom(msg.sender, address(this), amount), "Transfer failed");

    uint256 level = getStakeLevel(amount);

    // Add new stake to the user's array of stakes
    stakes[msg.sender].push(Stake({
        amount: amount,
        startTime: block.timestamp,
        level: level
    }));
}

    function getStakeLevel(uint256 amount) internal pure returns (uint256) {
        if (amount >= LEVEL_THREE_MIN) {
            return 3;
        } else if (amount >= LEVEL_TWO_MIN) {
      return 2;
        } else if (amount >= LEVEL_ONE_MIN) {
            return 1;
        }
        return 0;
    }

    function calculateReward(address staker) public view returns (uint256) {
    Stake[] memory userStakes = stakes[staker];
    require(userStakes.length > 0, "No active stakes");

    uint256 totalReward = 0;

    for (uint256 i = 0; i < userStakes.length; i++) {
        Stake memory stakeInfo = userStakes[i];
        uint256 stakingDuration = block.timestamp - stakeInfo.startTime;
        uint256 rate = rewardRates[stakeInfo.level];
        uint256 reward = (stakeInfo.amount * rate * stakingDuration) / (365 days * 100);
        totalReward += reward;
    }

    return totalReward;
}


   function unstakeAll() public {
    Stake[] memory userStakes = stakes[msg.sender];
    require(userStakes.length > 0, "No active stakes");

    uint256 totalAmount = 0;

    // Loop through each stake, calculate reward, and add to total amount
    for (uint256 i = 0; i < userStakes.length; i++) {
        uint256 reward = calculateSingleStakeReward(userStakes[i]);
        totalAmount += userStakes[i].amount + reward;
    }

    // Clear all stakes for the user
    delete stakes[msg.sender];

    // Transfer the total amount back to the user
    require(ERC20(tokenAddress).transfer(msg.sender, totalAmount), "Transfer failed");
}
function unstake(uint256 index) public {
   require(index < stakes[msg.sender].length, "Invalid index");

    Stake memory stakeInfo = stakes[msg.sender][index];
    uint256 reward = calculateSingleStakeReward(stakeInfo);

    uint256 totalAmount = stakeInfo.amount + reward;

    // Remove the stake from the array by swapping and popping
    stakes[msg.sender][index] = stakes[msg.sender][stakes[msg.sender].length - 1];
    stakes[msg.sender].pop();

    // Transfer the unstaked amount plus reward back to the user
    require(ERC20(tokenAddress).transfer(msg.sender, totalAmount), "Transfer failed");
}
function calculateSingleStakeReward(Stake memory stakeInfo) internal view returns (uint256) {
    uint256 stakingDuration = block.timestamp - stakeInfo.startTime;
    uint256 rate = rewardRates[stakeInfo.level];
    return (stakeInfo.amount * rate * stakingDuration) / (365 days * 100);
}
}

 

Also, Read | Smart Contract Upgradability | Proxy Patterns in Solidity

 

Explanation of the Each Function

 

Constructor

 

The Constructor Initializes the contract with the token address and sets reward rates for each staking level.

 

constructor(address _tokenAddress) {
    tokenAddress = _tokenAddress;
    rewardRates[1] = 5;
    rewardRates[2] = 10;
    rewardRates[3] = 15;
}

 

Stake

 

The stake function allows users to stake a specified amount of tokens, recording the staking level, amount, and start time.

 

function stake(uint256 amount) public {
    require(amount > 0, "Amount should be greater than 0");
    require(ERC20(tokenAddress).transferFrom(msg.sender, address(this), amount), "Transfer failed");

    uint256 level = getStakeLevel(amount);

    stakes[msg.sender].push(Stake({
        amount: amount,
        startTime: block.timestamp,
        level: level
    }));
}

 

calculateReward

 

This method calculates the total rewards earned for all stakes of a particular user and returns the rewards.

 

function calculateReward(address staker) public view returns (uint256) {
    Stake[] memory userStakes = stakes[staker];
    require(userStakes.length > 0, "No active stakes");

    uint256 totalReward = 0;

    for (uint256 i = 0; i < userStakes.length; i++) {
        Stake memory stakeInfo = userStakes[i];
        uint256 stakingDuration = block.timestamp - stakeInfo.startTime;
        uint256 rate = rewardRates[stakeInfo.level];
        uint256 reward = (stakeInfo.amount * rate * stakingDuration) / (365 days * 100);
        totalReward += reward;
    }

    return totalReward;
}

 

unstakeAll

 

The unstake all function allows a user to unstake all of their stakes and receive the total staked amount plus all rewards.

 

function unstakeAll() public {
    Stake[] memory userStakes = stakes[msg.sender];
    require(userStakes.length > 0, "No active stakes");

    uint256 totalAmount = 0;

    for (uint256 i = 0; i < userStakes.length; i++) {
        uint256 reward = calculateSingleStakeReward(userStakes[i]);
        totalAmount += userStakes[i].amount + reward;
    }

    delete stakes[msg.sender];

    require(ERC20(tokenAddress).transfer(msg.sender, totalAmount), "Transfer failed");
}

 

unstake

 

The unstake function allows users to unstake a specific stake by index and receive the principal plus rewards for that specific stake.

 

function unstake(uint256 index) public {
    require(index < stakes[msg.sender].length, "Invalid index");

    Stake memory stakeInfo = stakes[msg.sender][index];
    uint256 reward = calculateSingleStakeReward(stakeInfo);

    uint256 totalAmount = stakeInfo.amount + reward;

    stakes[msg.sender][index] = stakes[msg.sender][stakes[msg.sender].length - 1];
    stakes[msg.sender].pop();

    require(ERC20(tokenAddress).transfer(msg.sender, totalAmount), "Transfer failed");
}

 

Also, Explore | How to Write and Deploy Modular Smart Contracts

 

Steps to Create and Deploy on Remix

 

  • Go to Remix IDE, which is a browser-based Solidity development environment.
  • In the Remix IDE, create a new file under the contracts folder. Name it MultiLevelStaking.sol.
    Paste the MultiLevelStaking Solidity contract code into this file.
  • Set the compiler version to 0.8.24 
  • Click the Compile MultiLevelStaking.sol button.

     

Go to the "Deploy & Run Transactions" tab.

 

  1. Set Environment to Injected Web3 to deploy using MetaMask 
  2. In the Deploy section, input the constructor argument:
    _tokenAddress: Address of the ERC-20 token contract that users will be staking.
  3. Click Deploy, and MetaMask will prompt you to confirm the transaction. Confirm and pay for the gas fee.


    Verify Deployment:

     

    After deployment, the contract instance will appear under the Deployed Contracts section in Remix.

     

    Conclusion 

     

    Building a multi-level staking contract on Ethereum with Solidity allows you to harness the power of decentralized finance while providing enhanced incentives for your users. With layered rewards and flexible staking options, these contracts not only boost user engagement but also promote long-term participation in your ecosystem. By implementing a secure and scalable staking model, you're positioned to offer a competitive, feature-rich staking solution that can adapt as the DeFi landscape continues to evolve. Now, you're equipped to launch a robust staking contract that meets the needs of today's crypto users. If you are looking to create crypto-staking solutions, connect with our skilled crypto/token developers to get started. 

Category: Blockchain
Integrate Raydium Swap Functionality on a Solana Program

Solana is recognized as a top platform for blockchain app development due to its low transaction fees and excellent throughput. With its smooth token swaps, yield farming, and liquidity pools, Raydium is a well-known automated market maker (AMM) and liquidity provider among the many protocols that flourish on Solana. Developers wishing to expand on this dynamic environment have many options when integrating Raydium's switch feature into custom Solana software.

 

Also, Explore | How to Develop a Crypto Swap Aggregator Platform


This blog will guide you through the process of using the Raydium SDK and the Solana Web3.js framework to integrate the swap functionality of Raydium into your Solana program.

 

You may also like | How to Build a Solana Sniper Bot

 

Using Raydium SDK and Solana Web.js to Integrate Swap Functionality on a Solana Prorgram 

 

Prerequisites:

 

  • Node.js is installed on your machine.
  • Solana CLI installed and configured.
  • Basic knowledge of TypeScript and Solana development.
  • A basic understanding of how Raydium works.

     

    Setting Up the Environment: 

     

  • npm init -y
  • npm install @solana/web3.js @solana/spl-token @raydium-io/raydium-sdk decimal.js fs
  • @solana/web3.js: The official Solana JavaScript SDK.
  • @solana/spl-token: A library for interacting with the Solana Program Library (SPL) tokens.
  • @raydium-io/raydium-sdk: The Raydium SDK interacts with the protocol's AMM and liquidity pools.
  • decimal.js: A library for handling arbitrary-precision decimal arithmetic.

 

Also, Explore | SPL-404 Token Standard | Enhancing Utility in the Solana Ecosystem

 

Connect with Solana Cluster 

 

import { Connection, clusterApiUrl, Keypair, PublicKey, Transaction } from '@solana/web3.js';

const connection = new Connection(clusterApiUrl('devnet'), 'confirmed');
console.log("Connected to Solana Devnet");

 

Payer's Keypair Loading:

 

import * as fs from 'fs';

const data = fs.readFileSync('./secret.json', 'utf8');
const secretKey = Uint8Array.from(JSON.parse(data));
const payer = Keypair.fromSecretKey(secretKey);
console.log("Payer's public key:", payer.publicKey.toBase58());

 

Creating and Minting SPL Tokens

 

import { createMint, getMint, mintTo, getOrCreateAssociatedTokenAccount } from '@solana/spl-token';
const token1 = await createMint(connection, payer, payer.publicKey, null, 9);
const token2 = await createMint(connection, payer, payer.publicKey, null, 9);
const token1Account = await getOrCreateAssociatedTokenAccount(connection, payer, token1, payer.publicKey);
const token2Account = await getOrCreateAssociatedTokenAccount(connection, payer, token2, payer.publicKey);
await mintTo(connection, payer, token1, token1Account.address, payer.publicKey, 1000000000); // 1000 tokens
await mintTo(connection, payer, token2, token2Account.address, payer.publicKey, 1000000000);
console.log("Minted tokens and created associated token accounts.");

 

Creating a Liquidity Pool on Raydium:

 

import { Liquidity, DEVNET_PROGRAM_ID, TxVersion, BN } from '@raydium-io/raydium-sdk';
const targetMarketId = Keypair.generate().publicKey;
const startTime = Math.floor(Date.now() / 1000) + 60 * 60 * 24 * 7;
const walletAccount = await getWalletTokenAccount(connection, payer.publicKey);
const createPoolTx = await Liquidity.makeCreatePoolV4InstructionV2Simple({
    connection,
    programId: DEVNET_PROGRAM_ID.AmmV4,
    marketInfo: {
        marketId: targetMarketId,
        programId: DEVNET_PROGRAM_ID.OPENBOOK_MARKET,
    },
    baseMintInfo: { mint: token1, decimals: 9 },
    quoteMintInfo: { mint: new PublicKey('So11111111111111111111111111111111111111112'), decimals: 9 },
    baseAmount: new BN(10000),
    quoteAmount: new BN(10000),
    startTime: new BN(Math.floor(startTime)),
    ownerInfo: {
        feePayer: payer.publicKey,
        wallet: payer.publicKey,
        tokenAccounts: walletAccount,
        useSOLBalance: true,
    },
    associatedOnly: false,
    checkCreateATAOwner: true,
    makeTxVersion: TxVersion.V0,
});
console.log("Liquidity pool created on Raydium.");

 

Add Liquidity:

 

const addLiquidityTx = await Liquidity.makeAddLiquidityInstructionSimple({
    connection,
    poolKeys,
    userKeys: {
        owner: payer.publicKey,
        payer: payer.publicKey,
        tokenAccounts: walletAccount,
    },
    amountInA: new TokenAmount(new Token(TOKEN_PROGRAM_ID, token1, 9, 'Token1', 'Token1'), 100),
    amountInB: maxAnotherAmount,
    fixedSide: 'a',
    makeTxVersion,
});
console.log("Liquidity added to the pool.");

 

Perform a Swap: 

 

 const swapInstruction = await Liquidity.makeSwapInstruction({
    poolKeys,
    userKeys: {
      owner: payer.publicKey,
      tokenAccountIn: fromTokenAccount,
      tokenAccountOut: toTokenAccount,
    },
    amountIn,
    amountOut: minimumAmountOut,
    fixedSide: "in",
  });

  // Correcting the transaction creation by accessing the correct innerTransaction
  const transaction = new Transaction().add(...swapInstruction.innerTransaction.instructions);

  const transactionSignature = await connection.sendTransaction(
    transaction,
    [payer],
    { skipPreflight: false, preflightCommitment: "confirmed" }
  );

  console.log("Swap transaction signature:", transactionSignature);

 

Also, Explore | How to Get the Transaction Logs on Solana

 

Conclusion

 

You have successfully included Raydium's swap feature into your Solana program by following the instructions provided in this Blog. In the DeFi space, Raydium offers strong tools for swapping and liquidity. If you want to leverage the potential of Solana and Raydium Swap Functionality for your project, connect with our skilled Solana developers to get started. 

Category: Blockchain
How to Get the Transaction History of an NFT

Whether you're developing an NFT price estimator, an analytics platform, or a marketplace similar to OpenSea using NFT development services, you'll likely want to track down an NFT's ownership history and show it to your clients.

An NFT's ownership history can be found in a few different ways. Parsing every transaction made on the blockchain since the genesis block, searching for those connected to the NFT, and understandably presenting the results for humans is one method. This approach usually requires a significant investment of time and engineering resources.

 

You may also like | Unveiling the Top NFT Trends in 2024

 

Prerequisites

 

Install npm and Node.js(> 14) on your local computer.


You can find steps to install node and npm if you still need to install them. Use the following command in your terminal to find out your Node version:

 

node -v

 

Create a Node Project

 

The getAssetTransfers function will be used to obtain the transfer history of a specific NFT. This function accepts several necessary and optional arguments. We will make use of the following arguments in our example:


from block: The block from which the transfer history should be traced. This will be set to 0x0, or the genesis block.

contract addresses: A list of the contract addresses for which we wish to look up the history of transfers. This will just be the primary BAYC contract in our situation.

category: A list of transaction types that we wish to monitor. We simply want to monitor erc721 and token transactions in our situation.

excludeZeroValue: Used to filter out transfers with zero value. Since we are open to any transfer, we shall set this to false.

 

Also, Explore | How Multi Redeemable NFTs Elevate Web3 Experiences

 


const { Alchemy, Network, fromHex } = require("alchemy-sdk");

const config = {
  apiKey: "alchemy api key",
  network: Network.ETH_MAINNET,
};
const alchemy = new Alchemy(config);

const main = async () => {
  const address = ["0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D"];
  
  const response = await alchemy.core.getAssetTransfers({
    fromBlock: "0x0",
    contractAddresses: address,
    category: ["erc721"],
    excludeZeroValue: false,
  });

  const nftId = 1;
  let txns = response.transfers.filter(
    (txn) => fromHex(txn.erc721TokenId) === nftId
  );
  console.log(txns);
};

const getNftTxn = async () => {
  try {
    await main();
  } catch (error) {
    console.log(error);
   
  }
};

getNftTxn();

 

Also, Discover | Compressed NFTs (cNFTs) | Solana's Cost-Effective NFT standard

 

Conclusion

 

Tracking an NFT's transaction history is essential for developing price estimators, analytics platforms, or marketplaces. Using Alchemy's API and the `getAssetTransfers` function, you can efficiently retrieve an NFT's ownership history without parsing all blockchain transactions since the genesis block.

In this guide, we showed how to set up a Node.js project and use Alchemy's SDK to fetch NFT transfer data. By specifying parameters like the starting block, contract addresses, and transaction categories, you can obtain precise transaction histories for your NFTs.

This approach streamlines the process, allowing you to provide valuable insights to your users while focusing on building robust NFT platforms. In case you are looking for NFT development services, take a look at our talent pool of NFT developers who are skilled in addressing diverse industry demands.   

Category: Blockchain
How to Create and Deploy a Token Bound Account | ERC-6551

What if the NFT you own could perform the functions of a "wallet" and represent the asset itself as well? This would enable your asset to communicate with other smart contracts and hold other digital assets inside of it. ERC-6551: Non-fungible Token Bound Accounts, a new Ethereum Improvement Proposal, may soon make such possible. For more about blockchain and smart contracts, visit our smart contract development services

 

What is ERC-6551 (Token Bound Account)

 

ERC-6551 introduces the concept of Token Bound Accounts (TBAs), essentially transforming NFTs into their own smart contract wallets. Each TBA has a unique address and is directly linked to a specific NFT, unlocking a range of new functionalities:


Asset Storage: Unlike traditional wallets where you store your assets, NFTs themselves can now hold assets.

dApp Interaction: NFTs can directly engage with decentralized applications (dApps) including DeFi protocols and DAOs.

Transaction History: Each NFT maintains its own transaction history, independent of the owner's wallet history.

When ownership of the NFT changes, all the assets contained within the TBA are transferred along with it, seamlessly transferring both the NFT and its associated holdings.

 

You may also like | Understanding ERC-404 | The Unofficial Token Standard

 

Use Cases

 

Gaming and Virtual Worlds

 

In blockchain-based games and virtual worlds, ERC-6551 can enhance the player experience by allowing NFTs to hold in-game assets. 

 

For example:

 

Character NFTs: Each character can hold items, skills, and achievements as assets within its TBA.

Virtual Real Estate: Property NFTs can store furniture, decorations, and even other NFTs like artwork.

 

Prerequisites:

 

  • A basic knowledge of ERC-721 and ERC-1155.
  • knowledge of smart contracts and Ethereum.
  • Setup of the development environment: Metamask and Remix.
  • Testnet Token, such as the Sepolia testnet 

     

    We will create and implement smart contracts on one of the given EVMs using Remix IDE. Establishing a new workspace is Remix's initial step.

     

    We'll refer to this workspace as ERC6551. We are going to establish three smart contracts in this workspace:

     

    1. ERC-721: NewNFT.sol

    2. Account.sol

    3. Registry.sol

     

    Two interfaces are included with these contracts as well:

     

    1. Account.sol for IERC6551

    2.Registry.IERC6551.sol

     

    Also, Check | ERC-721 Non-Fungible Token Standard Development
     

Creating an ERC-721 Smart Contract

 

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/Counters.sol";
contract MyToken is ERC721, Ownable {
      using Counters for Counters.Counter;
    Counters.Counter private _tokenIds;
    constructor(address initialOwner)
        ERC721("MyToken", "MTK")
        Ownable(initialOwner)
    {}

    function safeMint(address to, uint256 tokenId) public onlyOwner {
        _safeMint(to, tokenId);
    }
    function _baseURI() internal pure override returns (string memory) {
        return "urlLink";
    }

}

 

Creating a Registry Smart Contract

 

You can think of the registry, also called the Singleton Registry, as a database of NFTs and the Token Bound Accounts that go along with them. A smart contract known as the registry can be implemented on any blockchain that supports the EVM. It has no owner, is unchangeable, and lacks permission. By maintaining this registry, all Token Bound Account addresses are guaranteed to use the same scheme.
 

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import "@openzeppelin/contracts/utils/Create2.sol";
import "./interfaces/IERC6551Registry.sol";

contract ERC6551Registry is IERC6551Registry {
    error InitializationFailed();
    event AccountCreated(
        address _account,
        address implementation,
          uint256 chainId,
        address tokenContract,
        uint256 tokenId,
        uint256 salt
        );
    function createAccount(
        address implementation,
        uint256 chainId,
        address tokenContract,
        uint256 tokenId,
        uint256 salt,
        bytes calldata initData
    ) external returns (address) {
        bytes memory code = _creationCode(implementation, chainId, tokenContract, tokenId, salt);

        address _account = Create2.computeAddress(
            bytes32(salt),
            keccak256(code)
        );

        if (_account.code.length != 0) return _account;

        _account = Create2.deploy(0, bytes32(salt), code);

        if (initData.length != 0) {
            (bool success, ) = _account.call(initData);
            if (!success) revert InitializationFailed();
        }

        emit AccountCreated(
            _account,
            implementation,
            chainId,
            tokenContract,
            tokenId,
            salt
        );

        return _account;
    }

    function account(
        address implementation,
        uint256 chainId,
        address tokenContract,
        uint256 tokenId,
        uint256 salt
    ) external view returns (address) {
        bytes32 bytecodeHash = keccak256(
            _creationCode(implementation, chainId, tokenContract, tokenId, salt)
        );

        return Create2.computeAddress(bytes32(salt), bytecodeHash);
    }

    function _creationCode(
        address implementation_,
        uint256 chainId_,
        address tokenContract_,
        uint256 tokenId_,
        uint256 salt_
    ) internal pure returns (bytes memory) {
        return
            abi.encodePacked(
                hex"3d60ad80600a3d3981f3363d3d373d3d3d363d73",
                implementation_,
                hex"5af43d82803e903d91602b57fd5bf3",
                abi.encode(salt_, chainId_, tokenContract_, tokenId_)
            );
    }
}


 

createAccount: 

 

With an implementation address, this method generates the Token Bound Account for an NFT. 

 

account: 

 

Based on an implementation address, token ID, chainId, NFT address, and salt, compute the Token Bound Account address for an NFT.
 

Both the functions take the following arguments:

 

implementation: The address of the deployed Account Smart Contract

chainId: The chain ID on which the account will be created

token contract: The address of the NFT smart contract

tokenId: The token ID for which the TBA is to be created

salt: It is a unique value to compute the account address

 

Also, Discover | A Comprehensive Guide to ERC-6551 Token Standard

 

Creating an Account Smart Contract

 

The Account.sol contract is the last one we will ever create. The Registry contracts createAccount() and account () methods' implementation address is this smart contract's address on the chain. This smart contract's primary purposes are:


executeCall: This function is used to call the operations only if the signer is the actual owner of the account.

Owner: This function is used to return the owner address of the account linked to the provided NFT.

 

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import "@openzeppelin/contracts/token/ERC721/IERC721.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/interfaces/IERC1271.sol";
import "@openzeppelin/contracts/utils/cryptography/SignatureChecker.sol";

import "@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol";
import "@openzeppelin/contracts/utils/introspection/IERC165.sol";
import "./interfaces/IERC6551Account.sol";

import "./lib/MinimalReceiver.sol";

 contract ERC6551Account is IERC165, IERC1271, IERC6551Account {
    uint256 public nonce;
   event TransactionExecuted(address to,uint256 value ,bytes data);
    receive() external payable {}

    function executeCall(
        address to,
        uint256 value,
        bytes calldata data
    ) external payable returns (bytes memory result) {
        require(msg.sender == owner(), "Not token owner");

        ++nonce;

        emit TransactionExecuted(to, value, data);

        bool success;
        (success, result) = to.call{value: value}(data);

        if (!success) {
            assembly {
                revert(add(result, 32), mload(result))
            }
        }
    }

    function token()
        external
        view
        returns (
            uint256,
            address,
            uint256
        )
    {
        return ERC6551AccountLib.token();
    }

    function owner() public view returns (address) {
        (uint256 chainId, address tokenContract, uint256 tokenId) = this.token();
        if (chainId != block.chainid) return address(0);

        return IERC721(tokenContract).ownerOf(tokenId);
    }

    function supportsInterface(bytes4 interfaceId) public pure returns (bool) {
        return (interfaceId == type(IERC165).interfaceId ||
            interfaceId == type(IERC6551Account).interfaceId);
    }

    function isValidSignature(bytes32 hash, bytes memory signature)
        external
        view
        returns (bytes4 magicValue)
    {
        bool isValid = SignatureChecker.isValidSignatureNow(owner(), hash, signature);

        if (isValid) {
            return IERC1271.isValidSignature.selector;
        }

        return "";
    }
}

 

Deploying the Smart Contracts

 

Compiling and implementing all three contracts is the next stage. From the file explorer area, choose the smart contract you want to deploy. Navigate to the "Compile" section and press the "compile" button. The contracts can also be automatically compiled by turning on the Auto Compile option. Next, navigate to the Deployment section and choose an address from the drop-down menu. Click the Deploy button after making sure you have chosen the relevant contract to be deployed. Repeat this step for all three contracts.

 

Also, Explore | ERC-1155 | An Introduction to Multi Token Standard Development
 

Mint the ERC-721 NFT

 

It's time to mint the NFT now that every contract has been deployed. Choose a different address from the list and copy it. Next, go to the Deployed Contracts area, pick the owner address, and open the deployed MyNFT.sol contract. For the copied address, expand the safeMint() function and mint tokenId 1.
 

Compute TBA Address for NFT

 

The generated NFT's address must now be calculated. To call the method, expand the account() method under the Registry smart contract and input the following arguments.

implementation: The address of the deployed Account smart contract

chainId: 1

tokenContract: The address of the deployed NFT smart contract

tokenId: 1

salt: 0

 

The account address for the supplied NFT will be calculated by this function and returned as the output. 

 

Creating Token Bound Account


This will create a new TBA for the provided NFT. Now to verify, you can go into the transaction details and check the decoded output. It should be the same as the computed address.

 

Also, Check | ERC-4337: Ethereum's Account Abstraction Proposal
 

Testing the TBA

 

We are about to make a call using this recently established Token-bound Address. Choose the owner's address from the drop-down menu to place a call from the contract. Using the TBA, we will transfer 1 ETH from the owner's address to a different address. From the Value type drop-down, choose ETH, then type 1 as the value. Choose and copy a different address from the address drop-down menu. Now, under your TBA contract, expand the executeCall() method and pass the copied address as an argument's input. Keep the bytes as [ and enter the value as 1000000000000000000 (1 ETH). Click the Transact button now. Following a successful execution, you will notice that the receiver address's balance has raised by one.

You would receive an error and the transaction would fail if you attempted to complete this transaction from an address other than the owner's address.

That's it for you. Using a deployed Account smart contract for a specific ERC-721, you have successfully established an ERC-6551 Registry for Token Bound Accounts and confirmed that it can sign transactions on your behalf. If you are looking for reliable smart contract development services, connect with our Solidity developers to get started.

Category: Blockchain
How to Create a Metaverse Smart Contract Example

The Metaverse is a virtual version of reality that resembles our experiences in the real world. Users of the metaverse may participate in activities such as social networking, gaming, trading, events, remote work, and entertainment. They can access the metaverse's virtual world, which is a three-dimensional representation of real-world locations like offices, buildings, trade shows, etc., by dressing up as animated avatars. Metaverse, with the convergence of blockchain solutions, can create numerous benefits.

 

Read Also | Metaverse NFT Marketplace Guide to Beginners
 

Use of SmartContracts in  Metaverse

 

A decentralized or centralized ecosystem might be a part of a metaverse project. Blockchain technology facilitates decentralized metaverses in a number of ways. For example, NFT marketplaces are coupled with decentralized metaverses to enable NFT trade and minting. Smart contracts are used to automate processes and guarantee that activities like trade and transactions are carried out in accordance with the established rules in every part of the metaverse that has been made blockchain-enabled.

Advantages

  • Dependability and credibility supported by the immutability of blockchain
  • The immutability of blockchain prevents tampering and makes fraud prevention easier.
  • Automation removes the need for intermediaries.
  • lucidity, visibility, and transparency

 Creating smart contract for Metaverse

Smart contracts are used by well-known metaverse projects like Decentraland and Axie Infinity to regulate the exchange of digital assets like NFTs, real estate, and land. A smart contract is capable of supporting several token, such as ERC tokens (ERC-1155 and ERC-721). Let's examine the creation of smart contracts for ERC1155 standard

Step 1:   Import the contracts


import "@openzeppelin/contracts/token/ERC1155/ERC1155.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/token/ERC1155/extensions/ERC1155Burnable.sol";

Step 2: Define the inheritance

 Now, we need to provide the inheritance from the previously imported contract. Use this command to access it:

Let's create a smart contract that uses tokens to represent game assets. Our game will include two fungible currencies (gold and silver), two fungible weapons (sword and shield), and one non-fungible crown.


// SPDX-License-Identifier: MIT
// Compatible with OpenZeppelin Contracts ^5.0.0
pragma solidity ^0.8.20;
import "@openzeppelin/contracts/token/ERC1155/ERC1155.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/token/ERC1155/extensions/ERC1155Burnable.sol";
contract MetaverseGame is ERC1155, Ownable, ERC1155Burnable {
    uint256 public constant GOLD = 0;
    uint256 public constant SILVER = 1;
    uint256 public constant SWORD = 2;
    uint256 public constant SHIELD = 3;
    uint256 public constant CROWN = 4;
    constructor() ERC1155("https://ipfs.hashcodeofmetaversegame/assets/{id}.json") {
        _mint(msg.sender, GOLD, 10**18, "");
        _mint(msg.sender, SILVER, 10**18, "");
        _mint(msg.sender, SWORD, 1000, "");
        _mint(msg.sender, SHIELD, 1000, "");
        _mint(msg.sender, CROWN, 1, "");
    }
}

Unlike ERC-20 and ERC-721, we have created fungible and non-fungible tokens from the same contract.

Moreover, please observe that the ERC1155 constructor has received a metadata URI from us. It is possible to link each token ID—whether fungible or not—with NFT-like metadata by passing this metadata.

For example, we can use an ERC-1155 to link a picture of a gold coin to the tokens related to GOLD. 

 

Also, Read | A Comprehensive Guide To Metaverse Token Development
 

Deployment of smart contracts : Conclusion

 

After you have finished the previous steps, your smart contract is prepared for deployment. Using Remix, you can deploy the contract easily. Easy to use and suitable for all kinds of development, The Remix is a vital browser-based tool for developers. Alternatively, you can copy the programmes to the Remix using the smart contract samples from the earlier steps. Paste the code into a newly created file, then save it.

The smart contract can be deployed after the code has been saved and has been assembled. Ensure you have enough test tokens in your MetaMask wallet to carry out the contract.
 

Contact our team of expert blockchain developers today!

 

Category: Blockchain
How to Deploy a smart Contract using Foundry

Foundry is a Rust-based smart contract development toolset for Ethereum. The creation and implementation of smart contracts are made easier with Foundry. By managing dependencies, executing tests, and assisting with deployment, it simplifies the process. Additionally, Foundry offers you a variety of tools for creating smart contracts, including:

 

Forge: Allows you to test, build, and implement smart contracts.

 

Cast: Cast is Foundry's CLI utility for making RPC calls to Ethereum. Send transactions, call smart contracts, and get any kind of chain data.

 

Anvil: Foundry ships with a local testnet node. It can be used to communicate over RPC or to test your contracts from frontends.

 

Chisel: Included with Foundry is a powerful Solidity REPL called Chisel. It can be used to rapidly evaluate how Solidity snippets behave on a forked or local network.

 

Also, Explore | Top 5 Smart Contract Development Companies

 

How to Deploy a Smart Contract using Foundry

 

Initialize the project

Use forge init to launch a new Foundry project:
 

init foundry_project forging

 

A new project folder named foundry_project will result from this. The following items will be in the folder:
 


src : Your smart contracts' default directory is called src.

 

tests: the tests' default directory

 

foundry.toml : Foundry project configuration file, foundry.toml

 

lib: includes the required libraries.

 

script: files with Solidity Scripting

 

You may also like | Code Analysis Tools for Solidity Smart Contracts

 

The Counter.sol sample smart contract is provided and can be found inside the src folder.

 

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;


contract Counter {
   uint256 public number;


   function setNumber(uint256 newNumber) public {
       number = newNumber;
   }


   function increment() public {
       number++;
   }
}

 

Use the forge build to compile the smart contract: forge build

 

The following output will appear in your terminal if your contract compiles successfully:

 

rahul@rahul:~/foundry/hello_foundry$ forge build
[⠰] Compiling...
[⠘] Compiling 24 files with 0.8.23
[⠒] Solc 0.8.23 finished in 6.28sCompiler run successful!
[⠢] Solc 0.8.23 finished in 6.28s

 

The tests directory is created by Foundry and serves as the default location for all of the smart contract testing. The test file names have a.t.sol extension.

 

You can find a specifically named test file called Counter.t.sol if you open the test folder.
 

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;


import {Test, console2} from "forge-std/Test.sol";
import {Counter} from "../src/Counter.sol";


contract CounterTest is Test {
   Counter public counter;


   function setUp() public {
       counter = new Counter();
       counter.setNumber(0);
   }


   function test_Increment() public {
       counter.increment();
       assertEq(counter.number(), 1);
   }


   function testFuzz_SetNumber(uint256 x) public {
       counter.setNumber(x);
       assertEq(counter.number(), x);
   }
}

 

To test the Couter.sol smart contract utilising forge test, execute the following file: forge test

 

If all the test are passed then,

 

rahul@rahul:~/foundry/hello_foundry$ forge test
[⠔] Compiling...No files changed, compilation skipped
[⠒] Compiling...

Running 2 tests for test/Counter.t.sol:CounterTest
[PASS] testFuzz_SetNumber(uint256) (runs: 256, μ: 27320, ~: 28409)
[PASS] test_Increment() (gas: 28379)
Test result: ok. 2 passed; 0 failed; 0 skipped; finished in 64.81ms

 

Also, Explore | AI-Driven Smart Contracts: Merging Intelligence with Automation


 

Deploying the smart contract

 

Use the forge create command to deploy the smart contract to a network:


Deploy command : forge create <your_rpc_endpoint> as the --rpc-url. <wallet_private_key>—private-key counter.sol: Counter in src . By following this tutorial, you can obtain the RPC for the network from Infura: 

 

Link :  https://www.infura.io/blog/post/getting-started-with-infura-28e41844cc89
should the smart contract be successfully deployed, your terminal will display the following output:

 

rahul@rahul:~/foundry/hello_foundry$  forge create src/Counter.sol:Counter --rpc-url https://sepolia.infura.io/v3/<your infura key> -
-private-key <wallet private key> 
[⠔] Compiling...No files changed, compilation skipped
[⠒] Compiling...
Deployer: 0x2Bc5b75F445cdAa418d32C5FD61A11E53c540Ba2
Deployed to: 0xb88758D730bDd6b07958427321169626A479afBc
Transaction hash: 0x4a6ebeb2d942a3c60648a44d8078ef00cb440f73a22acf2a06ee63f95604ef2f

 

If you are looking to bring your business idea into reality using the potential of blokchain and smart contracts, connect with our skilled smart contract developers to get started. 

 

Category: Blockchain
How to Access Private Data in Smart Contracts

During smart contract development, a project sometimes requires connecting with other contracts in the network. However, private variables in Solidity are inaccessible to any other contract and can only be read by the contracts themselves. These data can, however, be accessed from outside the blockchain. Let us examine the process of obtaining private data from smart contracts.

 

Accessing Private Data in Smart Contracts

 

Storage Architecture

 

The Ethereum Virtual Machine, or EVM, uses slots on the blockchain to store smart contract data in a big array with a length of 2**256. Up to 32 bytes of data can be stored in each memory slot. The state variables of smart contracts are stored by the EVM in the sequence in which they were declared in blockchain slots. 

 

Also, Explore | Code Analysis Tools for Solidity Smart Contracts

 

Space efficiency is the main goal of smart contract storage. Variables are packed into one 32-byte slot if two or more can fit into it, starting from the right.

 

uint8    => 1 byte
uint16   => 2 bytes and so on
uint256  => 32 bytes
bool     => 1 byte
address  => 20 byte
bytes1   => 1 byte
bytes2   => 2 bytes 

 

Pre-requisites

 

  • First, Make sure that node js is installed in your system to check if Node.js is installed or not run “node -v” if it shows some version example-”v18.16.0”. It means that nodejs is installed otherwise you can install nodejs from (https://nodejs.org/en) based on your OS.
  • Hardhat must be installed. We are using Hardhat for testing and deploying our smart contract.
  • For the test case, we use the Chai library. 

 

Steps to Accessing Private Data

 

We can take the following actions to get private data from a Solidity smart contract. Here, we'll be extracting data using ethers.js.

 

  • To begin with, we must read the contract and comprehend the declaration sequence of the state variables. Assume for a moment that we wish to use slot 0.
  • The memory slots of the contract on the blockchain can be read using ethers.js. Make use of the function below:   await ethers.provider.getStorage(contract. target, slot);
  • This will return a result that is hex encoded, which we can easily decode using ether or a hex decoder of some like. parseInt(Number(slot0Bytes))

 

You may also like | Top 5 Smart Contract Development Companies

 

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.20;

contract MyContract {
     uint256 private privateData_0;
     uint256 private privateData_1;
     constructor(uint256 _privateData0,uint256 _privateData1){
        privateData_0 = _privateData0;
        privateData_1 = _privateData1;
     }   
   
}

 

Test script

 

const { ethers, upgrades } = require("hardhat");
const { BigNumber } = require('ethers')
const { expect } = require("chai");
describe('accessing private data', function(){
   let deployer
   let Contract
   let addr1
   let contract
    beforeEach(async function(){
      [deployer ,addr1,addr2] = await ethers.getSigners();  
      Contract = await ethers.getContractFactory('MyContract');
      contract = await Contract.deploy(101,102);
      const data = await contract.waitForDeployment();
  

  console.log(
    `deployed to ${Contract},${contract.target},${data}`
  );
  });
    it('contract', async function(){

      const  private_1 = 101;
      const private_2 = 102;
      const slot = 0;
      const slot1 = 1;
      const slot0Bytes = await ethers.provider.getStorage(contract.target, slot);
      const slot0Bytes1 = await ethers.provider.getStorage(contract.target, slot1);
      const slotData = parseInt(Number(slot0Bytes))
      const slotData_1 = parseInt(Number(slot0Bytes1))
      expect(slotData).to.be.equals(parseInt(Number(private_1)));
      expect(slotData_1).to.be.equals(parseInt(Number(private_2)));
  
    })

})

 

Run test script

 

  • npx hardhat test

 

The test case that runs will confirm that the only integer read from slot 0 is 101, and the only integer read from slot 1 is 102. which both are private data.

 

Also, Explore | Top 5 Smart Contract Development Companies

 

Since we are working with public blockchains, private data in a smart contract is not private in the traditional sense. Blockchains cannot truly hide information from the outside world. We must use certain encryption algorithms if we wish to store sensitive data on-chain. For more about smart contract development, connect with our smart contract developers

Category: Blockchain
A Detailed Guide to NFT Minting on Solana using Metaplex API

This article outlines the process of developing and minting NFTs (non-fungible tokens) on the Solana blockchain using Metaplex's SDK. It covers key steps such as setting up prerequisites, connecting to Solana, creating a wallet, declaring variables, defining NFT characteristics, and executing the minting process. It provides a comprehensive overview of the process for interested developers or businesses looking to engage in NFT creation with Solana development. 

 

What is Solana

 

Solana is a high-performance blockchain network designed for a wide range of use cases, including payments, gaming, NFTs, and banking. It stands out as a platform built for extensive use, with transparency, connectivity, and decentralization at its core. In addition to its impressive scalability, Solana boasts several other exceptional features, such as "Proof of History."

 

Solana uses a unique consensus method called Proof of History, which depends on time-stamping techniques. Every transaction in the Solana network is given a timestamp, which allows the network as a whole to quickly verify the transaction as valid in a matter of milliseconds.

 

Check It Out | Exploring Solana Blockchain Development for Enterprises

 

Setup for Mint NFT

 

Prerequisites 

 

  • First, Make sure that node js is installed in your system to check if nodejs is installed or not run “node -v” if it shows some version example-”v18.16.0”. It means that nodejs is installed otherwise you can install nodejs from (https://nodejs.org/en) based on your OS.

 

  • It's essential to include the Solana Web3 and SPL Token libraries. Furthermore, we'll be incorporating Metaplex's JS SDK and MPL Token Metadata libraries. To initiate this, please enter the following command in your terminal

 

Connect Solana  

 

npm install @solana/web3.js @metaplex-foundation/js

 

const { Connection, Keypair, PublicKey } = require("@solana/web3.js");
const { Metaplex, keypairIdentity, bundlrStorage, toMetaplexFile, toBigNumber } = require("@metaplex-foundation/js");

 

Create a Wallet

 

It's crucial to generate a Solana File System Wallet, with the resulting keypair documented in a keypair.json file. Additionally, ensure the wallet receives airdropped SOL. This can be accomplished either through the Solana CLI.

 

Variables Declarations

 

To execute the script, it's essential to define several variables:

 

  • Your source wallet, which is represented by a keypair derived from your secret key.
  • An instance of Metaplex.
  • A CONFIG file that serves as a storage container for information related to the NFT we are set to mint.

 

const fs = require('fs');
const secret = require('./keypair.json');
const WALLET = Keypair.fromSecretKey(new Uint8Array(secret));
const NODE_RPC = 'https://rpc.ankr.com/solana_devnet';
const SOLANA_CONNECTION = new Connection(NODE_RPC);
const METAPLEX = Metaplex.make(SOLANA_CONNECTION)
.use(keypairIdentity(WALLET))
.use(bundlrStorage());

 

Suggested Read | A Quick Guide to NFT Development on Solana Blockchain

 

NFT Characteristics

 

Let's instantiate a CONFIG object encapsulating specific metadata for our NFT. Establish a new constant, CONFIG, and include the following attributes:

 

  const CONFIG = {
        uploadPath: 'images/',
        imgFileName: 'hello.jpeg',
        imgType: 'image/jpeg',
        imgName: 'Rahul Maurya',
        description: 'it is a Tree !',
        attributes: [
            {trait_type: 'hair', value: 'Black'},
            {trait_type: 'company', value: 'oodles'},
            {trait_type: 'color', value: 'white'}
        ],
        sellerFeeBasisPoints: 100,
        symbol: 'OO',
        creators: [
            {address: WALLET.publicKey, share: 100}
        ]
    };

    

 

Upload Image

 

It's crucial to upload the image designated for our NFT to a decentralized storage platform. This is imperative as we'll be passing the URI of the NFT image into the metadata. If you already have an image hosted with a URI, define it in your CONFIG file and proceed to step 2. Otherwise, let's establish a new asynchronous function named uploadImage before our main function. This function should take a filePath and fileName as parameters and return a promise resolving to a string, indicating the URI pointing to our uploaded image.

 

   async function uploadImage(filePath,fileName){

        console.log(`Step 1 - Uploading Image`);
        const imgBuffer = fs.readFileSync(filePath+fileName);
        const imgMetaplexFile = toMetaplexFile(imgBuffer,fileName);
        const imgUri = await METAPLEX.storage().upload(imgMetaplexFile);
        console.log(`   Image URI:`,imgUri);
        return imgUri;
    }

 

Upload Metadata

 

The metadata plays a crucial role in defining the uniqueness of your NFT, encompassing the image, defining traits, assigning it to a collection, and more. Metaplex simplifies the metadata uploading process through a single call to nfts().uploadMetadata(). To begin, let's craft a new function named uploadMetadata. This function should accept five parameters: imgUri, imgType, nftName, description, and attributes.

 

async function uploadMetadata(imgUri, imgType ,nftName, description, attributes){
    const { uri } = await METAPLEX
    .nfts()
    .uploadMetadata({
        name: nftName,
        description: description,
        image: imgUri,
        attributes: attributes,
        properties: {
            files: [
                {
                    type: imgType,
                    uri: imgUri,
                },
            ]
        }
    });
    console.log('   Metadata URI:',uri);
    return uri;  

 }
   

 

Mint NFTs

 

Minting our NFT becomes a straightforward process with a single method call: nfts().create(). However, in this final step, distinct from the metadata upload, we must provide some metadata that will be directly stored on the Solana chain.

 

 async function mintNft(metadataUri, name, sellerFee, symbol, creators) {

    const { nft } = await METAPLEX
    .nfts()
    .create({
        uri: metadataUri,
        name: name,
         sellerFeeBasisPoints: sellerFee,
         symbol: symbol,
        creators: creators,
        isMutable: false,
    },
    { commitment: "finalized" });
    console.log(`Minted NFT: https://explorer.solana.com/address/${nft.address}?cluster=devnet`);




 }
    async function main() {
    
         // Step 1 - upload Images
        const imgUri = await uploadImage(CONFIG.uploadPath,CONFIG.imgFileName);
        //Step 2 - Upload Metadata
        const metadataUri = await uploadMetadata(imgUri,CONFIG.imgType,CONFIG.imgName, CONFIG.description, CONFIG.attributes); 
        //Step 3 - Mint NFT
        mintNft(metadataUri,CONFIG.imgName,CONFIG.sellerFeeBasisPoints,CONFIG.symbol,CONFIG.creators);
    }
    
    main();

 

Now, you Feel free to explore your minted NFT by clicking on the following link: 

 

Minted NFT: https://explorer.solana.com/address/${nft.address}?cluster=devnet 

 

Also, Discover | Advanced NFT Marketplace Development on Solana Blockchain

 

Overview

 

You can create your own NFTs on the Solana blockchain by following these instructions and incorporating the included code samples. To ensure a smooth NFT creation process, make sure that each step is well-tested and validated.

 

References

 

 

Interested in developing NFTs on Solana, then connect with our NFT developers to get started. 

Category: Blockchain
Banner

Don't just hire talent,
But build your dream team

Our experience in providing the best talents in accordance with diverse industry demands sets us apart from the rest. Hire a dedicated team of experts to build & scale your project, achieve delivery excellence, and maximize your returns. Rest assured, we will help you start and launch your project, your way – with full trust and transparency!