0

Solidity code


pragma solidity ^0.8.7;

import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";
import "base64-sol/base64.sol";

error tokenURI__InvalidToken(uint256 tokenId);

contract DynamicNft is ERC721 {
    uint256 private s_tokenCounter;
    string private i_lowImageUri;
    string private i_highImageUri;
    string private constant base64EncodedPrefix = "data:image/svg+xml;base64,";
    AggregatorV3Interface internal immutable i_priceFeed;
    mapping(uint256 => int256) tokeninToHighValue;

    event CreatedNft(uint256 indexed tokenId, int256 highValue);

    constructor(
        address priceFeed,
        string memory lowSvg,
        string memory highSvg
    ) ERC721("DYNAMICNFT Nft", "DSN") {
        i_priceFeed = AggregatorV3Interface(priceFeed);
        s_tokenCounter = 0;
        i_lowImageUri = svgToImageUri(lowSvg);
        i_highImageUri = svgToImageUri(highSvg);
    }

    function svgToImageUri(string memory svg) public pure returns (string memory) {
        string memory svgBase64Encoded = Base64.encode(bytes(string(abi.encodePacked(svg))));
        return string(abi.encodePacked(base64EncodedPrefix, svgBase64Encoded));
    }

    function mintNft(int256 highValue) public {
        uint256 currentIndex = s_tokenCounter;
        s_tokenCounter++;
        tokeninToHighValue[currentIndex] = highValue;
        _safeMint(msg.sender, currentIndex);
        emit CreatedNft(currentIndex, highValue);
    }

    function _baseURI() internal pure override returns (string memory) {
        return "data:application/json;base64,";
    }

    function tokenURI(uint256 tokenId) public view override returns (string memory) {
        if (!_exists(tokenId)) {
            revert tokenURI__InvalidToken(tokenId);
        }
        string memory ImgUri = i_lowImageUri;
        (, int256 price, , , ) = i_priceFeed.latestRoundData();
        if (price >= tokeninToHighValue[tokenId]) {
            ImgUri = i_highImageUri;
        }
        return (
            string(
                abi.encodePacked(
                    _baseURI(),
                    Base64.encode(
                        bytes(
                            abi.encodePacked(
                                '{"name":"',
                                name(),
                                '", "description":"nft changes with price of ETH",',
                                '"attributes":[{"trait_type":"cuteness","value":100}],"image":"',
                                ImgUri,
                                '"}'
                            )
                        )
                    )
                )
            )
        );
    }

    function getPriceFeed() public view returns (AggregatorV3Interface) {
        return i_priceFeed;
    }

    function getLowSvg() public view returns (string memory) {
        return i_lowImageUri;
    }

    function getHighSvg() public view returns (string memory) {
        return i_highImageUri;
    }

hardhat deploy script

const { networkConfig, developmentChains } = require("../helper-hardhat-config");
const { verify } = require("../utils/verify");
const fs = require("fs");

module.exports = async function ({ getNamedAccounts, deployments }) {
    const { deploy, log } = deployments;
    const { deployer } = await getNamedAccounts();

    let ethUsdPriceFeedAddress;
    const ethUsdAggregator = await deployments.get("MockV3Aggregator");
    const chainId = network.config.chainId;
    if (developmentChains.includes(network.name)) {
        ethUsdPriceFeedAddress = ethUsdAggregator.address;
    } else {
        ethUsdPriceFeedAddress = networkConfig[chainId].ethUsdPrice;
    }
    const lowSvg = fs.readFileSync("./images/dynamicNft/sad.svg", { encoding: "utf8" });
    const highSvg = fs.readFileSync("./images/dynamicNft/smiley.svg", { encoding: "utf8" });

    const args = [ethUsdPriceFeedAddress, lowSvg, highSvg];
    const dynamicSvgNft = await deploy("DynamicNft", {
        from: deployer,
        args: args,
        log: true,
        waitConfirmations: network.config.blockConfirmations || 1,
    });

    if (!developmentChains.includes(network.name) && process.env.POLYGON_API_KEY) {
        log("Verifying..........");
        await verify(dynamicSvgNft.address, args);
    }
};

module.exports.tags = ["all", "dynamicnft", "main"];

Test file

const { network, deployments, ethers } = require("hardhat");
const { developmentChains } = require("../../helper-hardhat-config");

const highSvgImageUri ="HIGH_URL"
const lowSvgImageUri ="LOW_URL"
   
!developmentChains.includes(network.name)
    ? describe.skip
    : describe("Dynamic NFT svg tests", function () {
          let dynamicNft, MockV3Aggregator, deployer;
          beforeEach(async () => {
              accounts = await ethers.getSigners();
              MockV3Aggregator = ethers.deployContract("MockV3Aggregator");
              dynamicNft = ethers.deployContract("DynamicNft");
              deployer = accounts[0];
          });
          describe("Constructor Works", async function () {
              it("Sets string values correctly", async () => {
            
                  let lowSvgImage = await dynamicNft.getLowSvg();
                  let highSvgImage = await dynamicNft.getHighSvg();
            
                  assert.equal(lowSvgImage, lowSvgImageUri);
                  assert.equal(highSvgImage, highSvgImageUri);
              });
          });
      });
1
  • What do you mean by "Not able to test view functions in hardhat"? They fail, they do nothing, there's an error, etc. Can you clarify what your issue?
    – Ismael
    Commented Aug 3, 2023 at 1:32

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Browse other questions tagged or ask your own question.