首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何通过“@solana/web3.js”和“@solana/sol-钱包-适配器”传输自定义SPL令牌

如何通过“@solana/web3.js”和“@solana/sol-钱包-适配器”传输自定义SPL令牌
EN

Stack Overflow用户
提问于 2021-12-04 08:41:35
回答 5查看 14.9K关注 0票数 18

我试图转移一个自定义SPL令牌与solana-钱包适配器。然而,我很难拿到钱包的密匙/签下交易。

我已经查看了编写传输代码的这些答案,但是我需要让签名者和我很难弄清楚solana钱包适配器是如何使用的:

如何使用web3.jsSDK为Solana传输SOL?

如何通过“@solana/web3.js”传输自定义令牌

这些例子硬编码秘密密钥,因为我使用钱包扩展,这是不可能的。

根据https://github.com/solana-labs/wallet-adapter/issues/120上的这个问题,您需要:

  1. 创建@solana/web3.js事务对象并向其添加说明
  2. 用钱包签交易
  3. 通过连接发送事务

但是我很难找到关于如何做第一步和第二步的例子或文档。

代码语言:javascript
运行
复制
const SendTransaction: React.FC<Props> = ({ children }) => {
    const { connection } = useConnection()
    const { publicKey, sendTransaction } = useWallet()

    const onSendSPLTransaction = useCallback(
        async (toPubkey: string, amount: number) => {
            if (!toPubkey || !amount) return
            const toastId = toast.loading('Processing transaction...')

            try {
                if (!publicKey) throw new WalletNotConnectedError()
                const toPublicKey = new PublicKey(toPubkey)
                const mint = new PublicKey('Mint address')
                const payer = '????' // how to get this Signer
                const token = new Token(connection, mint, TOKEN_PROGRAM_ID, payer)
                const fromTokenAccount = await token.getOrCreateAssociatedAccountInfo(publicKey)
                const toTokenAccount = await token.getOrCreateAssociatedAccountInfo(toPublicKey)

                const transaction = new Transaction().add(
                    Token.createTransferInstruction(
                        TOKEN_PROGRAM_ID,
                        fromTokenAccount.address,
                        toTokenAccount.address,
                        publicKey,
                        [],
                        0
                    )
                )

                const signature = await sendTransaction(transaction, connection)

                const response = await connection.confirmTransaction(signature, 'processed')
                console.log('response', response)
                toast.success('Transaction sent', {
                    id: toastId,
                })
            } catch (error) {
                toast.error(`Transaction failed: ${error.message}`, {
                    id: toastId,
                })
            }
        },
        [publicKey, sendTransaction, connection]
    )

    return <>{children(onSendSPLTransaction)}</>
}
EN

Stack Overflow用户

发布于 2022-10-04 04:29:36

以上回答有两个问题。

  1. 首先,当我们可以使用内置的函数“@solana/钱包-适配器”、“@solana/spl-token”和“@solana/web3.js”时,我们需要编写大量的自定义代码。
  2. 第二,如果接收者帐户不存在,用户将被任何连接的钱包收取两次费用。第一次将收取创建帐户的费用,第二次将收取转移spl令牌的费用。此外,它还打开钱包审批模式两次,这将再次对用户不利。

下面的代码传输1 USDC(USDC是solana块链上的spl令牌之一)。

代码语言:javascript
运行
复制
import React from 'react';
import {
  WalletNotConnectedError,
  SignerWalletAdapterProps
} from '@solana/wallet-adapter-base';
import { useConnection, useWallet } from '@solana/wallet-adapter-react';
import {
  createTransferInstruction,
  createAssociatedTokenAccountInstruction,
  getAssociatedTokenAddress,
  getAccount
} from '@solana/spl-token';
import {
  PublicKey,
  Transaction,
  Connection,
  TransactionInstruction
} from '@solana/web3.js';

export const configureAndSendCurrentTransaction = async (
  transaction: Transaction,
  connection: Connection,
  feePayer: PublicKey,
  signTransaction: SignerWalletAdapterProps['signTransaction']
) => {
  const blockHash = await connection.getLatestBlockhash();
  transaction.feePayer = feePayer;
  transaction.recentBlockhash = blockHash.blockhash;
  const signed = await signTransaction(transaction);
  const signature = await connection.sendRawTransaction(signed.serialize());
  await connection.confirmTransaction({
    blockhash: blockHash.blockhash,
    lastValidBlockHeight: blockHash.lastValidBlockHeight,
    signature
  });
  return signature;
};

const SendSolanaSplTokens: React.FC = () => {
  const { connection } = useConnection();
  const { publicKey, signTransaction } = useWallet();

  const handlePayment = async () => {
    try {
      if (!publicKey || !signTransaction) {
        throw new WalletNotConnectedError();
      }
      const mintToken = new PublicKey(
        '4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU'
      ); // 4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU is USDC token address on solana devnet
      const recipientAddress = new PublicKey(
        'token receiver solana account address'
      );

      const transactionInstructions: TransactionInstruction[] = [];
      const associatedTokenFrom = await getAssociatedTokenAddress(
        mintToken,
        publicKey
      );
      const fromAccount = await getAccount(connection, associatedTokenFrom);
      const associatedTokenTo = await getAssociatedTokenAddress(
        mintToken,
        recipientAddress
      );
      if (!(await connection.getAccountInfo(associatedTokenTo))) {
        transactionInstructions.push(
          createAssociatedTokenAccountInstruction(
            publicKey,
            associatedTokenTo,
            recipientAddress,
            mintToken
          )
        );
      }
      transactionInstructions.push(
        createTransferInstruction(
          fromAccount.address, // source
          associatedTokenTo, // dest
          publicKey,
          1000000 // transfer 1 USDC, USDC on solana devnet has 6 decimal
        )
      );
      const transaction = new Transaction().add(...transactionInstructions);
      const signature = await configureAndSendCurrentTransaction(
        transaction,
        connection,
        publicKey,
        signTransaction
      );
      // signature is transaction address, you can confirm your transaction on 'https://explorer.solana.com/?cluster=devnet'
    } catch (error) {}
  };

  return <button onClick={handlePayment}>Transfer spl token</button>;
};

export default SendSolanaSplTokens;
票数 2
EN
查看全部 5 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70224185

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档