Search code examples
c#.netblockchainsolana

Concept of Token Program & Associated Token Account Program


I'm trying to send a token [USDT] from one wallet to another. But I think I'm having some trouble understanding the concept of Associated Token Account [ATA]

According to my understanding:

1 - Every wallet account that wants to keep, receive or send tokens, must register in the account for these tokens in the network?

2 - The sending person can register the account of the receiving person

3- Are these concepts correct?

All of the above are done by the following instructions => AssociatedTokenAccountProgram.CreateAssociatedTokenAccount

4 - Once the recipient's wallet address is registered, can send the tokens to him via instructions => TokenProgram.Transfer

  Account ownerAccount = wallet.Account;
  PublicKey UsdtAddress = new PublicKey("Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB");
  PublicKey ToAddress = new PublicKey("CDQ3Gya9QermsPzU3cTNW9QPLbMVLbALQ2S8AwbruVJ");

  var Transaction = new TransactionBuilder().
             SetRecentBlockHash(blockHash.Result.Value.Blockhash).
             SetFeePayer(wallet.Account).

             AddInstruction(AssociatedTokenAccountProgram.CreateAssociatedTokenAccount(
             ownerAccount, // Sender Account [Wallet Owner]   ?
             UsdtAddress,    // Tether Address On-Chain         ?
             ToAddress)).  // The Recipient Wallet Address    ?
             
             AddInstruction(TokenProgram.Transfer(
             ownerAccount,
             ToAddress,
             100,
             ownerAccount)).

             Build(new List<Account> { ownerAccount });

  var txReq = await rpcClient.SendTransactionAsync(Transaction);

I'm so sorry for the long wait, but after a lot of attempts, all of them were unsuccessful, I really think I need someone to explain how sending tokens works.


Solution

  • After a long struggle I was able to reach some results, I will leave this comment as a solution to the problem and an understanding of how things work, and if it contains some errors, please do not hesitate to leave an explanation and a correction for this

    Let's agree on some concepts first:

    1- Wallet account is a normal account, owned by the system Program and called [account owner]

    2- The person who owns the private key is known as the authority

    3 - Each token has an account on the chain, has its own owner and authority

    what is happening now ?

    If you want to own some of these tokens for the first time, you must create an account known as Associated Token Account

    Associated Token Account: It is simply an account within the network that associates each wallet with a special and unique address of a token!! Is this clear??

    Your wallet number => Associated Token Account <= token account number

    G1G2G3G4 => A1T2A3T4 <= USDTADDRESS243

    Its job is to save and store data for a specific wallet address with a specific token address, such as quantity, balance and many other features that I have not seen yet

    The first time you will send these tokens to an account that does not contain [ATA], you will build instructions to create [ATA] for this account, and attach instructions directly to send the tokens with the same transaction, this structure worked for me,

    enter image description here

    Finally: It is possible to know the Associated Token Account for a wallet simply, because we will need to send the tokens with the Associated Tokens and not the addresses of the main wallets

    Here is the code to create a Associated Token Account and send some USDT to the address:

        PublicKey UsdtAddress = new PublicKey("Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB");
    
        //The [ATA] for my public address in the USDT token account = Sender
        Account ownerAccount = wallet.Account;
        var FromAssociatedTokenAccount=AssociatedTokenAccountProgram.DeriveAssociatedTokenAccount(ownerAccount,UsdtAddress); 
    
        //The [ATA] for Receiver public address in the USDT token account = Sender = Receiver 
        PublicKey ToAddress = new PublicKey("DqiE6PDXPFMMDC2jzoqY45VEqyEzdGd5qauVCQY8s3A7");
        var ToAssociatedTokenAccount = AssociatedTokenAccountProgram.DeriveAssociatedTokenAccount(ToAddress, UsdtAddress);
        //Note that a ToAssociatedTokenAccount can be defined, with the possibility that it is not registered/created on-Chain
    
    
    
        var blockHash = await rpcClient.GetRecentBlockHashAsync();
        var Transaction = new TransactionBuilder().
                 SetRecentBlockHash(blockHash.Result.Value.Blockhash).
                 SetFeePayer(ownerAccount).
     AddInstruction(AssociatedTokenAccountProgram.CreateAssociatedTokenAccount(
                 ownerAccount,
                 ToAddress,
                 UsdtAddress)).
    
                 AddInstruction(TokenProgram.Transfer(
                 FromAssociatedTokenAccount,
                 ToAssociatedTokenAccount,
                 1,
                 ownerAccount)).
    
                 Build(new List<Account> { ownerAccount });
         var txReq = await rpcClient.SendTransactionAsync(Transaction);
    

    enter image description here

    So finally, please bring a cup of coffee and read this article, I think it is good to clarify some concepts about the Solana Blockchain : https://www.brianfriel.xyz/how-to-create-a-token-on-solana/