Transfer NFT using Token.createTransferInstruction

916 views Asked by At

We have a transaction that transfers SOL & an NFT from the wallet's owner to our wallet. The transaction contains simple instructions:

  1. Token.createAssociatedTokenAccountInstruction
    Conditionnal, depending on the destination (our wallet)
  2. Token.createTransferInstruction Transfers from the owner's token account to our token account.
  3. SystemProgram.transfer SOL transfer.

Here is the transfer code (spl-token v0.1.8)

let createTransferInstructions = async function (mint, from, to, cluster) {
    let connection = new Connection(cluster, "confirmed")

    const mintPublicKey  = new PublicKey(mint);
    const ownerPublicKey = new PublicKey(from);
    const destPublicKey  = new PublicKey(to);
    

    // GET SOURCE ASSOCIATED ACCOUNT
    const associatedSourceTokenAddr = await Token.getAssociatedTokenAddress(
        ASSOCIATED_TOKEN_PROGRAM_ID,
        TOKEN_PROGRAM_ID,
        mintPublicKey,
        ownerPublicKey
    );
    
    // GET DESTINATION ASSOCIATED ACCOUNT
    const associatedDestinationTokenAddr = await Token.getAssociatedTokenAddress(
        ASSOCIATED_TOKEN_PROGRAM_ID,
        TOKEN_PROGRAM_ID,
        mintPublicKey,
        destPublicKey
    );

    const receiverAccount = await connection.getAccountInfo(associatedDestinationTokenAddr);

    const instructions = [];

    if (receiverAccount === null)
        instructions.push(
            Token.createAssociatedTokenAccountInstruction(
                ASSOCIATED_TOKEN_PROGRAM_ID,
                TOKEN_PROGRAM_ID,
                mintPublicKey,
                associatedDestinationTokenAddr,
                destPublicKey,
                ownerPublicKey
            )
        )

    instructions.push(
        Token.createTransferInstruction(
            TOKEN_PROGRAM_ID,
            associatedSourceTokenAddr,
            associatedDestinationTokenAddr,
            ownerPublicKey,
            [],
            1
        )
    );

    return instructions;
}

Here is the transaction code:

var transaction = new this.solana.Transaction({
   feePayer: new this.solana.PublicKey(from),
   recentBlockhash: await blockhashObj.blockhash
});

for (let transferInstruction of transferInstructions) {
   transaction.add(transferInstruction);
}

transaction.add(this.solana.SystemProgram.transfer({
   fromPubkey: new this.solana.PublicKey(this.provider.publicKey),
   toPubkey: new this.solana.PublicKey(farm.address),
   lamports: 10000000 
}));

The owners have to validate the transaction with their wallets (phantom, solflare etc..)
And everything works great, for most NFTs.

Some NFT owners are complaining about not being able to validate the transaction on the wallet, an error message indicates that the transaction can't be confirmed.

However, the NFT can be transferred successfully using the wallet's interface, can be listed on marketplaces etc. Even when the NFT is transferred to another wallet, the transaction above works perfectly.

I'm wondering if this has anything to do with the associated token account? If so, what is the solution?

0

There are 0 answers