> ## Documentation Index
> Fetch the complete documentation index at: https://kamino.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Withdraw to Privy Wallet and Check Balance

> Use a Privy-managed wallet to perform secure Earn withdrawals and check USDC balance

Withdraw from Kamino Earn vaults using Privy embedded wallets and check the resulting USDC balance. This integration allows users to withdraw without managing their own private keys.

## Earn Withdraw to Privy

<Steps>
  <Step>
    ### Import Dependencies

    Import the required packages for Privy client, Solana RPC communication, and Kamino SDK operations.

    ```typescript theme={null}
    import { PrivyClient } from '@privy-io/node';
    import {
      createSolanaRpc,
      address,
      pipe,
      createNoopSigner,
      createTransactionMessage,
      setTransactionMessageFeePayerSigner,
      setTransactionMessageLifetimeUsingBlockhash,
      appendTransactionMessageInstructions,
      compileTransaction,
      getBase64EncodedWireTransaction,
    } from '@solana/kit';
    import { KaminoVault } from '@kamino-finance/klend-sdk';
    import { Decimal } from 'decimal.js';
    ```
  </Step>

  <Step>
    ### Configure Privy and Initialize Client

    Set up your Privy credentials and initialize the Privy client and RPC connection.

    ```typescript theme={null}
    const PRIVY_APP_ID = 'your-privy-app-id';
    const PRIVY_APP_SECRET = 'your-privy-app-secret';
    const RPC_ENDPOINT = 'https://api.mainnet-beta.solana.com';
    const VAULT_ADDRESS = 'HDsayqAsDWy3QvANGqh2yNraqcD8Fnjgh73Mhb3WRS5E'; // Steakhouse USDC vault
    const AUTH_KEY_PRIVATE = 'your-auth-key-private';
    const WALLET_ID = 'your-wallet-id';

    const privy = new PrivyClient({
      appId: PRIVY_APP_ID,
      appSecret: PRIVY_APP_SECRET,
    });

    const rpc = createSolanaRpc(RPC_ENDPOINT);
    ```
  </Step>

  <Step>
    ### Get Wallet and Initialize Vault

    Retrieve the Privy wallet and initialize the Kamino vault instance.

    ```typescript theme={null}
    const wallet = await privy.wallets().get(WALLET_ID);
    const walletAddress = wallet.address;

    const vault = new KaminoVault(rpc, address(VAULT_ADDRESS));
    await vault.getState();
    ```
  </Step>

  <Step>
    ### Check User Shares

    Query the user's vault shares to determine how much can be withdrawn.

    ```typescript theme={null}
    const userShares = await vault.getUserShares(address(walletAddress));
    console.log(
      `Vault shares: ${userShares.unstakedShares?.toString() || '0'} unstaked, ${
        userShares.stakedShares?.toString() || '0'
      } staked`
    );

    const totalShares = parseFloat(userShares.totalShares?.toString() || '0');

    if (totalShares === 0) throw new Error('No shares to withdraw');
    ```

    <Info>
      The total shares represent the user's position in the vault. Both staked and unstaked shares are included in the withdrawal.
    </Info>
  </Step>

  <Step>
    ### Build Withdrawal Instructions

    Generate withdrawal instructions for all user shares using a noop signer.

    ```typescript theme={null}
    const noopSigner = createNoopSigner(address(walletAddress));
    const withdrawAmount = new Decimal(totalShares);

    const bundle = await vault.withdrawIxs(noopSigner, withdrawAmount);
    const withdrawInstructions = [...(bundle.withdrawIxs || [])];

    if (!withdrawInstructions.length) throw new Error('No withdrawal instructions returned');
    ```

    <Note>
      A noop signer is used to build instructions without requiring the actual private key. Privy will handle signing later.
    </Note>
  </Step>

  <Step>
    ### Build Transaction Message

    Fetch the latest blockhash and construct the withdrawal transaction message.

    ```typescript theme={null}
    const { value: withdrawBlockhash } = await rpc.getLatestBlockhash({ commitment: 'finalized' }).send();
    const withdrawTxMessage = pipe(
      createTransactionMessage({ version: 0 }),
      (tx) => setTransactionMessageFeePayerSigner(noopSigner, tx),
      (tx) => setTransactionMessageLifetimeUsingBlockhash(withdrawBlockhash, tx),
      (tx) => appendTransactionMessageInstructions(withdrawInstructions, tx)
    );
    ```
  </Step>

  <Step>
    ### Sign Transaction with Privy

    Compile the transaction, serialize it, and sign using Privy's wallet API.

    ```typescript theme={null}
    const compiledWithdrawTx = compileTransaction(withdrawTxMessage);
    const serializedWithdrawTx = getBase64EncodedWireTransaction(compiledWithdrawTx);

    const withdrawSignResponse = await privy
      .wallets()
      .solana()
      .signTransaction(WALLET_ID, {
        transaction: serializedWithdrawTx,
        authorization_context: { authorization_private_keys: [AUTH_KEY_PRIVATE] },
      });
    ```

    <Note>
      Privy handles the signing securely using the embedded wallet. The private key never leaves Privy's infrastructure.
    </Note>
  </Step>

  <Step>
    ### Send Transaction

    Submit the signed transaction to the Solana network.

    ```typescript theme={null}
    const withdrawSig = await rpc
      .sendTransaction(withdrawSignResponse.signed_transaction as any, {
        encoding: 'base64',
        skipPreflight: true,
      })
      .send();

    console.log('Withdrawal successful! Signature:', withdrawSig);
    ```
  </Step>

  <Step>
    ### Check USDC Balance

    Query the wallet's USDC balance using Privy's balance API.

    ```typescript theme={null}
    const balance = await privy.wallets().balance.get(WALLET_ID, {
      asset: 'usdc',
      chain: 'solana',
    });
    const usdcBalance = balance.balances[0];
    console.log(`USDC Balance: ${usdcBalance.display_values.usdc}`);
    ```

    <Check>
      Your withdrawal is complete! The user's vault shares have been redeemed for USDC, and the balance is now available in their Privy wallet.
    </Check>
  </Step>
</Steps>
