pragma solidity ^0.8.4;





contract ARClaimToken is ERC721, Ownable {
  using Counters for Counters.Counter;
  Counters.Counter private _tokenIdCounter;

  using Strings for uint256;

  mapping(uint256 => ARLibrary.Claim) public claims;
  mapping(uint256 => ARLibrary.Beneficiary[]) public beneficiaries;
  mapping(uint256 => string) private _tokenURIs;
  mapping(string => bool) public materials;

  event ClaimCreated(uint256 tokenId, address claimCreator, string tokenURI, string barcodeId, string material);

  constructor() ERC721("ARClaimTokenV2", "ARCT") {}

  function _baseURI() internal pure override returns (string memory) {
    return "https://ipfs.io/ipfs/";
  }

  function _setTokenURI(uint256 tokenId, string memory _tokenURI) internal virtual {
    require(_exists(tokenId), "ERC721Metadata: URI set of nonexistent token");
    _tokenURIs[tokenId] = _tokenURI;
  }

  function mintClaim(
    string memory _barcodeId,
    string memory _material,
    ARLibrary.Beneficiary[] memory _beneficiaries,
    string memory _tokenUri
  ) public {
    require(materials[_material] == true, "Material does not exist");

    uint256 tokenId = _tokenIdCounter.current();
    _tokenIdCounter.increment();

    ARLibrary.Claim storage cm = claims[tokenId];
    cm.creator = msg.sender;
    cm.barcodeId = _barcodeId;

    uint256 totalPercent = 0;
    for (uint256 i = 0; i < _beneficiaries.length; i++) {
      cm.beneficiaries.push(_beneficiaries[i].beneficiary);
      cm.percentages.push(_beneficiaries[i].percent);
      totalPercent += _beneficiaries[i].percent;
    }
    require(totalPercent <= 10_000, "Sum of beneficiary percentages exceeds 100%");

    _safeMint(msg.sender, tokenId);
    _setTokenURI(tokenId, _tokenUri);

    emit ClaimCreated(tokenId, msg.sender, _tokenUri, _barcodeId, _material);
  }

  function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
    require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token");

    string memory _tokenURI = _tokenURIs[tokenId];
    string memory base = _baseURI();

    if (bytes(base).length == 0) {
      return _tokenURI;
    }
    if (bytes(_tokenURI).length > 0) {
      return string(abi.encodePacked(base, _tokenURI));
    }
    return string(abi.encodePacked(base, tokenId.toString()));
  }

  function addMaterial(string memory _material) public onlyOwner {
    materials[_material] = true;
  }

  function removeMaterial(string memory _material) public onlyOwner {
    materials[_material] = false;
  }

  function getMaterial(string memory _material) public view returns (bool) {
    return materials[_material];
  }

  function getBeneficiaries(uint256 _tokenId) public view returns (ARLibrary.Beneficiary[] memory) {
    return beneficiaries[_tokenId];
  }

  function getClaim(uint256 _tokenId) public view returns (ARLibrary.Claim memory) {
    return claims[_tokenId];
  }
}
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"address","name":"claimCreator","type":"address"},{"indexed":false,"internalType":"string","name":"tokenURI","type":"string"},{"indexed":false,"internalType":"string","name":"barcodeId","type":"string"},{"indexed":false,"internalType":"string","name":"material","type":"string"}],"name":"ClaimCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"string","name":"_material","type":"string"}],"name":"addMaterial","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"beneficiaries","outputs":[{"internalType":"address","name":"beneficiary","type":"address"},{"internalType":"uint256","name":"percent","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"claims","outputs":[{"internalType":"string","name":"barcodeId","type":"string"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"address","name":"creator","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"getBeneficiaries","outputs":[{"components":[{"internalType":"address","name":"beneficiary","type":"address"},{"internalType":"uint256","name":"percent","type":"uint256"}],"internalType":"struct ARLibrary.Beneficiary[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"getClaim","outputs":[{"components":[{"internalType":"string","name":"barcodeId","type":"string"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"address","name":"creator","type":"address"},{"internalType":"address[]","name":"beneficiaries","type":"address[]"},{"internalType":"uint256[]","name":"percentages","type":"uint256[]"}],"internalType":"struct ARLibrary.Claim","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"_material","type":"string"}],"name":"getMaterial","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"","type":"string"}],"name":"materials","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"_barcodeId","type":"string"},{"internalType":"string","name":"_material","type":"string"},{"components":[{"internalType":"address","name":"beneficiary","type":"address"},{"internalType":"uint256","name":"percent","type":"uint256"}],"internalType":"struct ARLibrary.Beneficiary[]","name":"_beneficiaries","type":"tuple[]"},{"internalType":"string","name":"_tokenUri","type":"string"}],"name":"mintClaim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"_material","type":"string"}],"name":"removeMaterial","outputs":[],"stateMutability":"nonpayable","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":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"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"}]