diff --git a/components/CertificateMinter.js b/components/CertificateMinter.js index 5db8afa..8bf1285 100644 --- a/components/CertificateMinter.js +++ b/components/CertificateMinter.js @@ -4,7 +4,7 @@ import { ethers } from 'ethers'; import { abi, NFT_CONTRACT_ADDRESS } from "../constants/index"; const CertificateMinter = () => { - const [recipient, setRecipient] = useState(''); + const [certificateId, setCertificateId] = useState(''); const [userName, setUserName] = useState(''); const [surName, setSurName] = useState(''); const [email, setEmail] = useState(''); @@ -18,14 +18,19 @@ const CertificateMinter = () => { const signer = provider.getSigner(); const certificateContract = new ethers.Contract(NFT_CONTRACT_ADDRESS, abi, signer); - await certificateContract.mintCertificate(recipient, userName, surName, email, companyName); + await certificateContract.mintCertificate(certificateId, userName, surName, email, companyName); alert('Certificate minted successfully!'); } else { alert('Please connect your wallet'); } } catch (error) { console.error('Error minting certificate:', error); - alert('Error minting certificate. Please check the console for details.'); + + if (error.code === 4001) { + alert('Certificate already issued'); + } else { + alert('Error minting certificate. Please check the console for details.'); + } } }; @@ -33,28 +38,28 @@ const CertificateMinter = () => {

Certificate Minter






diff --git a/constants/index.js b/constants/index.js index a426048..d72f84a 100644 --- a/constants/index.js +++ b/constants/index.js @@ -1,22 +1,4 @@ export const abi = [ - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "approve", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, { "inputs": [], "stateMutability": "nonpayable", @@ -125,39 +107,6 @@ export const abi = [ "name": "ERC721NonexistentToken", "type": "error" }, - { - "inputs": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "string", - "name": "userName", - "type": "string" - }, - { - "internalType": "string", - "name": "surName", - "type": "string" - }, - { - "internalType": "string", - "name": "email", - "type": "string" - }, - { - "internalType": "string", - "name": "companyName", - "type": "string" - } - ], - "name": "mintCertificate", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, { "inputs": [ { @@ -249,82 +198,6 @@ export const abi = [ "name": "OwnershipTransferred", "type": "event" }, - { - "inputs": [], - "name": "renounceOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "safeTransferFrom", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "safeTransferFrom", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "operator", - "type": "address" - }, - { - "internalType": "bool", - "name": "approved", - "type": "bool" - } - ], - "name": "setApprovalForAll", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, { "anonymous": false, "inputs": [ @@ -352,11 +225,6 @@ export const abi = [ }, { "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, { "internalType": "address", "name": "to", @@ -368,20 +236,7 @@ export const abi = [ "type": "uint256" } ], - "name": "transferFrom", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "transferOwnership", + "name": "approve", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -482,6 +337,39 @@ export const abi = [ "stateMutability": "view", "type": "function" }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "certificateId", + "type": "uint256" + }, + { + "internalType": "string", + "name": "userName", + "type": "string" + }, + { + "internalType": "string", + "name": "surName", + "type": "string" + }, + { + "internalType": "string", + "name": "email", + "type": "string" + }, + { + "internalType": "string", + "name": "companyName", + "type": "string" + } + ], + "name": "mintCertificate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [], "name": "name", @@ -540,6 +428,82 @@ export const abi = [ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "setApprovalForAll", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [ { @@ -590,8 +554,44 @@ export const abi = [ ], "stateMutability": "view", "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" } ]; export const NFT_CONTRACT_ADDRESS = - "0x402F88e39B21390Ff962fb4bF1EE05f335E7dA3c"; + "0xe7Bf32841a34C053aBcE967E0bE787F4164536d9"; diff --git a/nftCert.sol b/nftCert.sol index 72c8090..283d88b 100644 --- a/nftCert.sol +++ b/nftCert.sol @@ -10,6 +10,9 @@ contract Certificate is ERC721, Ownable { // Mapping to store additional information for each certificate mapping(uint256 => CertificateInfo) private certificateInfoMapping; + // Mapping to check if a certificate with a given name and wallet address has been issued + mapping(string => mapping(address => bool)) private issuedCertificates; + struct CertificateInfo { string userName; string surName; @@ -20,18 +23,25 @@ contract Certificate is ERC721, Ownable { constructor() ERC721("Certificate", "CERT") Ownable(msg.sender) {} function mintCertificate( - address recipient, + uint256 certificateId, string memory userName, string memory surName, string memory email, string memory companyName - ) external onlyOwner { - uint256 tokenId = nextCertificateId; - _safeMint(recipient, tokenId); - nextCertificateId++; + ) external { + // Check if the certificate with the given ID has already been issued + require(!issuedCertificates[userName][msg.sender], "Certificate already issued"); + + _safeMint(msg.sender, certificateId); // Store additional information using a mapping - _storeCertificateInfo(tokenId, userName, surName, email, companyName); + _storeCertificateInfo(certificateId, userName, surName, email, companyName); + + // Mark the certificate as issued + issuedCertificates[userName][msg.sender] = true; + + // Update the nextCertificateId only if the mint is successful + nextCertificateId = certificateId + 1; } function _storeCertificateInfo(