How to call `meetadataURI` to mint with `Moralis.executeFunction();`

Following code would execute the smart contract, but it fails to get metadata associated. So, the NFT is listed on Opensea without the image. I can’t figure out how to configure the metadataURI in the transactionParameters.

const nft_contract_address = "0xDed2d19bF2495b2c45d55FfEFd104292E8eFE38d"
const ABI = ABI

async function mintNFT(){

await Moralis.enableWeb3();
const web3 = new Web3(Moralis.provider);

const getBase64ImageFromUrl=(imageUrl)=>
new Promise(resolve=> fetch(imageUrl).then(res=>res.blob()).then(blob=>{
const reader = new FileReader();
reader.addEventListener('load',()=>{
resolve(reader.result); 
});
reader.readAsDataURL(blob);
})
);
(async()=>{
const url='';
const data = await getBase64ImageFromUrl(url);
const file1 = new Moralis.File("image.png", { base64: data });
await file1.saveIPFS();
console.log("ipfsURL:", file1.ipfs());
await file1.saveIPFS();
const imageURI = file1.ipfs();

const metadata = {
"name":"name",
"description":"description",
"image":imageURI,
}

const metadataFile = new Moralis.File("metadata.json", {base64 :btoa(JSON.stringify(metadata))});
await metadataFile.saveIPFS();
const metadataURI = metadataFile.ipfs();
const txt = await mintToken(metadataURI).then(notify)
})();

async function mintToken(_uri){

const encodedFunction = web3.eth.abi.encodeFunctionCall({
name: "mint",
type: "function",
inputs: [{
type: 'string',
name: 'tokenURI'
}]
}, [_uri]);


const options = {
  contractAddress: nft_contract_address,
  functionName: "mint",
  abi: ABI,
  msgValue: Moralis.Units.ETH("0.01"),
};

const transactionParameters = {
    to: nft_contract_address,
    from: ethereum.selectedAddress,
    data: encodedFunction
  };

const txt = await ethereum.request({
    method: 'eth_sendTransaction',
    params: [transactionParameters]
  });
  return txt
}

const transaction = await Moralis.executeFunction(options);
const result = await transaction.wait();

async function notify(_txt){
  document.getElementById("resultSpace").innerHTML =  
  `<input disabled = "true" id="result" type="text" class="form-control" placeholder="Description" aria-label="URL" aria-describedby="basic-addon1" value="Your NFT was minted in transaction ${_txt}">`;
}
}

mintNFT();

Thanks in advance.

Try to add a console.log here to see what is the value for metadataURI

I get https://ipfs.moralis.io:2053/ipfs/QmaGVM7CVpN7iVowZePEAUSdsjHPcNKQLchbYhxTN3azp4

How does it relate to my question?
I can not figure out where to put the metadataURI. Is it called in transactionParameters or options? Is there any code sample that mints NFT?

here you have an example in documentation:
https://v1docs.moralis.io/moralis-dapp/web3/web3#example-of-calling-a-write-contract-method

Thanks for the reference. I read through the document twice, but couldn’t figure out how to associate the metadataURI in the Moralis.executeFunction(). Sorry I am still newbie in here. Could you kindly point me where to put the medataURI so that I can include the metadata onto eth blockchain?

I had the impression that you asked how to send a parameter, that was an example with a parameter.
You have to know what is the parameter name for your specific case.

I still don’t understand what to do next. Could you elaborate a bit more detail?

What is the code that you use now?

const nft_contract_address = "0xDed2d19bF2495b2c45d55FfEFd104292E8eFE38d"
const ABI = ABI

async function mintNFT(){

await Moralis.enableWeb3();
const web3 = new Web3(Moralis.provider);

const getBase64ImageFromUrl=(imageUrl)=>
new Promise(resolve=> fetch(imageUrl).then(res=>res.blob()).then(blob=>{
const reader = new FileReader();
reader.addEventListener('load',()=>{
resolve(reader.result); 
});
reader.readAsDataURL(blob);
})
);
(async()=>{
const url='';
const data = await getBase64ImageFromUrl(url);
const file1 = new Moralis.File("image.png", { base64: data });
await file1.saveIPFS();
console.log("ipfsURL:", file1.ipfs());
await file1.saveIPFS();
const imageURI = file1.ipfs();

const metadata = {
"name":"name",
"description":"description",
"image":imageURI,
}

const metadataFile = new Moralis.File("metadata.json", {base64 :btoa(JSON.stringify(metadata))});
await metadataFile.saveIPFS();
const metadataURI = metadataFile.ipfs();
const txt = await mintToken(metadataURI).then(notify)
})();

async function mintToken(_uri){

const encodedFunction = web3.eth.abi.encodeFunctionCall({
name: "mint",
type: "function",
inputs: [{
type: 'string',
name: 'tokenURI'
}]
}, [_uri]);


const options = {
  contractAddress: nft_contract_address,
  functionName: "mint",
  abi: ABI,
  msgValue: Moralis.Units.ETH("0.01"),
};

const transactionParameters = {
    to: nft_contract_address,
    from: ethereum.selectedAddress,
    data: encodedFunction
  };

const txt = await ethereum.request({
    method: 'eth_sendTransaction',
    params: [transactionParameters]
  });
  return txt
}

const transaction = await Moralis.executeFunction(options);
const result = await transaction.wait();

async function notify(_txt){
  document.getElementById("resultSpace").innerHTML =  
  `<input disabled = "true" id="result" type="text" class="form-control" placeholder="Description" aria-label="URL" aria-describedby="basic-addon1" value="Your NFT was minted in transaction ${_txt}">`;
}
}

mintNFT();

This is the contract.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.8;

import '@openzeppelin/contracts/token/ERC721/ERC721.sol';
import '@openzeppelin/contracts/access/Ownable.sol';

