如何使用 @solana/web3.js 请求传输 NFT

发布于 2025-01-12 02:20:46 字数 3140 浏览 0 评论 0原文

我正在开发一个 Web 应用程序,NFT 所有者可以在其中质押他们的 NFT 并获得奖励。 在我的应用程序中,我需要创建一个将 NFT 从用户钱包转移到我的应用程序钱包的请求。

代码示例:

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 doNFTTransfer = async function (mint: string, from: Wallet, to: string) {
  let connection = new Connection("https://api.devnet.solana.com");

  const mintPublicKey = new web3.PublicKey(mint);// Mint is the Mint address found in the NFT metadata
  const ownerPublicKey = from.publicKey;
  const destPublicKey = new web3.PublicKey("MY_APPS_WALLET_ADDRESS");

  const mintToken = new Token(
    connection,
    mintPublicKey,
    TOKEN_PROGRAM_ID,
    from.payer
  );

  // GET SOURCE ASSOCIATED ACCOUNT
  const associatedSourceTokenAddr = await Token.getAssociatedTokenAddress(
    mintToken.associatedProgramId,
    mintToken.programId,
    mintPublicKey,
    ownerPublicKey
  );

  // GET DESTINATION ASSOCIATED ACCOUNT
  const associatedDestinationTokenAddr = await Token.getAssociatedTokenAddress(
    mintToken.associatedProgramId,
    mintToken.programId,
    mintPublicKey,
    destPublicKey
  );

  const receiverAccount = await connection.getAccountInfo(
    associatedDestinationTokenAddr
  );

  const instructions = [];

  if (receiverAccount === null) {
    console.log("receiver account is null!");
    instructions.push(
      Token.createAssociatedTokenAccountInstruction(
        mintToken.associatedProgramId,
        mintToken.programId,
        mintPublicKey,
        associatedDestinationTokenAddr,
        destPublicKey,
        ownerPublicKey
      )
    );
  }

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

  // This transaction is sending the tokens
  let transaction = null;
  for (let i = 0; i < instructions.length; i++) {
    transaction = new web3.Transaction().add(instructions[i]);
  }

  if (transaction) {
    let response = await from.sendTransaction(transaction, connection);

    console.log("response: ", response);
  } else {
    console.log("Transaction error: transaction data is null");
  }
};

export default doNFTTransfer;

但是当我运行代码时。批准交易后提示用户接受交易我收到以下错误。

next-dev.js?3515:32 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

我还尝试将

  • mintToken.linkedProgramID 与 ASSOCIATED_TOKEN_PROGRAM_ID
  • TOKEN_PROGRAM_ID

mintToken.programI 与从 @solana/spl-token 导入的

交换有人知道我的问题可能是什么吗?

I am working on a web application where a NFT owner can stake their NFT and earn rewards.
In my application I need to create a transfer request of the NFT from the users wallet to my applications wallet.

Code Example:

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 doNFTTransfer = async function (mint: string, from: Wallet, to: string) {
  let connection = new Connection("https://api.devnet.solana.com");

  const mintPublicKey = new web3.PublicKey(mint);// Mint is the Mint address found in the NFT metadata
  const ownerPublicKey = from.publicKey;
  const destPublicKey = new web3.PublicKey("MY_APPS_WALLET_ADDRESS");

  const mintToken = new Token(
    connection,
    mintPublicKey,
    TOKEN_PROGRAM_ID,
    from.payer
  );

  // GET SOURCE ASSOCIATED ACCOUNT
  const associatedSourceTokenAddr = await Token.getAssociatedTokenAddress(
    mintToken.associatedProgramId,
    mintToken.programId,
    mintPublicKey,
    ownerPublicKey
  );

  // GET DESTINATION ASSOCIATED ACCOUNT
  const associatedDestinationTokenAddr = await Token.getAssociatedTokenAddress(
    mintToken.associatedProgramId,
    mintToken.programId,
    mintPublicKey,
    destPublicKey
  );

  const receiverAccount = await connection.getAccountInfo(
    associatedDestinationTokenAddr
  );

  const instructions = [];

  if (receiverAccount === null) {
    console.log("receiver account is null!");
    instructions.push(
      Token.createAssociatedTokenAccountInstruction(
        mintToken.associatedProgramId,
        mintToken.programId,
        mintPublicKey,
        associatedDestinationTokenAddr,
        destPublicKey,
        ownerPublicKey
      )
    );
  }

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

  // This transaction is sending the tokens
  let transaction = null;
  for (let i = 0; i < instructions.length; i++) {
    transaction = new web3.Transaction().add(instructions[i]);
  }

  if (transaction) {
    let response = await from.sendTransaction(transaction, connection);

    console.log("response: ", response);
  } else {
    console.log("Transaction error: transaction data is null");
  }
};

export default doNFTTransfer;

However when I run the code. The user is prompted to accept the transaction after approving the transaction I receive the following error.

next-dev.js?3515:32 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've also tried swapping

  • mintToken.associatedProgramID with ASSOCIATED_TOKEN_PROGRAM_ID
  • mintToken.programI with TOKEN_PROGRAM_ID

imported from @solana/spl-token

Anyone know what might be my issue ?

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

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

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

土豪 2025-01-19 02:20:46

我认为这部分是你的问题:

  // This transaction is sending the tokens
  let transaction = null;
  for (let i = 0; i < instructions.length; i++) {
    transaction = new web3.Transaction().add(instructions[i]);
  }

每次循环运行时,它都会覆盖整个事务。这意味着只有您所做的最后一笔交易才会被发送(createTransferInstruction)。下面的应该效果更好!

  // This transaction is sending the tokens
  let transaction = new web3.Transaction();
  for (let i = 0; i < instructions.length; i++) {
    transaction.add(instructions[i]);
  }

I think this section is your problem:

  // This transaction is sending the tokens
  let transaction = null;
  for (let i = 0; i < instructions.length; i++) {
    transaction = new web3.Transaction().add(instructions[i]);
  }

Every time the loop runs, it overwrites the entire transaction. This means that only the last transaction you made gets sent (createTransferInstruction). The following should work better!

  // This transaction is sending the tokens
  let transaction = new web3.Transaction();
  for (let i = 0; i < instructions.length; i++) {
    transaction.add(instructions[i]);
  }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文