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

# User Obligation

## Manage User Obligations

Manage and retrieve user obligations, positions, and transaction history using the Kamino SDK and API.

<Note>Historical obligation data is only available via the API.</Note>

### Get User Obligation Info

Retrieve detailed obligation information including deposits, borrows, and health metrics.

<Tabs>
  <Tab title="TypeScript">
    ```typescript expandable title="getUserObligation.ts" theme={null}
    import { createSolanaRpc, address } from '@solana/kit';
    import { KaminoMarket, VanillaObligation, PROGRAM_ID } from '@kamino-finance/klend-sdk';

    const rpc = createSolanaRpc('https://api.mainnet-beta.solana.com');
    const marketPubkey = address('7u3HeHxYDLhnCoErrtycNokbQYbWGzLs6JSDqGAv5PfF');
    const userAddress = address('EZC9wzVCvihCsCHEMGADYdsRhcpdRYWzSCZAVegSCfqY');

    const market = await KaminoMarket.load(rpc, marketPubkey, 400, PROGRAM_ID);

    const kaminoObligation = await market!.getObligationByWallet(
    userAddress,
    new VanillaObligation(PROGRAM_ID)
    );

    if (!kaminoObligation) {
    console.log('No obligation found for user:', userAddress);
    } else {
    console.log('Obligation Info:');
    console.log('Owner:', kaminoObligation.state.owner.toString());

    console.log('\nDeposits (Collateral):');
    const deposits = [...kaminoObligation.deposits.values()];
    deposits.forEach((deposit) => {
      console.log(`Reserve:`, deposit.reserveAddress.toString());
      console.log(`    Amount:`, deposit.amount);
      console.log(`    Market Value:`, deposit.marketValueRefreshed);
    });

    console.log('\nBorrows:');
    const borrows = [...kaminoObligation.borrows.values()];
    borrows.forEach((borrow) => {
      console.log(`Reserve:`, borrow.reserveAddress.toString());
      console.log(`    Amount:`, borrow.amount);
    });

    console.log('\nMetrics:');
    console.log('Loan-to-Value:', kaminoObligation.loanToValue());
    console.log('Borrow Utilization:', kaminoObligation.refreshedStats.borrowUtilization);
    console.log('Number of Positions:', kaminoObligation.getNumberOfPositions());
    }

    ```

    <a target="_blank" rel="noopener noreferrer" class="github-link">
      <Icon icon="github" iconType="brands" size={16} />

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

  <Tab title="Rust">
    ```rust expandable title="get_user_obligation.rs" theme={null}
    // Additional deps: klend-interface = "0.1.0", solana-client = "~2.3",
    // solana-pubkey = "2.1", fixed = "1"
    use klend_interface::accounts::from_account_data;
    use klend_interface::state::Obligation;
    use klend_interface::pda;
    use klend_interface::KLEND_PROGRAM_ID;
    use solana_client::rpc_client::RpcClient;
    use solana_pubkey::Pubkey;
    use fixed::types::U68F60;
    use std::str::FromStr;

    let rpc_client = RpcClient::new("https://api.mainnet-beta.solana.com");
    let market_pubkey = Pubkey::from_str("7u3HeHxYDLhnCoErrtycNokbQYbWGzLs6JSDqGAv5PfF").unwrap();
    let user_pubkey = Pubkey::from_str("EZC9wzVCvihCsCHEMGADYdsRhcpdRYWzSCZAVegSCfqY").unwrap();

    // Derive the obligation PDA (tag 0 = Vanilla obligation)
    let (obligation_pubkey, _bump) = pda::obligation(
        &KLEND_PROGRAM_ID,
        0,
        0,
        &user_pubkey,
        &market_pubkey,
        &Pubkey::default(),
        &Pubkey::default(),
    );

    // Fetch and parse the obligation account
    let obligation_account = rpc_client.get_account(&obligation_pubkey)?;
    let obligation = from_account_data::<Obligation>(&obligation_account.data)?;
    println!("Obligation owner: {}", obligation.owner);

    // Active deposits
    println!("\nDeposits (Collateral):");
    for deposit in &obligation.deposits {
        if deposit.deposit_reserve == Pubkey::default() {
            continue;
        }
        println!("  Reserve: {}", deposit.deposit_reserve);
        println!("    Deposited amount (cTokens): {}", deposit.deposited_amount);
    }

    // Active borrows
    println!("\nBorrows:");
    for borrow in &obligation.borrows {
        if borrow.borrow_reserve == Pubkey::default() {
            continue;
        }
        println!("  Reserve: {}", borrow.borrow_reserve);
        println!("    Borrowed amount (sf): {}", borrow.borrowed_amount_sf);
    }

    // Health metrics — `_sf` fields use the `fixed` crate for precise conversion
    let deposited_value = U68F60::from_bits(obligation.deposited_value_sf as u128);
    let allowed_borrow = U68F60::from_bits(obligation.allowed_borrow_value_sf as u128);
    let unhealthy_borrow = U68F60::from_bits(obligation.unhealthy_borrow_value_sf as u128);
    let borrowed_value = U68F60::from_bits(obligation.borrow_factor_adjusted_debt_value_sf as u128);

    println!("\nMetrics:");
    println!("  Deposited value: ${deposited_value}");
    println!("  Allowed borrow value: ${allowed_borrow}");
    println!("  Unhealthy borrow value: ${unhealthy_borrow}");
    println!("  Current borrow value: ${borrowed_value}");
    println!("  Liquidatable: {}", borrowed_value > unhealthy_borrow);
    println!("  Borrowing disabled: {}", obligation.borrowing_disabled > 0);
    ```

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

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

