I’m building a dapp where users can deposit their NFTs into a staking contract to get rewards. I need help creating a transaction that moves the NFT from user wallet to my program wallet.
My current code:
import { Connection, PublicKey } from "@solana/web3.js";
import * as anchor from "@project-serum/anchor";
import { web3 } from "@project-serum/anchor";
import {
Token,
TOKEN_PROGRAM_ID,
ASSOCIATED_TOKEN_PROGRAM_ID,
} from "@solana/spl-token";
const transferNFTToStaking = async function (tokenMint: string, userWallet: Wallet, stakingAddress: string) {
let rpcConnection = new Connection("https://api.devnet.solana.com");
const nftMintKey = new web3.PublicKey(tokenMint);
const userPubkey = userWallet.publicKey;
const stakingPubkey = new web3.PublicKey("STAKING_PROGRAM_WALLET");
const tokenInstance = new Token(
rpcConnection,
nftMintKey,
TOKEN_PROGRAM_ID,
userWallet.payer
);
// FIND USER TOKEN ACCOUNT
const userTokenAccount = await Token.getAssociatedTokenAddress(
tokenInstance.associatedProgramId,
tokenInstance.programId,
nftMintKey,
userPubkey
);
// FIND STAKING TOKEN ACCOUNT
const stakingTokenAccount = await Token.getAssociatedTokenAddress(
tokenInstance.associatedProgramId,
tokenInstance.programId,
nftMintKey,
stakingPubkey
);
const stakingAccountInfo = await rpcConnection.getAccountInfo(
stakingTokenAccount
);
const txInstructions = [];
if (stakingAccountInfo === null) {
console.log("staking account needs creation");
txInstructions.push(
Token.createAssociatedTokenAccountInstruction(
tokenInstance.associatedProgramId,
tokenInstance.programId,
nftMintKey,
stakingTokenAccount,
stakingPubkey,
userPubkey
)
);
}
txInstructions.push(
Token.createTransferInstruction(
TOKEN_PROGRAM_ID,
userTokenAccount,
stakingTokenAccount,
userPubkey,
[],
1
)
);
let finalTransaction = null;
for (let idx = 0; idx < txInstructions.length; idx++) {
finalTransaction = new web3.Transaction().add(txInstructions[idx]);
}
if (finalTransaction) {
let txResult = await userWallet.sendTransaction(finalTransaction, rpcConnection);
console.log("transaction result: ", txResult);
} else {
console.log("Failed to build transaction");
}
};
export default transferNFTToStaking;
When I test this the wallet popup shows up and user approves it but then I get this error:
Transaction simulation failed: Error processing Instruction 0: invalid account data for instruction
Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA invoke [1]
Program log: Instruction: Transfer
Program log: Error: InvalidAccountData
Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA consumed 1781 of 200000 compute units
Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA failed: invalid account data for instruction
I already tried using the imported constants instead of the token instance properties but still getting the same error. What could be wrong with my approach?