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
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.
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.
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.
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.
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.
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.
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.
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.
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.
For users who want to implement customized and native reward claiming, we provide the following instructions:
Step-by-Step Process
Retrieve Claimable Rewards
Use get_user_claimable_rewards to fetch claimable reward information.
Parse the response using parse_claimable_rewardsto determine RewardCoinType, coin_types, and rule_ids
get_user_claimable_rewards
This function retrieves the claimable rewards for a user, returning detailed reward information.
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
This function parses the claimable rewards to return the asset coin types, reward coin types, user total rewards, user claimed rewards, and rule ids.
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.
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.
// 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)
}