### Get All User Obligations

Retrieve all obligations for a user wallet, including different obligation types across the market.

<Tabs>
  <Tab title="TypeScript">
    ```typescript expandable title="getAllUserObligations.ts" theme={null}
    import { createSolanaRpc, address } from '@solana/kit';
    import { KaminoMarket, PROGRAM_ID, ObligationTypeTag } from '@kamino-finance/klend-sdk';

    const rpc = createSolanaRpc('https://api.mainnet-beta.solana.com');
    const marketPubkey = address('7u3HeHxYDLhnCoErrtycNokbQYbWGzLs6JSDqGAv5PfF');
    const userWallet = address('Hs9ioQZ2pCUyvS18anwmBxjQJsZrMPShwTMLySD6Us3V');

    const market = await KaminoMarket.load(rpc, marketPubkey, 400, PROGRAM_ID);

    const obligations = await market.getAllUserObligations(userWallet);

    if (obligations.length === 0) {
    console.log('No obligations found for wallet:', userWallet);
    } else {
    console.log(`Found ${obligations.length} obligation(s):\n`);

    obligations.forEach((obligation, i) => {
      console.log(`Obligation ${i + 1}:`);
      console.log('Address:', obligation.obligationAddress.toString());
      console.log('Type:', ObligationTypeTag[obligation.obligationTag]);
      console.log('Owner:', obligation.state.owner.toString());

      console.log('\nDeposits (Collateral):');
      const deposits = [...obligation.deposits.values()];
      deposits.forEach((deposit) => {
        console.log(`  Reserve:`, deposit.reserveAddress.toString());
        console.log(`    Amount:`, deposit.amount);
        console.log(`    Market Value:`, deposit.marketValueRefreshed);
      });

      console.log('\nBorrows:');
      const borrows = [...obligation.borrows.values()];
      borrows.forEach((borrow) => {
        console.log(`  Reserve:`, borrow.reserveAddress.toString());
        console.log(`    Amount:`, borrow.amount);
        console.log(`    Market Value:`, borrow.marketValueRefreshed);
      });

      console.log('\nMetrics:');
      console.log('Loan-to-Value:', obligation.loanToValue());
      console.log('Borrow Utilization:', obligation.refreshedStats.borrowUtilization);
      console.log('Number of Positions:', obligation.getNumberOfPositions());
    });
    }

    ```

    <a target="_blank" rel="noopener noreferrer" class="github-link">
      <Icon icon="github" iconType="brands" size={16} />

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

### Get All Obligations by Reserve

Retrieve all obligations that have deposits in a specific reserve. Useful for analyzing reserve utilization and user exposure.

