tumi-labs / Candy-Machine-V3-UI

Candy Machine V3 UI
candy-machine-v3-ui.vercel.app
45 stars 60 forks source link

Signature verification failed - for phantom #10

Closed akinwol closed 1 year ago

akinwol commented 1 year ago

Not sure what I am doing wrong here but for some reason minting doesn't work with Phantom wallet. I tried other wallets and they seem to work. When the sendAndComfirmTransaction function runs I get an error "Signature verification failed". Not really sure why it's only an issue with phantom. Any help would be greatly appreciated.

Here is my sample code.

 const mint = React.useCallback(
    async ({ quantityString, label }: MintType) => {
      const found = guardsAndEligibility?.find((g) => g.label === label);
      console.log({ found });
      if (!found) throw new Error('Unknown guard group label');
      let nfts: (Sft | SftWithToken | Nft | NftWithToken)[] = [];
      try {
        if (!candyMachine) throw new Error('Candy Machine not loaded yet!');
        const transactionBuilders: TransactionBuilder[] = [];

        for (let index = 0; index < quantityString; index++) {
          transactionBuilders.push(
            await mintFromCandyMachineBuilder(mx, {
              candyMachine,
              collectionUpdateAuthority: candyMachine.authorityAddress, // mx.candyMachines().pdas().authority({candyMachine: candyMachine.address})
              group: label,
            })
          );
        }
        const blockhash = await mx.rpc().getLatestBlockhash();

        const transactions = transactionBuilders.map((t) =>
          t.toTransaction(blockhash)
        );
        const signers: { [k: string]: IdentitySigner } = {};

        transactions.forEach((tx, i) => {
          tx.feePayer = wallet.publicKey as PublicKey;
          tx.recentBlockhash = blockhash.blockhash;
          transactionBuilders[i]?.getSigners().forEach((s) => {
            if ('signAllTransactions' in s)
              signers[s.publicKey?.toString()] = s;
            else if ('secretKey' in s) tx.partialSign(s);
            // @ts-ignore
            else if ('_signer' in s) tx.partialSign(s._signer);
          });
        });
        let signedTransactions = transactions;

        for (let signer in signers) {
          await signers[signer]?.signAllTransactions(transactions);
        }

        const output = await Promise.all(
          signedTransactions.map((tx, i) => {
            console.log({ tx });
            return mx
              .rpc()
              .sendAndConfirmTransaction(tx, { commitment: 'finalized' })
              .then((tx) => {
                console.log({ txthen: tx });
                return {
                  ...tx,
                  context: transactionBuilders[i]?.getContext() as any,
                };
              })
              .catch((e) => {
                console.log({ e });
                throw new Error(e as any);
              });
          })
        );

        console.log({ output });

        const nfts = await Promise.all(
          output.map(({ context }) =>
            mx
              .nfts()
              .findByMint({
                mintAddress: context.mintSigner.publicKey,
                tokenAddress: context.tokenAddress,
              })
              .catch((e) => null)
          )
        );

        await fetchCandyMachine();
        const data = nfts.map((n) => ({
          address: n?.address.toBase58(),
          name: n?.name,
        }));
        return data;
      } catch (error: any) {
        console.log({ error });
        let message = error.msg || 'Minting failed! Please try again!';
        if (!error.msg) {
          if (!error.message) {
            message = 'Transaction Timeout! Please try again.';
          } else if (error.message.indexOf('0x138')) {
          } else if (error.message.indexOf('0x137')) {
            message = `SOLD OUT!`;
          } else if (error.message.indexOf('0x135')) {
            message = `Insufficient funds to mint. Please fund your wallet.`;
          }
        } else {
          if (error.code === 311) {
            message = `SOLD OUT!`;
          } else if (error.code === 312) {
            message = `Minting period hasn't started yet.`;
          }
        }
        console.error(error);
        console.log('THROWING ERROR ', error);
        // setStatus((x) => ({ ...x, minting: false }));
        throw new Error(message);
      }
    [candyMachine, guardsAndEligibility, mx, wallet?.publicKey]
  );
yuanshanhshan commented 1 year ago

Same question , need help , thank

smrnjeet222 commented 1 year ago

I'm also having same issue, any luck ?

akinwol commented 1 year ago

@yuanshanhshan @smrnjeet222 Here's the updated code to get it working.

const mint = React.useCallback(
    async ({ quantityString, label }: MintType) => {
      const found = guardsAndEligibility?.find((g) => g.label === label);
      console.log({ found });
      if (!found) throw new Error('Unknown guard group label');

      let nfts: (Sft | SftWithToken | Nft | NftWithToken)[] = [];
      try {
        if (!candyMachine) throw new Error('Candy Machine not loaded yet!');
        const transactionBuilders = await Promise.all(
          new Array(quantityString).fill(0).map(() =>
            mx.candyMachines().builders().mint({
              candyMachine,
              collectionUpdateAuthority: candyMachine.authorityAddress,
              group: label,
            })
          )
        );

        const mints = transactionBuilders.map((tb) => ({
          mintSigner: tb.getContext().mintSigner as Signer,
          mintAddress: tb.getContext().mintSigner.publicKey as PublicKey,
          tokenAddress: tb.getContext().tokenAddress as PublicKey,
        }));
        const blockhash = await mx.rpc().getLatestBlockhash();
        let signedTransactions = await wallet?.signAllTransactions!(
          transactionBuilders.map((t, ix) => {
            const tx = t.toTransaction(blockhash);
            tx.sign(mints[ix]?.mintSigner as Signer);
            return tx;
          })
        );

        const output = await Promise.all(
          signedTransactions.map((tx, i) => {
            console.log({ tx });
            return mx
              .rpc()
              .sendAndConfirmTransaction(tx, { commitment: 'finalized' })
              .then((tx) => {
                console.log({ txthen: tx });
                return {
                  ...tx,
                  context: transactionBuilders[i]?.getContext() as any,
                };
              })
              .catch((e) => {
                console.log({ e });
                throw new Error(e as any);
              });
          })
        );

        const nfts = await Promise.all(
          output.map(({ context }) =>
            mx
              .nfts()
              .findByMint({
                mintAddress: context.mintSigner.publicKey,
                tokenAddress: context.tokenAddress,
              })
              .catch((e) => null)
          )
        );

        const data = nfts.map((n) => ({
          address: n?.address.toBase58(),
          name: n?.name,
        }));
        const signatures = output.map((o) => o.signature);
        return { nftData: data, signatures };
      } catch (error: any) {
        console.log({ error });
        let message = error.msg || 'Minting failed! Please try again!';
        if (!error.msg) {
          if (!error.message) {
            message = 'Transaction Timeout! Please try again.';
          } else if (error.message.indexOf('0x138')) {
          } else if (error.message.indexOf('0x137')) {
            message = `SOLD OUT!`;
          } else if (error.message.indexOf('0x135')) {
            message = `Insufficient funds to mint. Please fund your wallet.`;
          }
        } else {
          if (error.code === 311) {
            message = `SOLD OUT!`;
          } else if (error.code === 312) {
            message = `Minting period hasn't started yet.`;
          }
        }
        console.error(error);
        console.log('THROWING ERROR ', error);
        throw new Error(message);
      }
    },
    [candyMachine, guardsAndEligibility, mx, wallet?.publicKey]
  );
smrnjeet222 commented 1 year ago

Thank You @akinwol I found the solution to my problem https://twitter.com/bfriel_/status/1604641581855698944?t=TCWHbh-ZW2VOOJ5B0xbpOA&s=19