contract SimpleMintContract is ERC721, Ownable {
    uint256 public mintPrice = 0.01 ether;
    uint256 public totalSupply;
    uint256 public maxSupply;
    bool public isMintEnabled;
    mapping(address => uint256) public mintedWallets;

    constructor() payable ERC721('Simple Mint', 'SIMPLEMINT'){
        maxSupply = 20;
    }

    function toggleIsMintedEnabled() external onlyOwner {
        isMintEnabled = !isMintEnabled;
    }

    function setMaxSupply(uint256 maxSupply_) external onlyOwner {
        maxSupply = maxSupply_;
    }

    function mint() external payable {
        require(isMintEnabled, 'minting not enabled');
        require(mintedWallets[msg.sender] < 5, 'exceeds max per wallet');
        require(msg.value == mintPrice, 'wrong value');
        require(maxSupply > totalSupply, 'sold out');

        mintedWallets[msg.sender]++;
        totalSupply++;
        uint256 tokenId = totalSupply;
        _safeMint(msg.sender, tokenId);
    }
}

I don’t see parameters used here, you can look in documentation to see how to add them

I am still making lots of tries and errors. When something goes right, other things go wrong…

I cannot figure out why this error occurs:

This is the current code:

const txt = await mintToken(metadataURI).then(notify)
})();

async function mintToken(_uri){

const encodedFunction = web3.eth.abi.encodeFunctionCall({
name: "mint",
type: "function",
inputs: [{type: 'string', name: 'tokenURI'},]
}, [_uri]);

const options = {
contractAddress: nft_contract_address,
functionName: "mint",
abi: ABI,
params: {
type: 'string', 
name: 'tokenURI',
msgValue: Moralis.Units.ETH("0.01")
},
};

const transaction = await Moralis.executeFunction(options);
const result = await transaction.wait();

const transactionParameters = {
to: nft_contract_address,
from: ethereum.selectedAddress,
data: encodedFunction,
  };
  
const txt = await ethereum.request({
method: 'eth_sendTransaction',
params: [transactionParameters]
  });
  return txt
}

async function notify(_txt){
  document.getElementById("resultSpace").innerHTML =  
  `<input disabled = "true" id="result" type="text" class="form-control" placeholder="Description" aria-label="URL" aria-describedby="basic-addon1" value="Your NFT was minted in transaction ${_txt}">`;
}

This is the contract function:

    function mint(string memory tokenURI) external payable {
        require(isMintEnabled, 'minting not enabled');
        require(mintedWallets[msg.sender] < 5, 'exceeds max per wallet');
        require(msg.value == mintPrice, 'wrong value');
        require(maxSupply > totalSupply, 'sold out');

        mintedWallets[msg.sender]++;
        totalSupply++;
        uint256 tokenId = totalSupply;
        _safeMint(msg.sender, tokenId);
        _setTokenURI(tokenId, tokenURI);

    }

Could I have any advises, please.

it looks like you are using two different methods there, one with moralis.ExecuteFunction an one with

try to use only one of them

Thanks for telling me that.
I have removed all the redundant codes:
I still get the same error.

const txt = await mintToken(metadataURI)
})();

async function mintToken(_uri){

const encodedFunction = web3.eth.abi.encodeFunctionCall({
name: "mint",
type: "function",
inputs: [{type: 'string', name: 'tokenURI'},]
}, [_uri]);

const options = {
contractAddress: nft_contract_address,
functionName: "mint",
abi: ABI,
params: {
type: 'string', 
name: 'tokenURI',
msgValue: Moralis.Units.ETH("0.01")
},
};

const transaction = await Moralis.executeFunction(options);
const result = await transaction.wait();

const transactionParameters = {
to: nft_contract_address,
from: ethereum.selectedAddress,
data: encodedFunction,
};

}
}

look at the example from documentation

Now, I started to understand how to catch the variable that resides in the smart contract.
But, I get new error which is related to msg.value.

Here is the error:

Here is the code:

const metadataURI = metadataFile.ipfs();
console.log("metadataURI:", metadataURI);

const options = {
contractAddress: nft_contract_address,
functionName: "mint",
abi: ABI,
params: {
tokenURI: metadataURI,
msgValue: Moralis.Units.ETH("0.01")
}
};

await mintToken(metadataURI);


async function mintToken(_uri){

const encodedFunction = web3.eth.abi.encodeFunctionCall({
name: "mint",
type: "function",
inputs: [{"name": "tokenURI", "type": "string"},]
}, [_uri]);


const transaction = await Moralis.executeFunction(options);
const result = await transaction.wait();

const transactionParameters = {
to: nft_contract_address,
from: ethereum.selectedAddress,
data: encodedFunction,
};

}


})();

Why is MetaMask returning me the error? I gave it the correct value tho.

maybe that wrong value message is directly from the contract? maybe there is a check in that contract function

msgValue needs to be outside of the params object.

const options = {
  contractAddress: nft_contract_address,
  functionName: "mint",
  abi: ABI,
  params: {
    tokenURI: metadataURI,
  },
  msgValue: Moralis.Units.ETH("0.01")
};

Thanks, @alex.
You are right. msgValue worked at outside of the param object.

But, I still cannot figure out why the total amount is way higher than the msgValue: Moralis.Units.ETH("0.01").

Total amount is 18.4894ETH. Gas fee is 0.04275ETH.
I was supposed to have the total of 1.04275. Why 18.4894?

Btw, msgValue: Moralis.Units.ETH("0.01") is called right, because whenever I change the value to something other than the 0.01, I get wrong value in return. This message is exactly what I meant as in require(msg.value == mintPrice, 'wrong value');

chain: "rinkeby", solved the issue related to the total amount.