# Lending Core

As a developer, your primary interactions with the NAVI Protocol will take place through the functions within the **`lending_core::incentive_v3`** module. This module serves as the entry point for all write transactions, including deposits, withdrawals, borrowing, repayment, liquidations, and reward claims

## Entry Functions

### entry\_deposit

{% hint style="info" %}
This function allows a user to deposit a specified amount of a given coin type into a lending pool. The deposit amount is added to the pool's balance, and a deposit event is emitted.
{% endhint %}

```rust
public entry fun entry_deposit<CoinType>(
    clock: &Clock,
    storage: &mut Storage,
    pool: &mut Pool<CoinType>,
    asset: u8,
    deposit_coin: Coin<CoinType>,
    amount: u64,
    incentive_v2: &mut IncentiveV2,
    incentive_v3: &mut Incentive,
    ctx: &mut TxContext
) {}
```

### entry\_withdraw\_v2

{% hint style="info" %}
This function allows a user to withdraw a specified amount from a lending pool. The withdrawal amount is deducted from the pool's balance, and a withdrawal event is emitted.
{% endhint %}

```rust
public entry fun entry_withdraw_v2<CoinType>(
    clock: &Clock,
    oracle: &PriceOracle,
    storage: &mut Storage,
    pool: &mut Pool<CoinType>,
    asset: u8,
    amount: u64,
    incentive_v2: &mut IncentiveV2,
    incentive_v3: &mut Incentive,
    system_state: &mut SuiSystemState,
    ctx: &mut TxContext
) {}
```

### entry\_borrow\_v2

{% hint style="info" %}
This function allows a user to borrow a specified amount from a lending pool. The borrowed amount is deducted from the pool's balance, and a borrow event is emitted.
{% endhint %}

```rust
public entry fun entry_borrow_v2<CoinType>(
    clock: &Clock,
    oracle: &PriceOracle,
    storage: &mut Storage,
    pool: &mut Pool<CoinType>,
    asset: u8,
    amount: u64,
    incentive_v2: &mut IncentiveV2,
    incentive_v3: &mut Incentive,
    system_state: &mut SuiSystemState,
    ctx: &mut TxContext
) {}
```

### entry\_repay

{% hint style="info" %}
This function allows a user to repay a specified loan amount. The repayment amount is added to the pool's balance, and a repay event is emitted.
{% endhint %}

```rust
public entry fun entry_repay<CoinType>(
    clock: &Clock,
    oracle: &PriceOracle,
    storage: &mut Storage,
    pool: &mut Pool<CoinType>,
    asset: u8,
    repay_coin: Coin<CoinType>,
    amount: u64,
    incentive_v2: &mut IncentiveV2,
    incentive_v3: &mut Incentive,
    ctx: &mut TxContext
) {}
```

### claim\_reward\_entry

{% hint style="info" %}
This function allows users to claim rewards in a specified reward coin. Rewards are distributed from the bonus pool and a claim reward event is emitted.
{% endhint %}

<pre><code><strong>public entry fun claim_reward_entry&#x3C;RewardCoinType>(
</strong>    clock: &#x26;Clock, 
    incentive: &#x26;mut Incentive,
    storage: &#x26;mut Storage, 
    reward_fund: &#x26;mut RewardFund&#x3C;RewardCoinType>,
    coin_types: vector&#x3C;String>,
    rule_ids: vector&#x3C;address>,
    ctx: &#x26;mut TxContext
) {}
</code></pre>

### entry\_liquidation\_v2

{% hint style="info" %}
This function is used to liquidate a loan when a borrower's collateral is insufficient to cover their debt. The liquidation process repays the debt, returning any excess amount to the sender. A liquidation call event is emitted.
{% endhint %}

```rust
public entry fun entry_liquidation_v2<DebtCoinType, CollateralCoinType>(
    clock: &Clock,
    oracle: &PriceOracle,
    storage: &mut Storage,
    debt_asset: u8,
    debt_pool: &mut Pool<DebtCoinType>,
    debt_coin: Coin<DebtCoinType>,
    collateral_asset: u8,
    collateral_pool: &mut Pool<CollateralCoinType>,
    liquidate_user: address,
    liquidate_amount: u64,
    incentive_v2: &mut IncentiveV2,
    incentive_v3: &mut Incentive,
    system_state: &mut SuiSystemState, 
    ctx: &mut TxContext
) {}
```

## Non-entry Functions

### deposit\_with\_account\_cap

{% hint style="info" %}
This function is similar to a standard deposit but includes an account cap limitation. The deposit amount is added to the pool's balance, and a deposit event is emitted.
{% endhint %}

