I'm developing a lazy minting website, which is deployed to Mumbai network. But the token id return undefined.


async function mintNFT({ contract, ownerAddress, provider, gasPrice, setStatus, image, name, description }) {

  // First we use the nft.storage client library to add the image and metadata to IPFS / Filecoin
  const client = new NFTStorage({ token: NFT_STORAGE_KEY });
  setStatus("Uploading to nft.storage...")
  const metadata = await client.store({
  setStatus(`Upload complete! Minting token with metadata URI: ${metadata.url}`);

  // the returned metadata.url has the IPFS URI we want to add.
  // our smart contract already prefixes URIs with "ipfs://", so we remove it before calling the `mintToken` function
  const metadataURI = metadata.url.replace(/^ipfs:\/\//, "");
  console.log("MetaData URI "+metadataURI);  

  // get metadata hash replace 1
  const lazyMinter = new LazyMinter({ contract, signer: ownerAddress })
  const voucher =  lazyMinter.createVoucher(1, metadata.url)
  console.log("Token Id  "+voucher.tokenId);
  return voucher.tokenId;


   * Creates a new NFTVoucher object and signs it using this LazyMinter's signing key.
   * @param {ethers.BigNumber | number} tokenId the id of the un-minted NFT
   * @param {string} uri the metadata URI to associate with this NFT
   * @param {ethers.BigNumber | number} minPrice the minimum price (in wei) that the creator will accept to redeem this NFT. defaults to zero
   * @returns {NFTVoucher}
  async createVoucher(tokenId, uri, minPrice = 0) {
    const voucher = { tokenId, uri, minPrice }
    const domain = await this._signingDomain()
    const types = {
      NFTVoucher: [
        { name: "tokenId", type: "uint256" },
        { name: "minPrice", type: "uint256" },
        { name: "uri", type: "string" },
    const signature = await this.signer._signTypedData(domain, types, voucher);
    return {

   * @private
   * @returns {object} the EIP-721 signing domain, tied to the chainId of the signer
  async _signingDomain() {
    if (this._domain != null) {
      console.log("it s not null");
      return this._domain
    console.log("The contract is " + this.contract);
    console.log("chain id " + this.contract.getChainID())
    const chainId = await this.contract.getChainID();
    console.log("chain id " + chainId);
    this._domain = {
      verifyingContract: this.contract.address,
    return this._domain

Console output

enter image description here


After added async in front, I get this error in frontend:

Unhandled Rejection (Error): call revert exception (method="getChainID()", errorArgs=null, errorName=null, errorSignature=null, reason=null, code=CALL_EXCEPTION, version=abi/5.2.0)

This is the console log displayed in _signingDomain method.

The contract is [object Object]
LazyMinter.js:70 chain id [object Promise]

1 Answer 1


const voucher = lazyMinter.createVoucher(1, metadata.url)

Here you are calling an asynchronous function without telling the thread to wait for the result.

const voucher = await lazyMinter.createVoucher(1, metadata.url)

As you have added a couple of awaits in the code, the above solution would be the simplest. Also you can use a promise or rxjs based solution.

  • after I add await in front, it not printing Token Id. Seems like keep waiting for something to return.
    – John Joe
    Commented Dec 23, 2022 at 7:31
  • it might be an issue with one or both of the async functions, there are no errors? can you check whether await this.contract.getChainID() and ` await this.signer._signTypedData(domain, types, voucher)` with console logs. also, the signer code is not visible hope it looks something like const signer = new ethers.Wallet(privateKey) Commented Dec 23, 2022 at 11:01
  • thanks for the tips! I have edited my post.
    – John Joe
    Commented Dec 23, 2022 at 16:34
  • 1
    Thanks ! I just replace chain id as 80001 first since it deployed to Mumbai.
    – John Joe
    Commented Dec 24, 2022 at 15:35
  • 1
    As you are using ERC721, You do. Or you can let the solidity code do the increment by removing tokenId as a parameter too. I hope you are checking whether the token is already minted before minting a token in your solidity contract, otherwise, there is a vulnerability of someone overriding metatada URL or even the price for that matter. Happy to help, have a nice day!! Commented Dec 24, 2022 at 19:13

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.