> ## 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.

# Deposit

> Deposit assets as collateral or liquidity

Deposit assets as collateral or supply liquidity into Kamino lending reserves. The SDK handles transaction building, instruction creation, and obligation management for deposit operations.

## Deposit for Lending

Supply liquidity to the reserve and earn interest.

<Tabs>
  <Tab title="TypeScript">
    <Steps>
      <Step>
        ### Import Dependencies

        Import the required packages for Solana RPC communication, Kamino SDK operations, and Kit transaction building.

        ```typescript theme={null}
        import {
          createSolanaRpc,
          createSolanaRpcSubscriptions,
          address,
          pipe,
          createTransactionMessage,
          setTransactionMessageFeePayerSigner,
          setTransactionMessageLifetimeUsingBlockhash,
          appendTransactionMessageInstructions,
          signTransactionMessageWithSigners,
          sendAndConfirmTransactionFactory,
          getSignatureFromTransaction,
          type Signature,
        } from '@solana/kit';
        import {
          KaminoMarket,
          KaminoAction,
          LendingObligation
        } from '@kamino-finance/klend-sdk';
        import { parseKeypairFile } from '@kamino-finance/klend-sdk/dist/utils/signer.js';
        import BN from 'bn.js';
        ```

        <Note>
          `@solana/kit` provides modern utilities for RPC, transaction building, and signing. `@kamino-finance/klend-sdk` contains market operation methods.
        </Note>
      </Step>

      <Step>
        ### Load Market and Initialize RPC

        Load the keypair, initialize RPC connections, and load the Kamino market.

        ```typescript theme={null}
        const KEYPAIR_FILE = '/path/to/your/keypair.json';
        const signer = await parseKeypairFile(KEYPAIR_FILE);

        const rpc = createSolanaRpc('https://api.mainnet-beta.solana.com');
        const rpcSubscriptions = createSolanaRpcSubscriptions('wss://api.mainnet-beta.solana.com');

        const marketPubkey = address('DxXdAyU3kCjnyggvHmY5nAwg5cRbbmdyX3npfDMjjMek');
        const market = await KaminoMarket.load(rpc, marketPubkey, 400);
        ```

        <Note>
          `KaminoMarket.load()` fetches the current market state including all reserve data and configuration.
        </Note>
      </Step>

      <Step>
        ### Build Deposit Instructions

        Generate deposit reserve liquidity instructions for the specified token and amount.

        ```typescript theme={null}
        const usdcMint = address('EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v');
        const depositAmount = new BN(1_000_000); // 1 USDC (6 decimals)

        const obligation = new LendingObligation(usdcMint, market!.programId, 0);

        const action = await KaminoAction.buildDepositReserveLiquidityTxns(
          market!,
          depositAmount,
          usdcMint,
          signer,
          obligation,
          undefined
        );
        ```

        <Info>
          `buildDepositReserveLiquidityTxns` creates a lending obligation for earning interest on deposited assets. The obligation parameter specifies the deposit configuration.
        </Info>
      </Step>

      <Step>
        ### Send Setup Transaction (If Needed)

        If setup instructions are present, send the setup transaction first and wait for confirmation.

        ```typescript theme={null}
        let setupSignature: Signature | undefined;

        if (action.setupIxs && action.setupIxs.length > 0) {
          const { value: setupBlockhash } = await rpc
            .getLatestBlockhash({ commitment: 'finalized' })
            .send();

          const setupTxMessage = pipe(
            createTransactionMessage({ version: 0 }),
            (tx) => setTransactionMessageFeePayerSigner(signer, tx),
            (tx) => setTransactionMessageLifetimeUsingBlockhash(setupBlockhash, tx),
            (tx) => appendTransactionMessageInstructions(action.setupIxs, tx)
          );

          const setupSignedTx = await signTransactionMessageWithSigners(setupTxMessage);
          setupSignature = getSignatureFromTransaction(setupSignedTx);

          await sendAndConfirmTransactionFactory({ rpc, rpcSubscriptions })(setupSignedTx, {
            commitment: 'confirmed',
            skipPreflight: true,
          });

          await new Promise((resolve) => setTimeout(resolve, 2000));
        }
        ```

        <Warning>
          Setup transactions must be confirmed and Address Lookup Tables (ALTs) must be activated before sending the main deposit transaction. Waiting 2 seconds ensures account settlement.
        </Warning>
      </Step>

      <Step>
        ### Build and Send Deposit Transaction

        Gather all instructions from the action.

        ```typescript theme={null}
        const lendingInstructions = [
          ...action.computeBudgetIxs,
          ...action.lendingIxs,
          ...action.cleanupIxs,
        ];

        if (!lendingInstructions.length) {
          throw new Error('No instructions returned by Kamino SDK');
        }
        ```

        Fetch the latest blockhash and construct the transaction message.

        ```typescript theme={null}
        const { value: latestBlockhash } = await rpc
          .getLatestBlockhash({ commitment: 'finalized' })
          .send();

        const transactionMessage = pipe(
          createTransactionMessage({ version: 0 }),
          (tx) => setTransactionMessageFeePayerSigner(signer, tx),
          (tx) => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, tx),
          (tx) => appendTransactionMessageInstructions(lendingInstructions, tx)
        );
        ```

        <Note>
          A fresh blockhash is fetched for the main transaction to ensure it remains valid after the setup transaction completes.
        </Note>

        Sign and send the transaction.

        ```typescript theme={null}
        const signedTransaction = await signTransactionMessageWithSigners(transactionMessage);

        const signature = getSignatureFromTransaction(signedTransaction);

        await sendAndConfirmTransactionFactory({ rpc, rpcSubscriptions })(signedTransaction, {
          commitment: 'confirmed',
          skipPreflight: true,
        });

        console.log(
          `Deposit successful! Signature: ${signature}${
            setupSignature ? `\nSetup transaction: https://solscan.io/tx/${setupSignature}` : ''
          }`
        );
        ```

        <Check>
          The deposit is complete. The assets are now supplied to the reserve and earning interest.
        </Check>
      </Step>
    </Steps>
  </Tab>

  <Tab title="Rust">
    <Info>
      `klend-interface` is a lightweight Rust instruction builder — it creates `Vec<Instruction>` with required refresh instructions prepended automatically. Use `ReserveInfo::from_account_data(pubkey, &data)` to construct reserve info from raw RPC account bytes. For obligation-based operations, `ObligationContext` is the recommended approach — it fetches the obligation and its associated reserves, then provides convenient `.deposit()`, `.borrow()`, `.repay()`, and `.withdraw()` methods.
    </Info>

    <Steps>
      <Step>
        ### Add Dependencies

        ```toml theme={null}
        [dependencies]
        klend-interface = "0.1.0"
        solana-pubkey = "2.1"
        solana-instruction = "2.1"
        solana-sdk = "~2.3"
        solana-client = "~2.3"
        spl-token = "7"
        spl-associated-token-account = "6"
        ```
      </Step>

      <Step>
        ### Set Up RPC Client

        ```rust theme={null}
        use solana_client::rpc_client::RpcClient;
        use solana_sdk::signer::keypair::read_keypair_file;
        use solana_sdk::signer::Signer;

        let rpc_client = RpcClient::new("https://api.mainnet-beta.solana.com");
        let signer = read_keypair_file("/path/to/your/keypair.json")
            .expect("Failed to read keypair file");
        let owner = signer.pubkey();
        ```
      </Step>

      <Step>
        ### Fetch Reserve Data

        Fetch the reserve account from the chain and construct `ReserveInfo` from its raw bytes.

        ```rust theme={null}
        use klend_interface::helpers;
        use klend_interface::ReserveInfo;
        use klend_interface::pda;
        use klend_interface::KLEND_PROGRAM_ID;
        use solana_pubkey::Pubkey;
        use std::str::FromStr;

        let reserve_pubkey = Pubkey::from_str("D6q6wuQSrifJKZYpR1M8R4YawnLDtDsMmWM1NbBmgJ59").unwrap();

        let reserve_data = rpc_client.get_account(&reserve_pubkey)?;
        let reserve = ReserveInfo::from_account_data(reserve_pubkey, &reserve_data.data)?;
        ```
      </Step>

      <Step>
        ### Derive Token Accounts

        Derive the user's associated token accounts for the liquidity mint and collateral mint.

        ```rust theme={null}
        use spl_associated_token_account::get_associated_token_address;

        // User's ATA for the deposit token (e.g. USDC)
        let user_source_liquidity = get_associated_token_address(&owner, &reserve.liquidity_mint);

        // Derive the collateral mint PDA, then the user's ATA for it
        let (collateral_mint, _) = pda::reserve_collateral_mint(&KLEND_PROGRAM_ID, &reserve_pubkey);
        let user_destination_collateral = get_associated_token_address(&owner, &collateral_mint);
        ```
      </Step>

      <Step>
        ### Build Instructions

        ```rust theme={null}
        let instructions = helpers::deposit::deposit(
            owner,
            &reserve,
            user_source_liquidity,       // user's USDC token account
            user_destination_collateral, // user's cToken account
            1_000_000,                   // 1 USDC (6 decimals)
        );
        // Returns: [refresh_reserve, deposit_reserve_liquidity]
        ```
      </Step>

      <Step>
        ### Build and Send Transaction

        ```rust theme={null}
        use solana_sdk::transaction::Transaction;
        use solana_sdk::message::Message;

        let message = Message::new(&instructions, Some(&owner));
        let recent_blockhash = rpc_client.get_latest_blockhash()?;
        let tx = Transaction::new(&[&signer], message, recent_blockhash);
        let signature = rpc_client.send_and_confirm_transaction(&tx)?;
        println!("Deposit successful! Signature: {signature}");
        ```
      </Step>
    </Steps>

    <a href="https://github.com/Kamino-Finance/klend/blob/master/libs/klend-interface/examples/deposit_lending.rs" target="_blank" rel="noopener noreferrer" class="github-link">
      <Icon icon="github" iconType="brands" size={16} />

      <span>View Code</span>
    </a>
  </Tab>