<pre class="language-rust"><code class="lang-rust"><strong>public fun deposit_with_account_cap&#x3C;T>(
</strong>    clock: &#x26;Clock, 
    storage: &#x26;mut Storage,
    pool: &#x26;mut Pool&#x3C;T>, 
    asset: u8,
    deposit_coin: Coin&#x3C;CoinType>,
    incentive_v2: &#x26;mut IncentiveV2,
    incentive_v3: &#x26;mut Incentive,
    account_cap: &#x26;AccountCap
) {}
</code></pre>

### withdraw\_v2

{% hint style="info" %}
This function allows other contracts to withdraw a specified amount from a lending pool. The balance object is returned, and a withdrawal event is emitted.
{% endhint %}

```rust
public fun withdraw_v2<CoinType>(
    clock: &Clock,
    oracle: &PriceOracle,
    storage: &mut Storage,
    pool: &mut Pool<CoinType>,
    asset: u8,
    amount: u64,
    incentive_v2: &mut IncentiveV2,
    incentive_v3: &mut Incentive,
    system_state: &mut SuiSystemState,
    ctx: &mut TxContext
): Balance<CoinType> {}
```

### withdraw\_with\_account\_cap\_v2

{% hint style="info" %}
This function is similar to a standard withdraw but includes an account cap limitation. The balance object is returned, and a withdrawal event is emitted.
{% endhint %}

```rust
public fun withdraw_with_account_cap_v2<CoinType>(
    clock: &Clock,
    oracle: &PriceOracle,
    storage: &mut Storage,
    pool: &mut Pool<CoinType>,
    asset: u8,
    amount: u64,
    incentive_v2: &mut IncentiveV2,
    incentive_v3: &mut Incentive,
    account_cap: &AccountCap,
    system_state: &mut SuiSystemState,
    ctx: &mut TxContext
): Balance<CoinType> {}
```

### borrow\_v2

{% hint style="info" %}
This function allows other contracts to borrow a specified amount from a lending pool. The balance object is returned, and a borrow event is emitted.
{% endhint %}

```rust
public fun borrow_v2<CoinType>(
    clock: &Clock,
    oracle: &PriceOracle,
    storage: &mut Storage,
    pool: &mut Pool<CoinType>,
    asset: u8,
    amount: u64,
    incentive_v2: &mut IncentiveV2,
    incentive_v3: &mut Incentive,
    system_state: &mut SuiSystemState,
    ctx: &mut TxContext
): Balance<CoinType> {}
```

### borrow\_with\_account\_cap\_v2

{% hint style="info" %}
This function is similar to a standard borrow but includes an account cap limitation. The balance object is returned, and the borrow event is emitted.
{% endhint %}

```rust
public fun borrow_with_account_cap_v2<CoinType>(
    clock: &Clock,
    oracle: &PriceOracle,
    storage: &mut Storage,
    pool: &mut Pool<CoinType>,
    asset: u8,
    amount: u64,
    incentive_v2: &mut IncentiveV2,
    incentive_v3: &mut Incentive,
    account_cap: &AccountCap,
    system_state: &mut SuiSystemState,
    ctx: &mut TxContext
): Balance<CoinType> {}
```

### repay

{% hint style="info" %}
This function allows other contracts to repay a specified amount of a loan. The balance object is returned, and a repay event is emitted.
{% endhint %}

```rust
public fun repay<CoinType>(
    clock: &Clock,
    oracle: &PriceOracle,
    storage: &mut Storage,
    pool: &mut Pool<CoinType>,
    asset: u8,
    repay_coin: Coin<CoinType>,
    amount: u64,
    incentive_v2: &mut IncentiveV2,
    incentive_v3: &mut Incentive,
    ctx: &mut TxContext
): Balance<CoinType> {}
```

### repay\_with\_account\_cap

{% hint style="info" %}
This function is similar to a standard repay but includes an account cap limitation.  The balance object is returned, and a repay event is emitted.
{% endhint %}

```rust
public fun repay_with_account_cap<CoinType>(
    clock: &Clock,
    oracle: &PriceOracle,
    storage: &mut Storage,
    pool: &mut Pool<CoinType>,
    asset: u8,
    repay_coin: Coin<CoinType>,
    amount: u64,
    incentive_v2: &mut IncentiveV2,
    incentive_v3: &mut Incentive,
    account_cap: &AccountCap
): Balance<CoinType> {}
```

### claim\_reward

{% hint style="info" %}
Quick Reward Claiming Using the SDK

We recommend using the SDK to claim rewards because the SDK will automatically claim all available rewards and perform off-chain indexing to optimize gas usage.

#### SDK Benefits:

* **Off-chain indexing**: Retrieves relevant rules without incurring on-chain gas costs.
* **Optimized filtering**: Selects only the necessary rule IDs before executing on-chain transactions.
  {% endhint %}

