Skip to main content
2 of 3
Added a working version

Invalid account data on multisig token transfer from nodejs

I have a multisig address with 3 other signers. Not sure if this was created with cli or serum project (the developer that created it is working anymore).

When trying to transfer a token, I get this error:

   'Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA invoke [1]',
   'Program log: Instruction: Transfer',
   'Program log: Error: InvalidAccountData',
   'Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA consumed 1810 of 200000 compute units',
   'Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA failed: invalid account data for instruction'

Code:

const signer1Account = Keypair.fromSecretKey(key1);
const signer2Account = Keypair.fromSecretKey(key2);
const signer3Account = Keypair.fromSecretKey(key3);

const tokenAmount = 10000

const tokenMintPubkey = new PublicKey(' ');
const fromMultisigAddress = new PublicKey(' ');
const fromMultisigOwnerAddress = new PublicKey('');
const toAddress = new PublicKey('');

const amountToTransfer = tokenAmount * Math.pow(10, 6);

(async () => {

  let toAddressTokenAccount = await getOrCreateAssociatedTokenAccount(
    connection,
    signer1Account,
    tokenMintPubkey,
    toAddress,
    true
  );
  console.log(`toAddressTokenAccount: ${toAddressTokenAccount.address}`);

  
  let tx = new Transaction();
  try {
    tx.add(
      createTransferInstruction(
        fromMultisigAddress, // from
        toAddressTokenAccount.address, // to
        TOKEN_PROGRAM_ID, // from's owner
        amountToTransfer, // amount
        [signer1Account, signer2Account, signer3Account] //signers
      )
    );    
  } catch (error) {
    console.error(error)
  }  

  try {
    const latestBlockHash = await connection.getLatestBlockhash('confirmed');
    tx.recentBlockhash = await latestBlockHash.blockhash;    
    const signature = await sendAndConfirmTransaction(connection, tx, [signer1Account, signer2Account, signer3Account]);
  } catch (error) {
    console.error(error)
  }
})();

I search and read all questions on it, found this but I am not sure how to solve it. Error: Invalid account data for instruction

Thanks for any help

Update - solved thanks to help of Jon C.

Adding the working code maybe it will help someone else

  import { clusterApiUrl, Keypair, Transaction, Connection, PublicKey, sendAndConfirmTransaction, ParsedAccountData } from "@solana/web3.js";
    import { TOKEN_PROGRAM_ID, getOrCreateAssociatedTokenAccount, createTransferInstruction } from "@solana/spl-token";
    
    // connection
    const connection = new Connection(clusterApiUrl("mainnet-beta"), "confirmed");

    // your array keys
    const key1 = new Uint8Array([]);
    const key2 = new Uint8Array([]);
    const key3 = new Uint8Array([]);
    
    
    const signer1Account = Keypair.fromSecretKey(key1);
    const signer2Account = Keypair.fromSecretKey(key2);
    const signer3Account = Keypair.fromSecretKey(key3);
    
    
    const tokenAmount = 1
    
    // your public keys
    const tokenMintPubkey = new PublicKey('');
    const fromMultisigAddress = new PublicKey('');
    const fromMultisigOwnerAddress = new PublicKey('');
    const toAddress = new PublicKey(''); 
    const tokenAddressOnMultisigAddress = new PublicKey(''); 
    
    
    async function getNumberDecimals(mintPubkey: PublicKey) : Promise<number> {
      const info = await connection.getParsedAccountInfo(mintPubkey);
      const result = (info.value?.data as ParsedAccountData).parsed.info.decimals as number;
      return result;
    }
    
    (async () => {
    
      let toAddressTokenAccount = await getOrCreateAssociatedTokenAccount(
        connection,
        signer1Account,
        tokenMintPubkey,
        toAddress,
        true
      );
    
      console.log(`toAddressTokenAccount: ${toAddressTokenAccount.address}`);
      
      const decimals = await getNumberDecimals(tokenMintPubkey); 
      console.log(`Token decimals: ${decimals}`);
    
      const amountToTransfer = tokenAmount * Math.pow(10, decimals);
    
      let tx = new Transaction();
    
      try {
        tx.add(
          createTransferInstruction(
            tokenAddressOnMultisigAddress, // from (token account on the source address)
            toAddressTokenAccount.address, // to
            fromMultisigAddress, // from's owner (owner of the token account - the multisig address)
            amountToTransfer, // amount
            [signer1Account, signer2Account, signer3Account] //signers
          )
        );    
      } catch (error) {
        console.error(error)
      }  
    
      try {
    
        const latestBlockHash = await connection.getLatestBlockhash('confirmed');
        tx.recentBlockhash = await latestBlockHash.blockhash;    
        const signature = await sendAndConfirmTransaction(connection, tx, [signer1Account, signer2Account, signer3Account]);
    
      } catch (error) {
        console.error(error)
      }
    })();