Solana Sending SPL-Token Transaction

Viewed 27

I am trying to send a transaction through a DAPP. I am using solana wallet adapter to connect to my wallet. Once my wallet is connected to my app, here is the method that is called.``

const sendNFTs = async () => {
    if(itemsToSend.length > 0) {

      for (var i = 0; i < itemsToSend.length; i++) {
        const toPubKey = new PublicKey(toAddress)
        const tokenPubkey = new PublicKey(itemsToSend[i]);
        const fromTokenAccount = await findAssociatedTokenAddress(wallet.publicKey, itemsToSend[i]);
        console.log(fromTokenAccount.toString())
        let toTokenAccount = await splToken.Token.getAssociatedTokenAddress(
          ASSOCIATED_TOKEN_PROGRAM_ID,
          TOKEN_PROGRAM_ID,
          tokenPubkey,
          toPubKey
        );
        console.log(`ata: ${toTokenAccount.toBase58()}`);
        const transaction = new Transaction().add(
          splToken.Token.createTransferInstruction(
            splToken.TOKEN_PROGRAM_ID,
            fromTokenAccount,
            toTokenAccount,
            fromTokenAccount,
            [],
            1
        )
        );
        let signature = ""
        try {
          let blockhash = await (await connection.getLatestBlockhash('finalized')).blockhash;
          transaction.recentBlockhash = blockhash;
          transaction.feePayer = wallet.publicKey
          await signTransaction(transaction)
          signature = await sendTransaction(transaction, connection);
          await connection.confirmTransaction(signature, 'confirmed');
          notify({ type: 'success', message: 'Transaction successful!', txid: signature });
        } catch (error) {
          notify({ type: 'error', message: 'Error sending tx', description: `${error} `, txid: signature });
        }
      }
      
    }
  }

async function findAssociatedTokenAddress(
    walletAddress: PublicKey,
    tokenMintAddress: PublicKey,
  ): Promise<PublicKey> {
    return (
      await PublicKey.findProgramAddress(
        [
          walletAddress.toBuffer(),
          TOKEN_PROGRAM_ID.toBuffer(),
          new PublicKey(tokenMintAddress).toBuffer(),
        ],
        ASSOCIATED_TOKEN_PROGRAM_ID,
      )
    )[0];
  }

WalletSendTransactionError: failed to send transaction: Transaction simulation failed: Error processing Instruction 0: invalid account data for instruction

Here is my thought process on how I was going about it: I have an array of mint addresses so I am looping over it to send each token. I first get public keys for the "toAddress" which is the receiver, the tokenPubKey from the mint address, and then I get the token addresses for the receiver and sender. I was following the solana cookbook on how to send SPL tokens so I create a transaction with a transfer instruction. I then try to send the transaction. I confirm the transaction in the browser and then I get the error mentioned above. I am thinking my toTokenAccount is wrong or something but I am not sure

1 Answers

"Invalid account data" says that one of the accounts passed in does not contain the correct data, so likely either the sending account fromTokenAccount or the recipient account toTokenAccount is incorrect.

Since fromTokenAccount is controlled by you, it probably exists, but toTokenAccount may not exist. You can check that the account exists, and if not, prepend a createAssociatedTokenAccount instruction for toTokenAccount, ie:

const transaction = new Transaction();
const fetchedAccount = await connection.getAccountInfo(toTokenAccount);
if (fetchedAccount === null) {
    transaction.add(splToken.Token.createAssociatedTokenAccount(...));
}
Related