For users who want to implement customized and native reward claiming, we provide the following instructions:

### Step-by-Step Process

1. **Retrieve Claimable Rewards**&#x20;

* Use `get_user_claimable_rewards` to fetch claimable reward information.
* Parse the response using `parse_claimable_rewards`to determine RewardCoinType, coin\_types, and rule\_ids

### get\_user\_claimable\_rewards

{% hint style="info" %}
This function retrieves the claimable rewards for a user, returning detailed reward information.
{% endhint %}

```rust
struct ClaimableReward has copy, drop {
    asset_coin_type: String,
    reward_coin_type: String,
    user_claimable_reward: u256,
    user_claimed_reward: u256,
    rule_ids: vector<address>,
}

public fun get_user_claimable_rewards<RewardCoinType>(
    clock: &Clock, 
    storage: &mut Storage, 
    incentive: &mut Incentive,
    user: address
) vector<ClaimableReward> {}
```

### parse\_claimable\_rewards

{% hint style="info" %}
This function parses the claimable rewards to return the asset coin types, reward coin types, user total rewards, user claimed rewards, and rule ids.
{% endhint %}

```rust
public fun parse_claimable_rewards(claimable_rewards: vector<ClaimableReward>)
(
    vector<String>, // asset coin types
    vector<String>, // reward coin types
    vector<u256>,   // user total rewards
    vector<u256>,   // user claimed rewards
    vector<vector<address>> // rule ids
)
```

* The `coin_types` are derived from the asset tokens involved.
* The `rule_ids` are extracted from the parsed claimable rewards.

2. **Execute**

<pre><code><strong>// Reward Fund IDs
</strong>VSUI: 0x7093cf7549d5e5b35bfde2177223d1050f71655c7f676a5e610ee70eb4d93b5c
NAVX: 0x1a3f9fcfdfac10e92c99220203f7c4bb502558692f0be0f2cb5f788b4e12a6b5
SUINS: 0xc6b14b4eda9015ca69ec5f6a9688faa4f760259ce285dafe902ebe6700f5838f
DEEP: 0xc889d78b634f954979e80e622a2ae0fece824c0f6d9590044378a2563035f32f
FDUSD: 0x958dd7ad70755b10f96693bcd591d7a2cb9830a6c523baf43b3b5897664aa788
</code></pre>

### claim\_reward

```
public entry fun claim_reward<RewardCoinType>(
    clock: &Clock, 
    incentive: &mut Incentive,
    storage: &mut Storage, 
    reward_fund: &mut RewardFund<RewardCoinType>,
    coin_types: vector<String>,
    rule_ids: vector<address>,
    ctx: &mut TxContext
) {}
```

### claim\_reward\_with\_account\_cap

{% hint style="info" %}
This function is similar to a standard claim rewards but includes an account cap limitation. Rewards are distributed from the bonus pool, and a claim reward event is emitted.
{% endhint %}

<pre class="language-rust"><code class="lang-rust"><strong>public fun claim_reward_with_account_cap&#x3C;RewardCoinType>(
</strong>    clock: &#x26;Clock, 
    incentive: &#x26;mut Incentive,
    storage: &#x26;mut Storage, 
    reward_fund: &#x26;mut RewardFund&#x3C;RewardCoinType>,
    coin_types: vector&#x3C;String>,
    rule_ids: vector&#x3C;address>,
    account_cap: &#x26;AccountCap
) Balance&#x3C;RewardCoinType> {}
</code></pre>

* Sample: Provide the appropriate parameters:

```
// To claim rewards, we need to gather the same reward coin types
// and then pass the corresponding asset coin types and rule IDs.
// The expected function call should look like this:
claim_reward<VSUI>(
    ...,  // Additional parameters (e.g., clock, incentive, storage, etc.)
    coin_types: <SUI, SUI, BLUE, BLUE>,  // Expand asset types to match rule mappings
    rule_ids: <rule1, rule2, rule3, rule4>  // Flattened list of rule IDs
);
```

```
let user_a_rewards = incentive_v3::get_user_claimable_rewards(
    &clock,           
    &mut storage,     
    &mut incentive,   
    USER_A            
);
​
// Parse the retrieved claimable rewards into structured vectors
let (
    asset_coin_types,       // List of asset coin types
    reward_coin_types,      // List of corresponding reward coin types
    user_claimable_rewards, // Total claimable rewards per asset
    user_claimed_rewards,   // Already claimed rewards per asset
    rule_ids                // Associated rule IDs for each asset
) = incentive_v3::parse_claimable_rewards(user_a_rewards);
// Parse the retrieved claimable rewards into structured vectors
// Example output structure after parsing:
// (
//   <SUI, BLUE>,         // Unique asset coin types
//   <VSUI, VSUI>,        // Corresponding reward coin types
//   <claimable1, claimable2>, // Claimable rewards amounts
//   <claimed1, claimed2>, // Already claimed amounts
//   <<rule1, rule2>, <rule3, rule4>> // Rule IDs grouped by asset type
// )
```