<Tabs>
  <Tab title="TypeScript">
    ```typescript expandable title="getAllObligationsByReserve.ts" theme={null}
    import { createSolanaRpc, address } from '@solana/kit';
    import { KaminoMarket, PROGRAM_ID, ObligationTypeTag } from '@kamino-finance/klend-sdk';

    // Note: This example requires a paid/dedicated RPC node. Public RPCs will hit rate limits.
    const rpc = createSolanaRpc('https://api.mainnet-beta.solana.com');
    const marketPubkey = address('7u3HeHxYDLhnCoErrtycNokbQYbWGzLs6JSDqGAv5PfF');
    const reserveAddress = address('37Jk2zkz23vkAYBT66HM2gaqJuNg2nYLsCreQAVt5MWK');

    const market = await KaminoMarket.load(rpc, marketPubkey, 400, PROGRAM_ID);

    const obligations = await market.getAllObligationsByDepositedReserve(reserveAddress);

    if (obligations.length === 0) {
    console.log('No obligations found with deposits in reserve:', reserveAddress);
    } else {
    console.log(`Found ${obligations.length} obligation(s) with deposits in this reserve:\n`);

    obligations.forEach((obligation, i) => {
      console.log(`Obligation ${i + 1}:`);
      console.log('Address:', obligation.obligationAddress.toString());
      console.log('Type:', ObligationTypeTag[obligation.obligationTag]);
      console.log('Owner:', obligation.state.owner.toString());

      const reserveDeposit = [...obligation.deposits.values()].find(
        (deposit) => deposit.reserveAddress.toString() === reserveAddress.toString()
      );

      if (reserveDeposit) {
        console.log('\nDeposit in this Reserve:');
        console.log('  Amount:', reserveDeposit.amount);
        console.log('  Market Value:', reserveDeposit.marketValueRefreshed);
      }

      const otherDeposits = [...obligation.deposits.values()].filter(
        (deposit) => deposit.reserveAddress.toString() !== reserveAddress.toString()
      );
      if (otherDeposits.length > 0) {
        console.log('\nOther Deposits:');
        otherDeposits.forEach((deposit) => {
          console.log('  Reserve:', deposit.reserveAddress.toString());
          console.log('    Market Value:', deposit.marketValueRefreshed);
        });
      }

      const borrows = [...obligation.borrows.values()];
      if (borrows.length > 0) {
        console.log('\nBorrows:');
        borrows.forEach((borrow) => {
          console.log('  Reserve:', borrow.reserveAddress.toString());
          console.log('    Market Value:', borrow.marketValueRefreshed);
        });
      }

      console.log('\nMetrics:');
      console.log('Loan-to-Value:', obligation.loanToValue());
      console.log('Number of Positions:', obligation.getNumberOfPositions());
      console.log();
    });
    }

    ```

    <a target="_blank" rel="noopener noreferrer" class="github-link">
      <Icon icon="github" iconType="brands" size={16} />

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

### Get User Transaction History

Access all transaction history for a user's wallet across deposits, borrows, repayments, and liquidations.

<Tabs>
  <Tab title="TypeScript">
    ```typescript title="getTransactionHistory.ts" theme={null}
    const marketPubkey = 'DxXdAyU3kCjnyggvHmY5nAwg5cRbbmdyX3npfDMjjMek';
    const userPubkey = 'EZC9wzVCvihCsCHEMGADYdsRhcpdRYWzSCZAVegSCfqY';

    const API_BASE_URL = 'https://api.kamino.finance';

    const url = `${API_BASE_URL}/v2/kamino-market/${marketPubkey}/users/${userPubkey}/transactions`;

    const res = await fetch(url);

    if (!res.ok) {
      throw new Error(`Request failed: ${res.status} ${res.statusText}`);
    }

    const data = await res.json();

    console.log(data);
    ```

    <a target="_blank" rel="noopener noreferrer" class="github-link">
      <Icon icon="github" iconType="brands" size={16} />

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

## Additional Resources

<CardGroup cols={4}>
  <Card title="API Examples" icon="book" href="https://api-docs.kamino.com/" />

  <Card title="SDK Examples" icon="github" href="https://github.com/Kamino-Finance/klend-sdk/tree/master/examples" />
</CardGroup>
