// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.1; contract DynamicMetadata { // Mapping of token ID to another mapping that maps attribute names to their values. mapping(uint256 => mapping(string => string)) private tokenAttributes; // Mapping of token ID to a list of its attribute names. mapping(uint256 => string[]) private attributeNames; // Struct to represent an attribute with its name and value. struct Attribute { string name; string value; } // Event to notify that metadata for a specific token ID needs to be refreshed. event RefreshRequired( uint256 indexed ID, string attribute, string newValue ); // Fetches the list of attribute names for a specific token ID. function getAttributeNames( uint256 tokenId ) public view returns (string[] memory) { return attributeNames[tokenId]; } // Fetches the value of a specific attribute for a specific token ID. function getAttribute( uint256 tokenId, string memory attribute ) public view returns (string memory) { return tokenAttributes[tokenId][attribute]; } // Fetches all attributes (name-value pairs) for a specific token ID. function getAttributes( uint256 tokenId ) public view returns (Attribute[] memory) { string[] memory names = attributeNames[tokenId]; Attribute[] memory attributes = new Attribute[](names.length); for (uint i = 0; i < names.length; i++) { attributes[i] = Attribute( names[i], tokenAttributes[tokenId][names[i]] ); } return attributes; } // Internal function to trigger a RefreshRequired event for a specific token ID. function _emitRefresh( uint256 ID, string memory attribute, string memory newValue ) internal { emit RefreshRequired(ID, attribute, newValue); } // Internal function to update or add a new attribute for a specific token ID. function _updateMetadata( uint256 ID, string memory attribute, string memory newValue ) internal { if (bytes(tokenAttributes[ID][attribute]).length == 0) { // If this attribute was not previously set for this token, add the attribute name to the list. attributeNames[ID].push(attribute); } _updateAttribute(ID, attribute, newValue); } // Private helper function to handle attribute-specific logic. function _updateAttribute( uint256 ID, string memory attribute, string memory newValue ) private { tokenAttributes[ID][attribute] = newValue; _emitRefresh(ID, attribute, newValue); } }