Search code examples
rustsolana

Solana how to stake native SOL to a Rust program and withdraw SOL from a program?


I have Googled about this and only found how to send tokens via command line:

https://spl.solana.com/token

But I need to stake/withdraw Native SOL, not tokens, into/from Rust programs.

Also I found this about Rust native token:

https://docs.rs/solana-program/1.7.10/solana_program/native_token/index.html

https://docs.rs/solana-program/1.7.10/solana_program/native_token/struct.Sol.html

It seems I have to declare this Sol struct

pub struct Sol(pub u64);

Then use its "send" trait to send it... right? Could somebody explain how to do this via Rust programs?


Solution

  • You can wrap Sol into a wrapped sol Token via the SPL Token program. From there you can use the Wrapped SOL like any SPL Token. Here is a pretty good example

    https://github.com/project-serum/serum-dex-ui/blob/5b4487634e3738c57ace6da1377704e95f53c588/src/pages/pools/PoolPage/PoolAdminPanel.tsx#L250-L272

    const wrappedSolAccount = new Account();
    
    transaction.add(
      SystemProgram.createAccount({
        fromPubkey: wallet.publicKey,
        lamports: parsedQuantity + 2.04e6,
        newAccountPubkey: wrappedSolAccount.publicKey,
        programId: TokenInstructions.TOKEN_PROGRAM_ID,
        space: 165,
      }),
      TokenInstructions.initializeAccount({
        account: wrappedSolAccount.publicKey,
        mint: TokenInstructions.WRAPPED_SOL_MINT,
        owner: wallet.publicKey,
      }),
      TokenInstructions.transfer({
        source: wrappedSolAccount.publicKey,
        destination: vaultAddress,
        amount: parsedQuantity,
        owner: wallet.publicKey,
      }),
      TokenInstructions.closeAccount({
        source: wrappedSolAccount.publicKey,
        destination: walletTokenAccount.pubkey,
        owner: wallet.publicKey,
      }),
    );
    

    So essentially what it's doing here is

    1. Create a random account where you can deposit some SOL into and deposit the amount required plus the rent amount (hence parsedQuantity + 2.04e6)
    2. Use the token program to initialise the account as a WRAPPED_SOL_ACCOUNT
    3. Transfer the wrapped SOL (or in your case, you may just want to call the program and put the wrapped SOL account as a parameter)
    4. Close the Wrapped SOL account so that the user gets back their rent