@@ -14,7 +14,12 @@ import {IVotsElectionNft} from "./interfaces/IVotsElectionNft.sol";
1414 * @notice NFT contract that mints tokens to election creators as proof of election creation
1515 * @dev This contract creates unique NFTs for each election created through the VotsEngine
1616 */
17- contract VotsElectionNft is IVotsElectionNft , ERC721 , ERC721URIStorage , Ownable {
17+ contract VotsElectionNft is
18+ IVotsElectionNft ,
19+ ERC721 ,
20+ ERC721URIStorage ,
21+ Ownable
22+ {
1823 using Strings for uint256 ;
1924
2025 // ====================================================================
@@ -36,7 +41,8 @@ contract VotsElectionNft is IVotsElectionNft, ERC721, ERC721URIStorage, Ownable
3641 mapping (uint256 => uint256 ) public electionTokenToNftToken;
3742
3843 // Mapping from NFT token ID to election data
39- mapping (uint256 => IVotsElectionNft.ElectionNftData) public nftTokenToElectionData;
44+ mapping (uint256 => IVotsElectionNft.ElectionNftData)
45+ public nftTokenToElectionData;
4046
4147 // ====================================================================
4248 // Constructor
@@ -80,15 +86,16 @@ contract VotsElectionNft is IVotsElectionNft, ERC721, ERC721URIStorage, Ownable
8086 nftTokenId = _tokenIdCounter;
8187
8288 // Store election data
83- IVotsElectionNft.ElectionNftData memory nftData = IVotsElectionNft.ElectionNftData ({
84- electionTokenId: electionTokenId,
85- electionName: electionName,
86- creator: creator,
87- creationTimestamp: block .timestamp ,
88- electionDescription: electionDescription,
89- startTime: startTime,
90- endTime: endTime
91- });
89+ IVotsElectionNft.ElectionNftData memory nftData = IVotsElectionNft
90+ .ElectionNftData ({
91+ electionTokenId: electionTokenId,
92+ electionName: electionName,
93+ creator: creator,
94+ creationTimestamp: block .timestamp ,
95+ electionDescription: electionDescription,
96+ startTime: startTime,
97+ endTime: endTime
98+ });
9299
93100 nftTokenToElectionData[nftTokenId] = nftData;
94101 electionTokenToNftToken[electionTokenId] = nftTokenId;
@@ -97,10 +104,18 @@ contract VotsElectionNft is IVotsElectionNft, ERC721, ERC721URIStorage, Ownable
97104 _safeMint (creator, nftTokenId);
98105
99106 // Set token URI
100- string memory generatedTokenURI = _generateTokenURI (nftTokenId, nftData);
107+ string memory generatedTokenURI = _generateTokenURI (
108+ nftTokenId,
109+ nftData
110+ );
101111 _setTokenURI (nftTokenId, generatedTokenURI);
102112
103- emit IVotsElectionNft.ElectionNftMinted (nftTokenId, electionTokenId, creator, electionName);
113+ emit IVotsElectionNft.ElectionNftMinted (
114+ nftTokenId,
115+ electionTokenId,
116+ creator,
117+ electionName
118+ );
104119
105120 return nftTokenId;
106121 }
@@ -111,11 +126,10 @@ contract VotsElectionNft is IVotsElectionNft, ERC721, ERC721URIStorage, Ownable
111126 * @param nftData The election data for this NFT
112127 * @return The complete token URI with embedded metadata
113128 */
114- function _generateTokenURI (uint256 nftTokenId , IVotsElectionNft.ElectionNftData memory nftData )
115- internal
116- pure
117- returns (string memory )
118- {
129+ function _generateTokenURI (
130+ uint256 nftTokenId ,
131+ IVotsElectionNft.ElectionNftData memory nftData
132+ ) internal pure returns (string memory ) {
119133 // Create SVG image
120134 string memory svg = _generateSVG (nftData);
121135
@@ -163,46 +177,52 @@ contract VotsElectionNft is IVotsElectionNft, ERC721, ERC721URIStorage, Ownable
163177 * @param nftData The election data
164178 * @return SVG string
165179 */
166- function _generateSVG (IVotsElectionNft.ElectionNftData memory nftData ) internal pure returns (string memory ) {
167- return string (
168- abi.encodePacked (
169- '<svg width="400" height="400" xmlns="http://www.w3.org/2000/svg"> ' ,
170- "<defs> " ,
171- '<linearGradient id="grad1" x1="0%" y1="0%" x2="100%" y2="100%"> ' ,
172- '<stop offset="0%" style="stop-color:#667eea;stop-opacity:1" /> ' ,
173- '<stop offset="100%" style="stop-color:#764ba2;stop-opacity:1" /> ' ,
174- "</linearGradient> " ,
175- "</defs> " ,
176- '<rect width="400" height="400" fill="url(#grad1)" rx="20"/> ' ,
177- '<rect x="20" y="20" width="360" height="360" fill="none" stroke="white" stroke-width="2" rx="15"/> ' ,
178- '<text x="200" y="60" font-family="Arial, sans-serif" font-size="24" font-weight="bold" text-anchor="middle" fill="white">ELECTION CERTIFICATE</text> ' ,
179- '<text x="200" y="100" font-family="Arial, sans-serif" font-size="14" text-anchor="middle" fill="white">VotsEngine Creation Proof</text> ' ,
180- '<text x="50" y="140" font-family="Arial, sans-serif" font-size="14" fill="white">Election:</text> ' ,
181- '<text x="50" y="165" font-family="Arial, sans-serif" font-size="16" font-weight="bold" fill="white"> ' ,
182- _truncateString (nftData.electionName, 25 ),
183- "</text> " ,
184- '<text x="50" y="200" font-family="Arial, sans-serif" font-size="14" fill="white">Type:</text> ' ,
185- '<text x="50" y="225" font-family="Arial, sans-serif" font-size="16" font-weight="bold" fill="white"> ' ,
186- nftData.electionDescription,
187- "</text> " ,
188- '<text x="50" y="260" font-family="Arial, sans-serif" font-size="14" fill="white">Token ID:</text> ' ,
189- '<text x="50" y="285" font-family="Arial, sans-serif" font-size="16" font-weight="bold" fill="white"># ' ,
190- nftData.electionTokenId.toString (),
191- "</text> " ,
192- '<text x="50" y="320" font-family="Arial, sans-serif" font-size="14" fill="white">Creator:</text> ' ,
193- '<text x="50" y="345" font-family="Arial, sans-serif" font-size="16" font-weight="bold" fill="white"> ' ,
194- _truncateAddress (nftData.creator),
195- "</text> " ,
196- '<text x="200" y="375" font-family="Arial, sans-serif" font-size="12" text-anchor="middle" fill="white">powered by YENIYAN-Group</text> ' ,
197- "</svg> "
198- )
199- );
180+ function _generateSVG (
181+ IVotsElectionNft.ElectionNftData memory nftData
182+ ) internal pure returns (string memory ) {
183+ return
184+ string (
185+ abi.encodePacked (
186+ '<svg width="400" height="400" xmlns="http://www.w3.org/2000/svg"> ' ,
187+ "<defs> " ,
188+ '<linearGradient id="grad1" x1="0%" y1="0%" x2="100%" y2="100%"> ' ,
189+ '<stop offset="0%" style="stop-color:#667eea;stop-opacity:1" /> ' ,
190+ '<stop offset="100%" style="stop-color:#764ba2;stop-opacity:1" /> ' ,
191+ "</linearGradient> " ,
192+ "</defs> " ,
193+ '<rect width="400" height="400" fill="url(#grad1)" rx="20"/> ' ,
194+ '<rect x="20" y="20" width="360" height="360" fill="none" stroke="white" stroke-width="2" rx="15"/> ' ,
195+ '<text x="200" y="60" font-family="Arial, sans-serif" font-size="24" font-weight="bold" text-anchor="middle" fill="white">ELECTION CERTIFICATE</text> ' ,
196+ '<text x="200" y="100" font-family="Arial, sans-serif" font-size="14" text-anchor="middle" fill="white">VotsEngine Creation Proof</text> ' ,
197+ '<text x="50" y="140" font-family="Arial, sans-serif" font-size="14" fill="white">Election:</text> ' ,
198+ '<text x="50" y="165" font-family="Arial, sans-serif" font-size="16" font-weight="bold" fill="white"> ' ,
199+ _truncateString (nftData.electionName, 25 ),
200+ "</text> " ,
201+ '<text x="50" y="200" font-family="Arial, sans-serif" font-size="14" fill="white">Description:</text> ' ,
202+ '<text x="50" y="225" font-family="Arial, sans-serif" font-size="16" font-weight="bold" fill="white"> ' ,
203+ _truncateString (nftData.electionDescription, 30 ),
204+ "</text> " ,
205+ '<text x="50" y="260" font-family="Arial, sans-serif" font-size="14" fill="white">Token ID:</text> ' ,
206+ '<text x="50" y="285" font-family="Arial, sans-serif" font-size="16" font-weight="bold" fill="white"># ' ,
207+ nftData.electionTokenId.toString (),
208+ "</text> " ,
209+ '<text x="50" y="320" font-family="Arial, sans-serif" font-size="14" fill="white">Creator:</text> ' ,
210+ '<text x="50" y="345" font-family="Arial, sans-serif" font-size="16" font-weight="bold" fill="white"> ' ,
211+ _truncateAddress (nftData.creator),
212+ "</text> " ,
213+ '<text x="200" y="375" font-family="Arial, sans-serif" font-size="12" text-anchor="middle" fill="white">powered by YENIYAN-Group</text> ' ,
214+ "</svg> "
215+ )
216+ );
200217 }
201218
202219 /**
203220 * @dev Truncates a string to specified length with ellipsis
204221 */
205- function _truncateString (string memory str , uint256 maxLength ) internal pure returns (string memory ) {
222+ function _truncateString (
223+ string memory str ,
224+ uint256 maxLength
225+ ) internal pure returns (string memory ) {
206226 bytes memory strBytes = bytes (str);
207227 if (strBytes.length <= maxLength) {
208228 return str;
@@ -219,7 +239,9 @@ contract VotsElectionNft is IVotsElectionNft, ERC721, ERC721URIStorage, Ownable
219239 /**
220240 * @dev Truncates an address for display
221241 */
222- function _truncateAddress (address addr ) internal pure returns (string memory ) {
242+ function _truncateAddress (
243+ address addr
244+ ) internal pure returns (string memory ) {
223245 string memory addrStr = Strings.toHexString (uint160 (addr), 20 );
224246 bytes memory addrBytes = bytes (addrStr);
225247
@@ -251,7 +273,9 @@ contract VotsElectionNft is IVotsElectionNft, ERC721, ERC721URIStorage, Ownable
251273 * @dev Returns election data for a given NFT token ID
252274 * @param nftTokenId The NFT token ID
253275 */
254- function getElectionData (uint256 nftTokenId ) external view returns (IVotsElectionNft.ElectionNftData memory ) {
276+ function getElectionData (
277+ uint256 nftTokenId
278+ ) external view returns (IVotsElectionNft.ElectionNftData memory ) {
255279 if (! _exists (nftTokenId)) {
256280 revert VotsElectionNft__TokenDoesNotExist ();
257281 }
@@ -262,15 +286,19 @@ contract VotsElectionNft is IVotsElectionNft, ERC721, ERC721URIStorage, Ownable
262286 * @dev Returns NFT token ID for a given election token ID
263287 * @param electionTokenId The election token ID
264288 */
265- function getNftTokenByElectionId (uint256 electionTokenId ) external view returns (uint256 ) {
289+ function getNftTokenByElectionId (
290+ uint256 electionTokenId
291+ ) external view returns (uint256 ) {
266292 return electionTokenToNftToken[electionTokenId];
267293 }
268294
269295 /**
270296 * @dev Returns all NFTs owned by an address
271297 * @param owner The owner address
272298 */
273- function getOwnedTokens (address owner ) external view returns (uint256 [] memory ) {
299+ function getOwnedTokens (
300+ address owner
301+ ) external view returns (uint256 [] memory ) {
274302 uint256 balance = balanceOf (owner);
275303 uint256 [] memory tokens = new uint256 [](balance);
276304 uint256 currentIndex = 0 ;
@@ -291,7 +319,9 @@ contract VotsElectionNft is IVotsElectionNft, ERC721, ERC721URIStorage, Ownable
291319 * @dev Checks if an NFT exists for a given election
292320 * @param electionTokenId The election token ID
293321 */
294- function electionNftExists (uint256 electionTokenId ) external view returns (bool ) {
322+ function electionNftExists (
323+ uint256 electionTokenId
324+ ) external view returns (bool ) {
295325 return electionTokenToNftToken[electionTokenId] != 0 ;
296326 }
297327
@@ -303,11 +333,15 @@ contract VotsElectionNft is IVotsElectionNft, ERC721, ERC721URIStorage, Ownable
303333 // Override Functions
304334 // ====================================================================
305335
306- function tokenURI (uint256 tokenId ) public view override (ERC721 , ERC721URIStorage ) returns (string memory ) {
336+ function tokenURI (
337+ uint256 tokenId
338+ ) public view override (ERC721 , ERC721URIStorage ) returns (string memory ) {
307339 return super .tokenURI (tokenId);
308340 }
309341
310- function supportsInterface (bytes4 interfaceId ) public view override (ERC721 , ERC721URIStorage ) returns (bool ) {
342+ function supportsInterface (
343+ bytes4 interfaceId
344+ ) public view override (ERC721 , ERC721URIStorage ) returns (bool ) {
311345 return super .supportsInterface (interfaceId);
312346 }
313347}
0 commit comments