1

I've created a dApp on React which uses the Solana blockchain to create, mint, and send utility tokens. I'm using @metaplex-foundation/umi and @mpl-toolbox to create the token, mint it to the creator's account, and then send the created tokens to any wallet address. Now, the token creation ( using createFungibleAsset instruction ) and the token minting (using mintV1) are working perfectly fine. When I use the transferToken instruction, the instruction fails with this error:

Program returned error: "invalid account data for instruction"

Also, the instruction works perfectly for the account to which the tokens were minted ( also being the creator account ) but fails for the accounts with no ATA. I've even tried creating an ATA for these accounts but still, the transaction fails.

Here's the relevant part of the code:

const [mint, setMint] = useState(generateSigner(umi));

// function triggered when the 'Create Token' button is clicked
  const submitHandler = async () => {
    const tokenName = tokenNameRef.current?.value || "";
    const tokenSymbol = tokenSymbolRef.current?.value || "";
    const tokenDescription = tokenDescriptionRef.current?.value || "";

    console.log(tokenName, tokenSymbol, tokenDescription);

    const mint = generateSigner(umi);
    setMint(mint);
    const tokenMetadata = {
      tokenName,
      tokenSymbol,
      tokenDescription,
    };

    // upload the tokenMetadata to irys ( previously bundlr)
    const uri = await umi.uploader.uploadJson([tokenMetadata]);

    console.log("TokenMetadata uploaded successfully", uri);
    toast.success("Token metadata uploaded successfully");

    // create the fungible token

    createFungibleAsset(umi, {
      mint,
      name: tokenMetadata.tokenName,
      symbol: tokenMetadata.tokenSymbol,
      uri: uri,
      sellerFeeBasisPoints: percentAmount(0),
      isMutable: true,
      isCollection: false,
      authority: umi.identity, // the address which is allowed to mint the tokens
      decimals: 3, // the divisibility of the fungible token
    })
      .sendAndConfirm(umi)
      .then(() => {
        console.log(
          tokenMetadata.tokenName + "created successfully: ",
          mint.publicKey
        );
        toast.success("🦄 Token created successfully!");
        setCanMintTokens(true);
      });
  };

// Minting the fungible token using the mpl-token-metadata library's mintV1 function
  const mintHandler = () => {
    const tokensToMint = mintAmountRef.current?.value || 0;
    mintV1(umi, {
      mint: mint.publicKey,
      authority: umi.identity,
      amount: +tokensToMint * 1000,
      tokenOwner: umi.identity.publicKey,
      tokenStandard: TokenStandard.Fungible,
    })
      .sendAndConfirm(umi, { send: { skipPreflight: true } }) // preflight is Solana's simulation of the txn, if simulation fails, txn is failed and not even sent to the chains
      .then(() => {
        console.log("minted successfully!");
        toast.success("🦄 Token minted successfully!");
      });
  };

// Send SPL tokens
  const sendSplTokensHandler = async () => {
    const tokenAmount = Number(numOfTokensToSendRef.current?.value) || 0;

    if (!destinationWalletAddressRef.current?.value) {
      throw new Error("Please provide a destination wallet address.");
    }

    if (!wallet || !wallet.publicKey) {
      throw new Error("Wallet not loaded");
    }

    if (tokenAmount <= 0) {
      throw new Error("Token amount must be greater than 0.");
    }
    const destinationWalletAddress = publicKey(
      destinationWalletAddressRef.current?.value
    );

    const senderTokenAccount = findAssociatedTokenPda(umi, {
      // Gets the ATA of the sender account
      mint: mint.publicKey,
      owner: umi.payer.publicKey,
    });
    const receiverTokenAccount = findAssociatedTokenPda(umi, {
      // Predicts the ATA of the recepient acc which doesn't exist yet
      mint: mint.publicKey,
      owner: destinationWalletAddress,
    });

    let txnBuilder = transactionBuilder();

    txnBuilder = txnBuilder.add(
      createTokenIfMissing(umi, {
        // creates the recipient ATA
        mint: mint.publicKey,
        // token: receiverTokenAccount,
        // ata: receiverTokenAccount,
        owner: receiverTokenAccount,
      })
    );

    txnBuilder = txnBuilder.append(
      transferTokens(umi, {
        source: senderTokenAccount,
        destination: receiverTokenAccount,
        amount: tokenAmount,
      })
    );
    txnBuilder
      .sendAndConfirm(umi, { send: { skipPreflight: true } })
      .then(() => {
        console.log("Token sent");
        toast.success("Token sent");
      });
  };

Now, I'll attach the transaction failure screenshot: enter image description here

I'll also attach the Solana Explorer link:

https://explorer.solana.com/tx/3pen4jY2EJWFM7fQz2wZ7PcymyT45Dq6YqJMnqZ125bSedzxud4keYHauo7ewpZ1JbKeVCsXfuVXWjuX7Kju4gJv?cluster=devnet

1 Answer 1

1

If you look at the last failing instruction in your transaction, you'll notice that it's issuing a transfer from HCBDHVQTrfMVvQEQwowE6dFj6JqKM3U4aGeac1hukyYi to EFKaPHLSxG8mCnDKMWzH9vWakNRAJeCs5NFgStsRUbNB. The first account looks correct https://explorer.solana.com/address/HCBDHVQTrfMVvQEQwowE6dFj6JqKM3U4aGeac1hukyYi?cluster=devnet, but the second one doesn't exist https://explorer.solana.com/address/EFKaPHLSxG8mCnDKMWzH9vWakNRAJeCs5NFgStsRUbNB?cluster=devnet.

Be sure to create the token account at EFKaPHLSxG8mCnDKMWzH9vWakNRAJeCs5NFgStsRUbNB before attempting a transfer using something like getOrCreateAssociatedTokenAccount.

There's likely something wrong in createTokenIfMissing since it's not creating the account.

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.