'Solana / web3.js : getting web3.Signer from wallet

I want to send a token from one wallet to another using web3.js and spl-token. To send it I have to create an object named Token, one of the parameters of the constructor of Token() is payer: web3.Signer.

    const mintPublicKey = new web3.PublicKey(this.props.nft.data.mint);  
    const mintToken = new Token(
      this.props.connection,
      mintPublicKey,
      TOKEN_PROGRAM_ID,
      //payer: web3.Signer,
    );

I get the information from the user's wallet using @solana/wallet-adapter-wallets. I know that web3.Signer is created from a private key, which cannot be obtained from a wallet for security purpose.

I actually don't know how to deals with wallet to get the transaction done.

Thanks a lot for your help, here is my full code :

import * as web3 from "@solana/web3.js";
import { getPhantomWallet } from "@solana/wallet-adapter-wallets";
import { Token, TOKEN_PROGRAM_ID } from "@solana/spl-token";


async sendNFT() {
  const wallet = getPhantomWallet();
  const adapter = wallet.adapter();

  await adapter.connect();
  if (adapter.connected && adapter.publicKey != null)
  {
    const mintPublicKey = new web3.PublicKey(this.props.nft.data.mint);  
    const mintToken = new Token(
      this.props.connection,
      mintPublicKey,
      TOKEN_PROGRAM_ID,
      //payer: web3.Signer
    );
          
    const fromTokenAccount = await mintToken.getOrCreateAssociatedAccountInfo(
      adapter.publicKey
    );

    const destPublicKey = new web3.PublicKey("example");

    const associatedDestinationTokenAddr = await Token.getAssociatedTokenAddress(
      mintToken.associatedProgramId,
      mintToken.programId,
      mintPublicKey,
      destPublicKey
    );

    const receiverAccount = await this.props.connection.getAccountInfo(associatedDestinationTokenAddr);
          
    const instructions: web3.TransactionInstruction[] = [];  

    if (receiverAccount === null) {

      instructions.push(
        Token.createAssociatedTokenAccountInstruction(
          mintToken.associatedProgramId,
          mintToken.programId,
          mintPublicKey,
          associatedDestinationTokenAddr,
          destPublicKey,
          adapter.publicKey
        )
      )

    }
    
    instructions.push(
      Token.createTransferInstruction(
        TOKEN_PROGRAM_ID,
        fromTokenAccount.address,
        associatedDestinationTokenAddr,
        adapter.publicKey,
        [],
        1000000
      )
    );

    const transaction = new web3.Transaction().add(...instructions);
    transaction.feePayer = adapter.publicKey;
    transaction.recentBlockhash = (await this.props.connection.getRecentBlockhash()).blockhash;
    
    const transactionSignature = await this.props.connection.sendRawTransaction(
      transaction.serialize(),
      { skipPreflight: true }
    );

    await this.props.connection.confirmTransaction(transactionSignature);
  }
}


Solution 1:[1]

I think the easiest way to do this is to create a provider and get the signer from there.


provider = new anchor.Provider(connection, wallet, anchor.Provider.defaultOptions());
    

and then you can send transactions by invoking provider.send(tx), which will also sign with your wallet if it requires signing.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 DaveTheAl