使用 Token.createTransferInstruction 转账 NFT

发布于 2025-01-11 16:33:28 字数 2539 浏览 0 评论 0原文

我们有一项转移 SOL 和 SOL 的交易;从钱包所有者到我们钱包的 NFT。 该交易包含简单的指令:

  1. Token.createAssociatedTokenAccountInstruction
    有条件的,取决于目的地(我们的钱包)
  2. Token.createTransferInstruction 从所有者的代币账户转账到我们的代币账户。
  3. 系统程序传输 SOL 传输。

这是转移代码(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;
}

这是交易代码:

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 
}));

所有者必须使用他们的钱包(phantom、solflare 等..)验证交易
对于大多数 NFT 来说,一切都运转良好。

一些 NFT 所有者抱怨无法在钱包上验证交易,错误消息表明交易无法确认。

然而,NFT 可以使用钱包界面成功转移,可以在市场上列出等。即使 NFT 转移到另一个钱包,上述交易也可以完美运行。

我想知道这是否与关联的令牌帐户有任何关系? 如果是这样,解决办法是什么?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文