</Tabs>

## Deposit for Borrowing

Deposit USDC as collateral to borrow other assets.

<Tabs>
  <Tab title="TypeScript">
    <Steps>
      <Step>
        ### Import Dependencies

        Import the required packages for Solana RPC communication, Kamino SDK operations, and Kit transaction building.

        ```typescript theme={null}
        import {
          createSolanaRpc,
          createSolanaRpcSubscriptions,
          address,
          pipe,
          createTransactionMessage,
          setTransactionMessageFeePayerSigner,
          setTransactionMessageLifetimeUsingBlockhash,
          appendTransactionMessageInstructions,
          signTransactionMessageWithSigners,
          sendAndConfirmTransactionFactory,
          getSignatureFromTransaction,
        } from '@solana/kit';
        import {
          KaminoMarket,
          KaminoAction,
          VanillaObligation,
          PROGRAM_ID
        } from '@kamino-finance/klend-sdk';
        import { parseKeypairFile } from '@kamino-finance/klend-sdk/dist/utils/signer.js';
        import BN from 'bn.js';
        ```
      </Step>

      <Step>
        ### Load Market and Initialize RPC

        Load the keypair, initialize RPC connections, and load the Kamino market.

        ```typescript theme={null}
        const KEYPAIR_FILE = '/path/to/your/keypair.json';
        const signer = await parseKeypairFile(KEYPAIR_FILE);

        const rpc = createSolanaRpc('https://api.mainnet-beta.solana.com');
        const rpcSubscriptions = createSolanaRpcSubscriptions('wss://api.mainnet-beta.solana.com');

        const marketPubkey = address('7u3HeHxYDLhnCoErrtycNokbQYbWGzLs6JSDqGAv5PfF');
        const market = await KaminoMarket.load(rpc, marketPubkey, 400);
        ```
      </Step>

      <Step>
        ### Build Deposit Instructions

        Build deposit instructions for depositing collateral to enable borrowing.

        ```typescript theme={null}
        const usdcMint = address('EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v');
        const depositAmount = new BN(3_000_000); // 3 USDC (6 decimals)

        const signatures: string[] = [];

        let depositAction = await KaminoAction.buildDepositTxns(
          market!,
          depositAmount,
          usdcMint,
          signer,
          new VanillaObligation(PROGRAM_ID),
          true,
          undefined,
          1_000_000,
          true,
          false,
          { skipInitialization: false, skipLutCreation: false }
        );

        const hasSetup = (depositAction.setupIxs || []).length > 0;

        let instructions = [
          ...(depositAction.setupIxs || []),
          ...(depositAction.lendingIxs || []),
          ...(depositAction.cleanupIxs || []),
        ];
        ```
      </Step>

      <Step>
        ### Send Initial Transaction

        Fetch the latest blockhash and build the transaction message.

        ```typescript theme={null}
        try {
          const { value: depositBlockhash } = await rpc
            .getLatestBlockhash({ commitment: 'finalized' })
            .send();

          const depositTx = pipe(
            createTransactionMessage({ version: 0 }),
            (tx) => setTransactionMessageFeePayerSigner(signer, tx),
            (tx) => setTransactionMessageLifetimeUsingBlockhash(depositBlockhash, tx),
            (tx) => appendTransactionMessageInstructions(instructions, tx)
          );
        ```

        Sign and send the transaction.

        ```typescript theme={null}
          const depositSigned = await signTransactionMessageWithSigners(depositTx);
          const depositSignature = getSignatureFromTransaction(depositSigned);
          signatures.push(depositSignature);

          await sendAndConfirmTransactionFactory({ rpc, rpcSubscriptions })(depositSigned, {
            commitment: 'confirmed',
            skipPreflight: true,
          });

          console.log(`Deposit successful! Signature: ${depositSignature}`);
        ```
      </Step>

      <Step>
        ### Handle Retry Logic

        Detect and handle setup-related errors that may occur.

        ```typescript theme={null}
        } catch (error: any) {
          const errorMsg = error?.message || error?.toString() || '';
          const is0x17a3 =
            errorMsg.includes('0x17a3') ||
            errorMsg.includes('6051') ||
            errorMsg.includes('IncorrectInstructionInPosition');

          if (hasSetup && is0x17a3) {
        ```

        <Warning>
          When setup instructions are included, the first transaction may fail with error 0x17a3. The retry logic handles this by waiting for blockchain state to settle, reloading the market, and rebuilding instructions.
        </Warning>

        Wait for blockchain state to settle and reload the market.

        ```typescript theme={null}
            await new Promise((resolve) => setTimeout(resolve, 2000));

            const reloadedMarket = await KaminoMarket.load(rpc, marketPubkey, 400);
        ```

        Rebuild the deposit instructions with the reloaded market state.

        ```typescript theme={null}
            depositAction = await KaminoAction.buildDepositTxns(
              reloadedMarket!,
              depositAmount,
              usdcMint,
              signer,
              new VanillaObligation(PROGRAM_ID),
              true,
              undefined,
              1_000_000,
              true,
              false,
              { skipInitialization: false, skipLutCreation: false }
            );

            instructions = [
              ...(depositAction.setupIxs || []),
              ...(depositAction.lendingIxs || []),
              ...(depositAction.cleanupIxs || []),
            ];
        ```

        Fetch a fresh blockhash and build the retry transaction.

        ```typescript theme={null}
            const { value: retryBlockhash } = await rpc
              .getLatestBlockhash({ commitment: 'finalized' })
              .send();

            const retryTx = pipe(
              createTransactionMessage({ version: 0 }),
              (tx) => setTransactionMessageFeePayerSigner(signer, tx),
              (tx) => setTransactionMessageLifetimeUsingBlockhash(retryBlockhash, tx),
              (tx) => appendTransactionMessageInstructions(instructions, tx)
            );
        ```

        Sign and send the retry transaction.

        ```typescript theme={null}
            const retrySigned = await signTransactionMessageWithSigners(retryTx);
            const retrySignature = getSignatureFromTransaction(retrySigned);
            signatures.push(retrySignature);

            await sendAndConfirmTransactionFactory({ rpc, rpcSubscriptions })(retrySigned, {
              commitment: 'confirmed',
              skipPreflight: true,
            });

            console.log(
              `Deposit successful! Signature: ${retrySignature}\nSetup transaction: https://solscan.io/tx/${signatures[0]}`
            );
          } else {
            console.error('Deposit failed:', error);
          }
        }
        ```

        <Check>
          The deposit is complete. The collateral is now deposited and can be used for borrowing other assets.
        </Check>
      </Step>
    </Steps>
  </Tab>

  <Tab title="Rust">
    <Info>
      `klend-interface` is a lightweight Rust instruction builder — it creates `Vec<Instruction>` with required refresh instructions prepended automatically. Use `ReserveInfo::from_account_data(pubkey, &data)` to construct reserve info from raw RPC account bytes. For obligation-based operations, `ObligationContext` is the recommended approach — it fetches the obligation and its associated reserves, then provides convenient `.deposit()`, `.borrow()`, `.repay()`, and `.withdraw()` methods.
    </Info>

    <Steps>
      <Step>
        ### Add Dependencies

        ```toml theme={null}
        [dependencies]
        klend-interface = "0.1.0"
        solana-pubkey = "2.1"
        solana-instruction = "2.1"
        solana-sdk = "~2.3"
        solana-client = "~2.3"
        spl-token = "7"
        spl-associated-token-account = "6"
        ```
      </Step>

      <Step>
        ### Set Up RPC Client

        ```rust theme={null}
        use solana_client::rpc_client::RpcClient;
        use solana_sdk::signer::keypair::read_keypair_file;
        use solana_sdk::signer::Signer;

        let rpc_client = RpcClient::new("https://api.mainnet-beta.solana.com");
        let signer = read_keypair_file("/path/to/your/keypair.json")
            .expect("Failed to read keypair file");
        let owner = signer.pubkey();
        ```
      </Step>

      <Step>
        ### Build Obligation Context

        Derive the obligation PDA, fetch its account data along with all associated reserves, and build an `ObligationContext`.

        ```rust theme={null}
        use klend_interface::ObligationContext;
        use klend_interface::pda;
        use klend_interface::KLEND_PROGRAM_ID;
        use solana_pubkey::Pubkey;
        use std::str::FromStr;

        let lending_market = Pubkey::from_str("7u3HeHxYDLhnCoErrtycNokbQYbWGzLs6JSDqGAv5PfF").unwrap();
        let reserve_pubkey = Pubkey::from_str("D6q6wuQSrifJKZYpR1M8R4YawnLDtDsMmWM1NbBmgJ59").unwrap();

        // Derive the obligation PDA
        let (obligation_pubkey, _) = pda::obligation(
            &KLEND_PROGRAM_ID, 0, 0, &owner, &lending_market,
            &Pubkey::default(), &Pubkey::default(),
        );

        // Fetch the obligation account
        let obligation_data = rpc_client.get_account(&obligation_pubkey)?;

        // Discover which reserves the obligation references
        let reserve_addrs = ObligationContext::reserve_addresses_for_obligation(&obligation_data.data)?;

        // Fetch all reserve accounts in one RPC call
        let reserve_accounts = rpc_client.get_multiple_accounts(&reserve_addrs)?;

        // Build the context
        let reserves: Vec<(Pubkey, &[u8])> = reserve_addrs.iter()
            .zip(reserve_accounts.iter())
            .filter_map(|(addr, acc)| acc.as_ref().map(|a| (*addr, a.data.as_slice())))
            .collect();
        let ctx = ObligationContext::from_account_data(
            obligation_pubkey, &obligation_data.data, &reserves
        )?;
        ```
      </Step>

      <Step>
        ### Derive Token Accounts

        ```rust theme={null}
        use spl_associated_token_account::get_associated_token_address;

        // User's ATA for the deposit token (e.g. USDC)
        let liquidity_mint = Pubkey::from_str("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v").unwrap();
        let user_source_liquidity = get_associated_token_address(&owner, &liquidity_mint);
        ```
      </Step>

      <Step>
        ### Build Instructions

        ```rust theme={null}
        let instructions = ctx.deposit(
            owner,
            &reserve_pubkey,
            user_source_liquidity,
            3_000_000, // 3 USDC (6 decimals)
        )?;
        // Returns: [refresh_reserves..., refresh_obligation, deposit_and_collateral_v2]
        ```
      </Step>

      <Step>
        ### Build and Send Transaction

        ```rust theme={null}
        use solana_sdk::transaction::Transaction;
        use solana_sdk::message::Message;

        let message = Message::new(&instructions, Some(&owner));
        let recent_blockhash = rpc_client.get_latest_blockhash()?;
        let tx = Transaction::new(&[&signer], message, recent_blockhash);
        let signature = rpc_client.send_and_confirm_transaction(&tx)?;
        println!("Deposit successful! Signature: {signature}");
        ```
      </Step>
    </Steps>

    <a href="https://github.com/Kamino-Finance/klend/blob/master/libs/klend-interface/examples/deposit_borrowing.rs" target="_blank" rel="noopener noreferrer" class="github-link">
      <Icon icon="github" iconType="brands" size={16} />

      <span>View Code</span>
    </a>
  </Tab>
</Tabs>
