How to move NFTs created with Metaplex candy machine to another wallet

I’m working on transferring NFTs that were created using Metaplex candy machine to different wallet addresses. I have a few questions about this process.

First, when an NFT gets minted through the candy machine, does it create a token account automatically? I need to know this because I want to transfer ownership using JavaScript.

I’m trying to use the getOrCreateAssociatedTokenAccount function but I’m running into issues. The function requires a keypair parameter, but I only have the wallet address available. How can I get the keypair from just a wallet address?

Here’s what I have so far:

// Current NFT owner's wallet address - need keypair instead
const currentOwner = original_wallet;
// New owner's public key  
const newOwner = recipient_wallet;
// The NFT's mint address
let nftMint = token_mint_address;
// Solana connection
const solanaConnection = my_connection;

// Create token account for recipient
const recipientTokenAccount = await getOrCreateAssociatedTokenAccount(
    solanaConnection, 
    currentOwner, 
    nftMint, 
    newOwner
);

// This is where I'm stuck - need keypair but only have address
const senderTokenAccount = await getOrCreateAssociatedTokenAccount(
    solanaConnection,
    currentOwner, // This needs to be a keypair
    nftMint,
    currentOwner.publicKey
);

const txSignature = await transfer(
    solanaConnection,
    currentOwner,
    senderTokenAccount.address,
    recipientTokenAccount.address,
    currentOwner.publicKey,
    1
);
console.log(`Transfer completed: ${txSignature}`);

Any help would be appreciated!

wait hold up - you cant just grab someones keypair from their wallet address, thats not how it works at all lol. the whole point of crypto is that private keys stay private. if you’re trying to move nfts that users own, they gotta sign it themselves thru their wallet connection. sounds like you need to implement wallet adapter instead of trying to get keypairs directly

You’re mixing up some concepts here. The getOrCreateAssociatedTokenAccount function is meant for creating token accounts, not for transferring ownership. When you want to transfer an NFT, you don’t need to create new token accounts - the associated token accounts already exist or get created automatically during the transfer process. For NFT transfers, you should be using createTransferInstruction from @solana/spl-token. The keypair issue you’re facing suggests you’re trying to transfer tokens without having the private key of the current owner. You can’t transfer tokens from a wallet unless you have its private key - that would be a major security flaw. If you’re building an application where users need to transfer their own NFTs, they need to sign the transaction themselves using their wallet (like Phantom or Solflare). You would create the transaction instruction and have them approve it through their wallet interface. The wallet handles the signing with their private key, not your code.

Oh interesting! I’ve been down this rabbit hole before with candy machine transfers and it can be pretty confusing at first.

So here’s the thing - when you mint from a candy machine, yeah it does create the associated token account automatically for whoever’s minting. That part’s handled for you which is nice.

But i’m curious about your setup here - are you trying to do this transfer as like an admin function where you control both wallets? Or are you building something where users would transfer their own nfts? Because that changes everything about how you’d approach this.

If you’re the one who minted these originally and you have the private keys for the current owner wallet, then you’d need to create a Keypair object from that private key. But if these are user-owned nfts, then you definitley can’t just transfer them without the user’s permission - they’d need to sign the transaction themselves.

Also just wondering - what’s the specific error you’re getting when you run this code? Is it complaining about the keypair type or something else? That might give us a better clue about what’s going wrong.

And one more thing - have you looked into using createTransferCheckedInstruction instead? Sometimes that works better with NFTs since it does additional validation. Just a thought!

What’s your end goal here exactly? Are you trying to build like a marketplace feature or just moving some nfts around between your own wallets?