2

I am trying to transfer NFT from One Account to Another account.

Where I am creating an associated account address if it is not available. A number of NFTS can transfer but only One NFT can not transfer and the reason is related to account create. The account does not exist so, try to CreateAndTransfer but throws errors.

{
  "jsonrpc": "2.0",
  "error": {
    "code": -32002,
    "message": "Transaction simulation failed: Error processing Instruction 1: invalid account data for instruction",
    "data": {
      "accounts": null,
      "err": {
        "InstructionError": [
          1,
          "InvalidAccountData"
        ]
      },
      "logs": [
        "Program ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL invoke [1]",
        "Program log: Create",
        "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA invoke [2]",
        "Program log: Instruction: GetAccountDataSize",
        "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA consumed 1622 of 394408 compute units",
        "Program return: TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA pQAAAAAAAAA=",
        "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA success",
        "Program 11111111111111111111111111111111 invoke [2]",
        "Program 11111111111111111111111111111111 success",
        "Program log: Initialize the associated token account",
        "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA invoke [2]",
        "Program log: Instruction: InitializeImmutableOwner",
        "Program log: Please upgrade to SPL Token 2022 for immutable owner support",
        "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA consumed 1405 of 387918 compute units",
        "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA success",
        "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA invoke [2]",
        "Program log: Instruction: InitializeAccount3",
        "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA consumed 4241 of 384034 compute units",
        "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA success",
        "Program ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL consumed 20545 of 400000 compute units",
        "Program ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL success",
        "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA invoke [1]",
        "Program log: Instruction: TransferChecked",
        "Program log: Error: InvalidAccountData",
        "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA consumed 1455 of 379455 compute units",
        "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA failed: invalid account data for instruction"
      ],
      "returnData": null,
      "unitsConsumed": 20545
    }
  },
  "id": 1
}
{
  "jsonrpc": "2.0",
  "error": {
    "code": -32002,
    "message": "Transaction simulation failed: Error processing Instruction 0: invalid account data for instruction",
    "data": {
      "accounts": null,
      "err": {
        "InstructionError": [
          0,
          "InvalidAccountData"
        ]
      },
      "logs": [
        "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA invoke [1]",
        "Program log: Instruction: TransferChecked",
        "Program log: Error: InvalidAccountData",
        "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA consumed 1455 of 200000 compute units",
        "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA failed: invalid account data for instruction"
      ],
      "returnData": null,
      "unitsConsumed": 0
    }
  },
  "id": 1
}
private fun createAndSignTransaction(
        amount: Double,
        contractAddress: String,
        senderTokenAddress: String,
        receiver: String,
        decimals: Int,
        blockhash: String
    ): Solana.SigningOutput {
        val _privateKey = wallet.getPrivateKeyAsBytes(CoinType.SOLANA.value())

        val transferMessage = Solana.CreateAndTransferToken.newBuilder().apply {
            this.recipientMainAddress = receiver
            this.tokenMintAddress = contractAddress
            this.senderTokenAddress = senderTokenAddress
            this.recipientTokenAddress =
                associatedAddress(receiver, contractAddress = contractAddress)
            this.amount = amount.toBigDecimal().toWEI(decimals).toLong()
            this.decimals = decimals
        }.build()
        val signingInput = Solana.SigningInput.newBuilder().apply {
            this.privateKey = ByteString.copyFrom(_privateKey)
            this.createAndTransferTokenTransaction = transferMessage
            this.recentBlockhash = blockhash
        }.build()
        return AnySigner.sign(signingInput, CoinType.SOLANA, Solana.SigningOutput.parser())

    }
2
  • Can you add the code for how you built the transaction?
    – john
    Commented Jan 3, 2023 at 11:36
  • I added code above Commented Jan 3, 2023 at 11:43

1 Answer 1

3

Here is an example of how to build a transaction using @solana/web3.js and @solana/spl-token that will create a token account if it does not already exist and transfer an SPL token in a single transaction. The sender/receiver in the example are just placeholders.

Note that NFTs on Solana are basically just SPL-Tokens with 0 decimals and metadata

import {
  Connection,
  Keypair,
  PublicKey,
  clusterApiUrl,
  Transaction,
} from "@solana/web3.js"
import {
  ASSOCIATED_TOKEN_PROGRAM_ID,
  createAssociatedTokenAccountInstruction,
  getAssociatedTokenAddress,
  TOKEN_PROGRAM_ID,
  Account,
  getAccount,
  createTransferInstruction,
} from "@solana/spl-token"

async function main() {
  const connection = new Connection(clusterApiUrl("devnet"))

  // Generate a new keypair to represent the sender
  const sender = Keypair.generate()

  // Generate a new keypair to represent the receiver
  const receiver = Keypair.generate()

  // The MINT address of token to transfer (ex. mint of NFT)
  const MINT = new PublicKey("Gh9ZwEmdLJ8DscKNTkTqPbNwLNNBjuSzaG9Vp2KGtKJr")

  // Get the sender's associated token account address
  const senderTokenAccountAddress = await getAssociatedTokenAddress(
    MINT,
    sender.publicKey
  )

  // Get the receiver's associated token account address
  const receiverTokenAccountAddress = await getAssociatedTokenAddress(
    MINT,
    receiver.publicKey
  )

  // Create a new transaction
  const transaction = new Transaction()

  // Create an instruction to create the receiver's token account if it does not exist
  const createAccountInstruction = createAssociatedTokenAccountInstruction(
    sender.publicKey,
    receiverTokenAccountAddress,
    receiver.publicKey,
    MINT,
    TOKEN_PROGRAM_ID,
    ASSOCIATED_TOKEN_PROGRAM_ID
  )

  // Check if the receiver's token account exists
  let receiverTokenAccount: Account
  try {
    receiverTokenAccount = await getAccount(
      connection,
      receiverTokenAccountAddress,
      "confirmed",
      TOKEN_PROGRAM_ID
    )
  } catch (e) {
    // If the account does not exist, add the create account instruction to the transaction
    transaction.add(createAccountInstruction)
  }

  // Create an instruction to transfer 1 token from the sender's token account to the receiver's token account
  const transferInstruction = await createTransferInstruction(
    senderTokenAccountAddress,
    receiverTokenAccountAddress,
    sender.publicKey,
    1
  )

  // Add the transfer instruction to the transaction
  transaction.add(transferInstruction)

  // Send the transaction signed by the sender
  const transactionSignature = await connection.sendTransaction(transaction, [
    sender,
  ])

  console.log(transactionSignature)
}

Here's the Metaplex docs that goes over tokens/NFTs on Solana: https://docs.metaplex.com/programs/understanding-programs

1
  • Thanks, @John but, I am using wallet-core lib so, can not do how you sent it. it will honorable if you tell me the reason behind the error. Commented Jan 4, 2023 at 7:07

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.