Skip to content

Commit

Permalink
feat: add InvestmentPortfolio Runtime API (#1608)
Browse files Browse the repository at this point in the history
* feat: add InvestmentPortfolio RtAPI

* tests: investment portfolio single tranche

* fix: rm locked, add reserved

* chore: use fungibles + add pool currency id
  • Loading branch information
wischli authored Nov 21, 2023
1 parent c49ac60 commit 55570cc
Show file tree
Hide file tree
Showing 17 changed files with 497 additions and 115 deletions.
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion libs/primitives/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ pub mod constants {
/// We allow for 0.5 seconds of compute with a 6 second average block time.
pub const MAXIMUM_BLOCK_WEIGHT: Weight = Weight::from_parts(WEIGHT_REF_TIME_PER_SECOND, 0)
.saturating_div(2)
.set_proof_size(MAX_POV_SIZE as u64);
.set_proof_size(MAX_POV_SIZE);

pub const MICRO_CFG: Balance = 1_000_000_000_000; // 10−6 0.000001
pub const MILLI_CFG: Balance = 1_000 * MICRO_CFG; // 10−3 0.001
Expand Down
20 changes: 0 additions & 20 deletions libs/traits/src/investments.rs
Original file line number Diff line number Diff line change
Expand Up @@ -219,26 +219,6 @@ pub trait InvestmentAccountant<AccountId> {
) -> Result<(), Self::Error>;
}

/// Trait to handle Investment Portfolios for accounts
pub trait InvestmentsPortfolio<Account> {
type InvestmentId;
type CurrencyId;
type Balance;
type Error;
type AccountInvestmentPortfolio;

/// Get the payment currency for an investment.
fn get_investment_currency_id(
investment_id: Self::InvestmentId,
) -> Result<Self::CurrencyId, Self::Error>;

/// Get the investments and associated payment currencies and balances for
/// an account.
fn get_account_investments_currency(
who: &Account,
) -> Result<Self::AccountInvestmentPortfolio, Self::Error>;
}

/// Trait to handle investments in (presumably) foreign currencies, i.e., other
/// currencies than the pool currency.
///
Expand Down
2 changes: 1 addition & 1 deletion libs/types/src/fixed_point.rs
Original file line number Diff line number Diff line change
Expand Up @@ -550,7 +550,7 @@ impl<const DIV: u128> FixedPointNumberExtension for FixedU128<DIV> {

multiply_by_rational_with_rounding(
lhs.value,
Self::DIV as u128,
Self::DIV,
rhs.value,
Rounding::from_signed(r, negative),
)
Expand Down
66 changes: 66 additions & 0 deletions libs/types/src/investments.rs
Original file line number Diff line number Diff line change
Expand Up @@ -239,3 +239,69 @@ pub struct ExecutedForeignCollect<Balance, Currency> {
/// pool currency)
pub amount_remaining: Balance,
}

/// A representation of an investment portfolio consisting of free, pending and
/// claimable pool currency as well as tranche tokens.
#[derive(Encode, Decode, Default, Clone, Eq, PartialEq, RuntimeDebug, TypeInfo, MaxEncodedLen)]

pub struct InvestmentPortfolio<Balance, CurrencyId> {
/// The identifier of the pool currency
pub pool_currency_id: CurrencyId,
/// The unprocessed invest order amount in pool currency
pub pending_invest_currency: Balance,
/// The amount of tranche tokens which can be collected for an invest order
pub claimable_tranche_tokens: Balance,
/// The amount of tranche tokens which can be transferred
pub free_tranche_tokens: Balance,
/// The amount of tranche tokens which can not be used at all and could get
/// slashed
pub reserved_tranche_tokens: Balance,
/// The unprocessed redeem order amount in tranche tokens
pub pending_redeem_tranche_tokens: Balance,
/// The amount of pool currency which can be collected for a redeem order
pub claimable_currency: Balance,
}

impl<Balance: Default, CurrencyId> InvestmentPortfolio<Balance, CurrencyId> {
pub fn new(pool_currency_id: CurrencyId) -> Self {
Self {
pool_currency_id,
pending_invest_currency: Balance::default(),
claimable_tranche_tokens: Balance::default(),
free_tranche_tokens: Balance::default(),
reserved_tranche_tokens: Balance::default(),
pending_redeem_tranche_tokens: Balance::default(),
claimable_currency: Balance::default(),
}
}

pub fn with_pending_invest_currency(mut self, amount: Balance) -> Self {
self.pending_invest_currency = amount;
self
}

pub fn with_free_tranche_tokens(mut self, amount: Balance) -> Self {
self.free_tranche_tokens = amount;
self
}

pub fn with_reserved_tranche_tokens(mut self, amount: Balance) -> Self {
self.reserved_tranche_tokens = amount;
self
}

pub fn with_claimable_tranche_tokens(mut self, amount: Balance) -> Self {
self.claimable_tranche_tokens = amount;
self
}

pub fn with_pending_redeem_tranche_tokens(mut self, amount: Balance) -> Self {
self.pending_redeem_tranche_tokens = amount;
self
}

pub fn with_claimable_currency(mut self, amount: Balance) -> Self {
self.claimable_currency = amount;
self
}
}
42 changes: 2 additions & 40 deletions pallets/investments/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,7 @@

use cfg_primitives::OrderId;
use cfg_traits::{
investments::{
Investment, InvestmentAccountant, InvestmentCollector, InvestmentsPortfolio, OrderManager,
},
investments::{Investment, InvestmentAccountant, InvestmentCollector, OrderManager},
PreConditions, StatusNotificationHook,
};
use cfg_types::{
Expand Down Expand Up @@ -47,6 +45,7 @@ use sp_std::{
convert::TryInto,
vec::Vec,
};

pub mod weights;
pub use weights::WeightInfo;

Expand All @@ -60,12 +59,6 @@ mod tests;
type CurrencyOf<T> =
<<T as Config>::Tokens as Inspect<<T as frame_system::Config>::AccountId>>::AssetId;

type AccountInvestmentPortfolioOf<T> = Vec<(
<T as Config>::InvestmentId,
CurrencyOf<T>,
<T as Config>::Amount,
)>;

/// The enum we parse to `PreConditions` so the runtime
/// can make an educated decision about this investment
#[derive(Encode, Decode, Clone, Eq, PartialEq, RuntimeDebug, TypeInfo)]
Expand Down Expand Up @@ -1100,37 +1093,6 @@ impl<T: Config> Pallet<T> {
}
}

impl<T: Config> InvestmentsPortfolio<T::AccountId> for Pallet<T> {
type AccountInvestmentPortfolio = AccountInvestmentPortfolioOf<T>;
type Balance = T::Amount;
type CurrencyId = CurrencyOf<T>;
type Error = DispatchError;
type InvestmentId = T::InvestmentId;

/// Get the payment currency for an investment.
fn get_investment_currency_id(
investment_id: T::InvestmentId,
) -> Result<CurrencyOf<T>, DispatchError> {
let info = T::Accountant::info(investment_id).map_err(|_| Error::<T>::UnknownInvestment)?;
Ok(info.payment_currency)
}

/// Get the investments and associated payment currencies and balances for
/// an account.
fn get_account_investments_currency(
who: &T::AccountId,
) -> Result<Self::AccountInvestmentPortfolio, DispatchError> {
let mut investments_currency: Vec<(Self::InvestmentId, Self::CurrencyId, Self::Balance)> =
Vec::new();
<InvestOrders<T>>::iter_key_prefix(who).try_for_each(|i| {
let currency = Self::get_investment_currency_id(i)?;
let balance = T::Accountant::balance(i, who);
investments_currency.push((i, currency, balance));
Ok::<(), DispatchError>(())
})?;
Ok(investments_currency)
}
}
impl<T: Config> Investment<T::AccountId> for Pallet<T> {
type Amount = T::Amount;
type CurrencyId = CurrencyOf<T>;
Expand Down
7 changes: 4 additions & 3 deletions runtime/altair/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ use cfg_types::{
fee_keys::FeeKey,
fixed_point::{Quantity, Rate, Ratio},
ids::PRICE_ORACLE_PALLET_ID,
investments::InvestmentPortfolio,
oracles::OracleKey,
permissions::{PermissionRoles, PermissionScope, PermissionedCurrencyRole, PoolRole, Role},
time::TimeProvider,
Expand Down Expand Up @@ -2164,9 +2165,9 @@ impl_runtime_apis! {


// Investment Runtime APIs
impl runtime_common::apis::InvestmentsApi<Block, AccountId, TrancheCurrency, CurrencyId, PoolId, Balance> for Runtime {
fn investment_portfolio(account_id: AccountId) -> Option<Vec<(PoolId, CurrencyId, TrancheCurrency, Balance)>> {
runtime_common::investment_portfolios::get_portfolios::<Runtime, AccountId, TrancheId, Investments, TrancheCurrency, CurrencyId, PoolId, Balance>(account_id)
impl runtime_common::apis::InvestmentsApi<Block, AccountId, TrancheCurrency, InvestmentPortfolio<Balance, CurrencyId>> for Runtime {
fn investment_portfolio(account_id: AccountId) -> Vec<(TrancheCurrency, InvestmentPortfolio<Balance, CurrencyId>)> {
runtime_common::investment_portfolios::get_account_portfolio::<Runtime, PoolSystem>(account_id)
}
}

Expand Down
1 change: 1 addition & 0 deletions runtime/centrifuge/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -420,3 +420,4 @@ on-chain-release-build = [

# Set timing constants (e.g. session period) to faster versions to speed up testing.
fast-runtime = []

7 changes: 4 additions & 3 deletions runtime/centrifuge/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ use cfg_types::{
fee_keys::FeeKey,
fixed_point::{Quantity, Rate, Ratio},
ids::PRICE_ORACLE_PALLET_ID,
investments::InvestmentPortfolio,
oracles::OracleKey,
permissions::{
PermissionRoles, PermissionScope, PermissionedCurrencyRole, PoolRole, Role, UNION,
Expand Down Expand Up @@ -2201,9 +2202,9 @@ impl_runtime_apis! {
}

// Investment Runtime APIs
impl runtime_common::apis::InvestmentsApi<Block, AccountId, TrancheCurrency, CurrencyId, PoolId, Balance> for Runtime {
fn investment_portfolio(account_id: AccountId) -> Option<Vec<(PoolId, CurrencyId, TrancheCurrency, Balance)>> {
runtime_common::investment_portfolios::get_portfolios::<Runtime, AccountId, TrancheId, Investments, TrancheCurrency, CurrencyId, PoolId, Balance>(account_id)
impl runtime_common::apis::InvestmentsApi<Block, AccountId, TrancheCurrency, InvestmentPortfolio<Balance, CurrencyId>> for Runtime {
fn investment_portfolio(account_id: AccountId) -> Vec<(TrancheCurrency, InvestmentPortfolio<Balance, CurrencyId>)> {
runtime_common::investment_portfolios::get_account_portfolio::<Runtime, PoolSystem>(account_id)
}
}

Expand Down
8 changes: 8 additions & 0 deletions runtime/common/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ xcm-executor = { git = "https://github.com/paritytech/polkadot", default-feature
# ORML dependencies
orml-asset-registry = { git = "https://github.com/open-web3-stack/open-runtime-module-library", default-features = false, branch = "polkadot-v0.9.43" }
orml-oracle = { git = "https://github.com/open-web3-stack/open-runtime-module-library", default-features = false, branch = "polkadot-v0.9.43" }
orml-tokens = { git = "https://github.com/open-web3-stack/open-runtime-module-library", default-features = false, branch = "polkadot-v0.9.43" }
orml-traits = { git = "https://github.com/open-web3-stack/open-runtime-module-library", default-features = false, branch = "polkadot-v0.9.43" }

# Frontier dependencies
Expand Down Expand Up @@ -70,6 +71,7 @@ pallet-liquidity-pools = { path = "../../pallets/liquidity-pools", default-featu
pallet-liquidity-pools-gateway = { path = "../../pallets/liquidity-pools-gateway", default-features = false }
pallet-loans = { path = "../../pallets/loans", default-features = false }
pallet-pool-system = { path = "../../pallets/pool-system", default-features = false }
pallet-restricted-tokens = { path = "../../pallets/restricted-tokens", default-features = false }

# Used for migrations
log = "0.4"
Expand Down Expand Up @@ -97,6 +99,7 @@ std = [
"log/std",
"orml-asset-registry/std",
"orml-oracle/std",
"orml-tokens/std",
"orml-traits/std",
"pallet-anchors/std",
"pallet-authorship/std",
Expand All @@ -117,6 +120,7 @@ std = [
"pallet-liquidity-pools/std",
"pallet-loans/std",
"pallet-pool-system/std",
"pallet-restricted-tokens/std",
"pallet-treasury/std",
"parachain-info/std",
"polkadot-parachain/std",
Expand All @@ -143,6 +147,7 @@ runtime-benchmarks = [
"frame-support/runtime-benchmarks",
"frame-system/runtime-benchmarks",
"orml-asset-registry/runtime-benchmarks",
"orml-tokens/runtime-benchmarks",
"pallet-anchors/runtime-benchmarks",
"pallet-balances/runtime-benchmarks",
"pallet-data-collector/runtime-benchmarks",
Expand All @@ -153,6 +158,7 @@ runtime-benchmarks = [
"pallet-liquidity-pools/runtime-benchmarks",
"pallet-loans/runtime-benchmarks",
"pallet-pool-system/runtime-benchmarks",
"pallet-restricted-tokens/runtime-benchmarks",
"pallet-treasury/runtime-benchmarks",
"polkadot-parachain/runtime-benchmarks",
"sp-runtime/runtime-benchmarks",
Expand All @@ -176,6 +182,7 @@ try-runtime = [
"frame-system/try-runtime",
"orml-asset-registry/try-runtime",
"orml-oracle/try-runtime",
"orml-tokens/try-runtime",
"pallet-anchors/try-runtime",
"pallet-authorship/try-runtime",
"pallet-balances/try-runtime",
Expand All @@ -189,6 +196,7 @@ try-runtime = [
"pallet-liquidity-pools/try-runtime",
"pallet-loans/try-runtime",
"pallet-pool-system/try-runtime",
"pallet-restricted-tokens/try-runtime",
"pallet-treasury/try-runtime",
"parachain-info/try-runtime",
"sp-runtime/try-runtime",
Expand Down
8 changes: 3 additions & 5 deletions runtime/common/src/apis/investments.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,12 @@ use sp_std::vec::Vec;

decl_runtime_apis! {
/// Runtime API for investments
pub trait InvestmentsApi<AccountId, InvestmentId, CurrencyId, PoolId, Balance>
pub trait InvestmentsApi<AccountId, InvestmentId, InvestmentPortfolio>
where
AccountId: Codec,
InvestmentId: Codec,
PoolId: Codec,
CurrencyId: Codec,
Balance: Codec,
InvestmentPortfolio: Codec,
{
fn investment_portfolio(account_id: AccountId) -> Option<Vec<(PoolId, CurrencyId, InvestmentId, Balance)>>;
fn investment_portfolio(account_id: AccountId) -> Vec<(InvestmentId, InvestmentPortfolio)>;
}
}
Loading

0 comments on commit 55570cc

Please sign in to comment.