0

I'm building a website where people log in to their phantom wallet then by clicking on a button they will send a certain amount of our custom token to one wallet.

The code shown below is working with SOL and I would like to make it work with our custom SPL token, I have the mint address of the token but I couldn't find any way to make it work. Could anyone help me?

async function transferSOL(toSend) {
            // Detecing and storing the phantom wallet of the user (creator in this case)
            var provider = await getProvider();
            console.log("Public key of the emitter: ",provider.publicKey.toString());
        
            // Establishing connection
            var connection = new web3.Connection(
                "https://api.mainnet-beta.solana.com/"
            );
        
            // I have hardcoded my secondary wallet address here. You can take this address either from user input or your DB or wherever
            var recieverWallet = new web3.PublicKey("address of the wallet recieving the custom SPL Token");
        
            var transaction = new web3.Transaction().add(
                web3.SystemProgram.transfer({
                fromPubkey: provider.publicKey,
                toPubkey: recieverWallet,
                lamports: (web3.LAMPORTS_PER_SOL)*toSend //Investing 1 SOL. Remember 1 Lamport = 10^-9 SOL.
                }),
            );
        
            // Setting the variables for the transaction
            transaction.feePayer = await provider.publicKey;
            let blockhashObj = await connection.getRecentBlockhash();
            transaction.recentBlockhash = await blockhashObj.blockhash;
        

            // Request creator to sign the transaction (allow the transaction)
            let signed = await provider.signTransaction(transaction);
            // The signature is generated
            let signature = await connection.sendRawTransaction(signed.serialize());
            // Confirm whether the transaction went through or not
            console.log(await connection.confirmTransaction(signature));
            
            //Signature chhap diya idhar
            console.log("Signature: ", signature);
        }

I'd like to specify that people will use phantom and I cant have access to their private keys (cause it was needed in all the answers I found on internet)

TylerH
  • 20,799
  • 66
  • 75
  • 101
Jerowd
  • 1
  • 1

2 Answers2

0

You're very close! You just need to replace the web3.SystemProgram.transfer instruction with an instruction to transfer SPL tokens, referencing the proper accounts. There's an example at the Solana Cookbook covering this exactly situation: https://solanacookbook.com/references/token.html#transfer-token

Jon C
  • 7,019
  • 10
  • 17
  • Sorry i'm kind of a noob, when I try to use the Token.createTransferCheckedInstruction() i get an error saying that it doesnt exist on type 'typeof Token'. One other question : the 2 variables "tokenAccountPubkey are obtained thanks to which function? Thanks in advance – Jerowd Jan 31 '22 at 16:51
  • If you click on the `>` icon, it'll give you the full snippet of code, including the additional modules that you need. As for the other variables, you'll need source and destination token accounts in order to do a transfer. Typically, you should use the "associated token account" for that. There's another great example at the cookbook doing that: https://solanacookbook.com/references/token.html#associated-token-account-ata – Jon C Jan 31 '22 at 17:36
  • I did all the import but nothing changed for the problem said above, it just looks like i might have imported the wrong "Token" or that it ain't up to date? I don't know tbh... I searched but couldn't find anymore information. Thanks anyway – Jerowd Jan 31 '22 at 18:51
  • did you `npm install @solana/spl-token`? – Jon C Jan 31 '22 at 19:49
0

You can do this with help of anchor and spl-token, which is used for dealing with custom tokens on solana. This is a custom transfer function. You'll need the mint address of the token, wallet from which the tokens will be taken( which you get in front end when user connects wallet. Can make use of solana-web3), to address and amount.

import * as splToken from "@solana/spl-token";
import { web3, Wallet } from "@project-serum/anchor";
           
async function transfer(tokenMintAddress: string, wallet: Wallet, to: string, connection: web3.Connection, amount: number) {
        
             const mintPublicKey = new web3.PublicKey(tokenMintAddress);  
             const {TOKEN_PROGRAM_ID} = splToken
            
             const fromTokenAccount = await splToken.getOrCreateAssociatedTokenAccount(
                connection,
                wallet.payer,
                mintPublicKey,
                wallet.publicKey
              );
            
              const destPublicKey = new web3.PublicKey(to);
            
              // Get the derived address of the destination wallet which will hold the custom token
              const associatedDestinationTokenAddr = await splToken.getOrCreateAssociatedTokenAccount(
                connection,
                wallet.payer,
                mintPublicKey,
                destPublicKey
              );
             
            
              const receiverAccount = await connection.getAccountInfo(associatedDestinationTokenAddr.address);
                    
              const instructions: web3.TransactionInstruction[] = [];  
            
              
              instructions.push(
                splToken.createTransferInstruction(
                  fromTokenAccount.address,
                  associatedDestinationTokenAddr.address,
                  wallet.publicKey,
                  amount,
                  [],
                  TOKEN_PROGRAM_ID
                )
              );
            
              const transaction = new web3.Transaction().add(...instructions);
              transaction.feePayer = wallet.publicKey;
              transaction.recentBlockhash = (await connection.getRecentBlockhash()).blockhash;
              
              const transactionSignature = await connection.sendRawTransaction(
                transaction.serialize(),
                { skipPreflight: true }
              );
            
              await connection.confirmTransaction(transactionSignature);
            }
Sanjay
  • 551
  • 6
  • 14