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

import “@openzeppelin/contracts/token/ERC721/ERC721.sol”;
import “@openzeppelin/contracts/access/Ownable.sol”;
import “@openzeppelin/contracts/utils/math/SafeMath.sol”;

contract FarmingCropNFT is ERC721, Ownable {
using SafeMath for uint256;

// Define events
event CropIssued(uint256 cropID, string cropName, uint256 amount, uint256 value, address farmer);
event CropTransferred(address from, address to, uint256 cropID, uint256 value);

// Define struct for crop
struct Crop {
string cropName;
uint256 amount;
uint256 value;
address farmer;
bool exists;
string ipfsHash; // added ipfsHash for off-chain data
}

// Define mapping of crop IDs to crops
mapping(uint256 => Crop) public crops;

// Define counter for crop IDs
uint256 public cropIDCounter;

// Define constructor to initialize contract and ERC721 token
constructor() ERC721(“Farming Crop NFT”, “FARMCRP”) {}

// Define function for farmer to issue NFT of crops to primary buyer
function issueCropNFT (
string memory _cropName,
uint256 _amount,
uint256 _value,
string memory _ipfsHash
) public payable returns (uint256) {
// Increment crop ID counter
cropIDCounter++;

// Create new crop struct
Crop memory newCrop = Crop({
cropName: _cropName,
amount: _amount,
value: _value,
farmer: msg.sender,
exists: true,
ipfsHash: _ipfsHash // store the ipfsHash for off-chain data
});

// Add new crop to mapping
crops[cropIDCounter] = newCrop;

// Mint NFT to farmer
_mint(msg.sender, cropIDCounter);

// Emit event for new crop issuance
emit CropIssued(cropIDCounter, _cropName, _amount, _value, msg.sender);

// Return crop ID
return cropIDCounter;
}

// Override the transferFrom function with custom logic for primary and secondary buyers.
function transferFrom(address from, address to, uint256 tokenId) public override {
// Ensure crop exists
require(crops[tokenId].exists, “Crop does not exist”);

// If the owner is farmer, primary buyer logic
if (ownerOf(tokenId) == crops[tokenId].farmer) {
// Primary buyer logic
// Here you can add conditions for primary buyer purchase
super.transferFrom(from, to, tokenId);
emit CropTransferred(from, to, tokenId, crops[tokenId].value);
} else {
// Secondary buyer logic
// Here you can add conditions for secondary buyer purchase on the marketplace
super.transferFrom(from, to, tokenId);
emit CropTransferred(from, to, tokenId, crops[tokenId].value);
}
}

// Define function for farmer to destroy NFT of crops when they stop farming
function destroyCropNFT(uint256 _cropID) public onlyOwner {
// Ensure crop exists and is owned by farmer
require(crops[_cropID].exists, “Crop does not exist”);
require(ownerOf(_cropID) == crops[_cropID].farmer, “Crop is not owned by farmer”);

// Burn NFT
_burn(_cropID);

// Emit event for crop destruction
emit CropTransferred(crops[_cropID].farmer, address(0), _cropID, crops[_cropID].value);

// Delete crop from mapping
delete crops[_cropID];
}

// Add a function to retrieve the IPFS hash
function getCropIPFSHash(uint256 _cropID) public view returns (string memory) {
require(crops[_cropID].exists, “Crop does not exist”);

return crops[_cropID].ipfsHash;
}
}

there is no mint price in the above code kindly add it and give me whole code