### Full Claim Contract Demo

```
use lending_core::incentive_v3::{Self, Incentive as IncentiveV3, RewardFund};
use lending_core::storage::Storage;
use std::ascii::String;
use std::type_name;
use std::vector;
use sui::balance::{Balance};
use sui::coin::{Self};
use sui::clock::{Clock};
use sui::transfer::{Self};
use sui::tx_context::{Self, TxContext};

/// This function is used to claim reward with one coin type
/// It runs fully onchain without offchain indexing.
/// This practice is not gas optimized, and claiming reward though SDK with is recommended.
/// Params objectIds will be available on the gitbook.
    public fun claim_reward<RewardCoinType>(
        clock: &Clock,
        incentive: &mut IncentiveV3,
        storage: &mut Storage,
        reward_fund: &mut RewardFund<RewardCoinType>,
        ctx: &mut TxContext,
    ): Balance<RewardCoinType> {
        let (
            asset_coin_types,
            reward_coin_types,
            user_total_rewards,
            user_claimed_rewards,
            rule_ids,
        ) = incentive_v3::parse_claimable_rewards(
            incentive_v3::get_user_claimable_rewards(
                clock,
                storage,
                incentive,
                tx_context::sender(ctx),
            ),
        );

        let target_coin_type = &type_name::into_string(type_name::get<RewardCoinType>());

        let input_coin_types = vector::empty<String>();
        let input_rule_ids = vector::empty<address>();

        let i = 0;
        while (i < vector::length(&asset_coin_types)) {
            let asset_coin_type = vector::borrow(&asset_coin_types, i);
            let reward_coin_type = vector::borrow(&reward_coin_types, i);
            let user_total_reward = *vector::borrow(&user_total_rewards, i);
            let user_claimed_reward = *vector::borrow(&user_claimed_rewards, i);
            let rule_id = vector::borrow(&rule_ids, i);

            if (user_total_reward > user_claimed_reward && reward_coin_type == target_coin_type) {
                vector::push_back(&mut input_coin_types, *asset_coin_type);
                vector::append(&mut input_rule_ids, *rule_id);
            };

            i = i + 1;
        };

        incentive_v3::claim_reward<RewardCoinType>(
            clock,
            incentive,
            storage,
            reward_fund,
            input_coin_types,
            input_rule_ids,
            ctx,
        )
    }

    public entry fun claim_reward_entry<RewardCoinType>(
        clock: &Clock,
        incentive: &mut IncentiveV3,
        storage: &mut Storage,
        reward_fund: &mut RewardFund<RewardCoinType>,
        recipient: address,
        ctx: &mut TxContext,
    ) {
        let (
            asset_coin_types,
            reward_coin_types,
            user_total_rewards,
            user_claimed_rewards,
            rule_ids,
        ) = incentive_v3::parse_claimable_rewards(
            incentive_v3::get_user_claimable_rewards(
                clock,
                storage,
                incentive,
                tx_context::sender(ctx),
            ),
        );

        let target_coin_type = &type_name::into_string(type_name::get<RewardCoinType>());

        let input_coin_types = vector::empty<String>();
        let input_rule_ids = vector::empty<address>();

        let i = 0;
        while (i < vector::length(&asset_coin_types)) {
            let asset_coin_type = vector::borrow(&asset_coin_types, i);
            let reward_coin_type = vector::borrow(&reward_coin_types, i);
            let user_total_reward = *vector::borrow(&user_total_rewards, i);
            let user_claimed_reward = *vector::borrow(&user_claimed_rewards, i);
            let rule_id = vector::borrow(&rule_ids, i);

            if (user_total_reward > user_claimed_reward && reward_coin_type == target_coin_type) {
                vector::push_back(&mut input_coin_types, *asset_coin_type);
                vector::append(&mut input_rule_ids, *rule_id);
            };

            i = i + 1;
        };

        let balance = incentive_v3::claim_reward<RewardCoinType>(
            clock,
            incentive,
            storage,
            reward_fund,
            input_coin_types,
            input_rule_ids,
            ctx,
        );

        transfer::public_transfer(coin::from_balance(balance, ctx), recipient)
    }
```

example: [https://suivision.xyz/txblock/5Nr7nkQg8GGLepEPVRmZ2CamkUgsSoNMqDyhNGbVqjjW](https://suivision.xyz/txblock/5Nr7nkQg8GGLepEPVRmZ2CamkUgsSoNMqDyhNGbVqjjW?tab=Overview)
