2

I have an ipfs URL stored in a variable named string memory _uri and I am setting it to this in the constructor: "ipfs://QmPsG54TQRaeuqRexDXxd77E916zMugjsqmifH2QTvAmxr/{id}.json" and I want to split this to 3 parts so I can ask for whichever token I want:

abi.encodePacked(
            "ipfs://QmPsG54TQRaeuqRexDXxd77E916zMugjsqmifH2QTvAmxr/",
            Strings.toString(_tokenId),
            ".json"
           )

How can I split the _uri programmatically so the "ipfs://QmPsG54TQRaeuqRexDXxd77E916zMugjsqmifH2QTvAmxr/" and ".json" parts could also be dynamic?

PS: I also have a setURI function to change the URI. This is why I need it to be dynamic.

PS2: The full function to retreive the token by ID in ERC1155 contract:

function uri(uint256 _tokenId) override public pure returns (string memory) {
        return string(
            abi.encodePacked(
            "ipfs://QmPsG54TQRaeuqRexDXxd77E916zMugjsqmifH2QTvAmxr/",
            Strings.toString(_tokenId),
            ".json"
           )
        );
      }

1 Answer 1

2

I don't know of any easy way to do this in solidity. And if you are forced to do string manipulation on smartContracts you have probably made an error in your idea/design of the whole thing. It's expensive and such a thing is better left for some API to do.

However, you asked for help, so here is an example of a contract with two functions that together do exactly what you need (They replace {id} in URL to whatever token name you would like.

Hope this helps you.

// SPDX-License-Identifier: MIT
pragma solidity >=0.7.0 <0.9.0;
pragma experimental ABIEncoderV2;
 
 
 contract ReplaceWord {

 
 function _stringReplace(string memory _URL, string memory _tokenID) public pure returns (string memory) {
        bytes memory _stringBytes = bytes(_URL);
        uint count = _stringBytes.length -1; //Length of string

        bytes memory idByte = bytes("{i");
        bytes memory word;
        

        bytes memory result = new bytes(count);
        

  for(uint i = 0; i < count; i++) {
        word = bytes.concat(_stringBytes[i],_stringBytes[i+1] );
        
      
        if (keccak256(word) == keccak256(idByte)){

            bytes memory firstHalf = new bytes(count);
            bytes memory secondHalf = new bytes(count);
            (firstHalf,secondHalf)= _splitString(_stringBytes,i);
  
            result= abi.encodePacked(firstHalf,_tokenID,secondHalf);
            _stringBytes = result;
            return string(result);

        }
     

    }
      return string(result);
 }


 function _splitString(bytes memory _stringBytes, uint splitPoint) internal pure returns (bytes memory, bytes memory){

      uint lenght = _stringBytes.length;
      bytes memory firstHalf = new bytes(splitPoint);
      bytes memory secondHalf = new bytes(lenght-splitPoint-4);


      for(uint n = 0; n < splitPoint; n++) {
      firstHalf[n] = _stringBytes[n];
      }

        //Using 4 because the is the number of char in "{id}"
      for(uint x = 0; x < (lenght - splitPoint - 4); x++) {
      secondHalf[x] = _stringBytes[x + splitPoint + 4 ];
      }

      return (firstHalf, secondHalf);

 }


 }

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.