Skip to content

Commit

Permalink
NNS1-3281: Add function to get TVL (#5406)
Browse files Browse the repository at this point in the history
# Motivation

The NNS dapp displays the USD value of the total amount of ICP locked in
neurons.
It gets this information from the TVL canister but we want to move this
functionality to the nns-dapp canister and remove the TVL canister.

There are 2 inputs to this data:
1. The amount of ICP locked in neurons
2. The price of ICP in USD.

We already have functions which periodically fetch this data and store
it in the canister state.

This PR adds a function to get the TVL calculated from these 2 inputs.

# Changes

Add `get_tvl` which returns the current TVL. The return type is the way
it is to make it compatible with the existing TVL canister. This allows
us to migrate the frontend from using the TVL canister to getting the
same data from the nns-dapp canister without changing frontend code.

# Tests

1. Unit test added.
2. Tested manually in another branch which has more changes.
3. Will add an integration test when the feature is ready.

# Todos

- [ ] Add entry to changelog (if necessary).
not yet.
  • Loading branch information
dskloetd authored Sep 5, 2024
1 parent b04fec2 commit ac8d1a0
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 1 deletion.
1 change: 1 addition & 0 deletions rs/backend/src/constants.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use icp_ledger::Memo;

pub const E8S_PER_UNIT: u64 = 100_000_000;
pub const NANOS_PER_UNIT: u64 = 1_000_000_000;

pub const MEMO_CREATE_CANISTER: Memo = Memo(0x4145_5243); // == 'CREA'
Expand Down
32 changes: 31 additions & 1 deletion rs/backend/src/tvl.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,30 @@
use crate::{
canisters::{exchange_rate_canister, governance},
constants::NANOS_PER_UNIT,
constants::{E8S_PER_UNIT, NANOS_PER_UNIT},
spawn,
state::STATE,
time,
timer::{set_timer, set_timer_interval},
};
use candid::{CandidType, Nat};
use std::time::Duration;

pub mod state;

const XRC_MARGIN_SECONDS: u64 = 60 * 5;
const UPDATE_INTERVAL_SECONDS: u64 = 6 * 60 * 60; // 4 times a day

#[derive(CandidType, Debug, PartialEq)]
pub struct TvlResult {
pub tvl: Nat, // Total Value Locked in whole USD.
pub time_sec: Nat,
}

#[derive(CandidType, Debug, PartialEq)]
pub enum TvlResponse {
Ok(TvlResult),
}

// TODO(NNS1-3281): Remove #[allow(unused)].
#[allow(unused)]
pub fn start_updating_exchange_rate_in_background() {
Expand Down Expand Up @@ -156,5 +168,23 @@ pub async fn update_locked_icp_e8s() {
});
}

// TODO(NNS1-3281): Remove #[allow(unused)].
#[allow(unused)]
pub fn get_tvl() -> TvlResponse {
STATE.with(|s| {
let state = s.tvl_state.borrow();
let locked_u128 = state.total_locked_icp_e8s as u128;
let rate_u128 = state.usd_e8s_per_icp as u128;
let e8s_per_unit = E8S_PER_UNIT as u128;
let tvl = locked_u128 * rate_u128 / e8s_per_unit / e8s_per_unit;
let time_sec = state.exchange_rate_timestamp_seconds;

TvlResponse::Ok(TvlResult {
tvl: Nat::from(tvl),
time_sec: Nat::from(time_sec),
})
})
}

#[cfg(test)]
pub(crate) mod tests;
21 changes: 21 additions & 0 deletions rs/backend/src/tvl/tests.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::timer;
use crate::tvl::{self, exchange_rate_canister, governance, spawn, time, STATE};
use candid::Nat;
use lazy_static::lazy_static;

const NOW_SECONDS: u64 = 1_234_567_890;
Expand Down Expand Up @@ -314,6 +315,26 @@ async fn update_locked_icp_e8s_with_method_error() {
assert_eq!(get_total_locked_icp_e8s(), initial_locked_icp_e8s);
}

#[test]
fn get_tvl() {
let timestamp = 1_738_485_470;
let locked_icp_units = 15_000;
let usd_per_icp_units = 8;
let expected_tvl_in_usd = locked_icp_units * usd_per_icp_units;

set_total_locked_icp_e8s(locked_icp_units * 100_000_000);
set_usd_e8s_per_icp(usd_per_icp_units * 100_000_000);
set_exchange_rate_timestamp_seconds(timestamp);

assert_eq!(
tvl::get_tvl(),
tvl::TvlResponse::Ok(tvl::TvlResult {
tvl: Nat::from(expected_tvl_in_usd),
time_sec: Nat::from(timestamp),
})
);
}

#[tokio::test]
async fn start_updating_exchange_rate_in_background() {
tvl::time::testing::set_time(NOW_SECONDS * 1_000_000_000);
Expand Down

0 comments on commit ac8d1a0

Please sign in to comment.