Skip to content

Commit

Permalink
Add RPC call to query inflation and ROI at block hash
Browse files Browse the repository at this point in the history
  • Loading branch information
ekovalev committed Sep 15, 2023
1 parent 9eea531 commit 1b7340f
Show file tree
Hide file tree
Showing 14 changed files with 256 additions and 2 deletions.
24 changes: 24 additions & 0 deletions Cargo.lock

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

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,8 @@ pallet-gear-rpc = { path = "pallets/gear/rpc" }
pallet-gear-rpc-runtime-api = { path = "pallets/gear/rpc/runtime-api", default-features = false }
pallet-gear-scheduler = { path = "pallets/gear-scheduler", default-features = false }
pallet-gear-staking-rewards = { path = "pallets/staking-rewards", default-features = false }
pallet-gear-staking-rewards-rpc = { path = "pallets/staking-rewards/rpc" }
pallet-gear-staking-rewards-rpc-runtime-api = { path = "pallets/staking-rewards/rpc/runtime-api", default-features = false }
pallet-gear-voucher = { path = "pallets/gear-voucher", default-features = false }
pallet-gear-bank = { path = "pallets/gear-bank", default-features = false }
runtime-common = { package = "gear-runtime-common", path = "runtime/common", default-features = false }
Expand Down
2 changes: 2 additions & 0 deletions node/service/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ serde = { workspace = true, features = ["derive"] }
# Gear
pallet-gear-rpc.workspace = true
pallet-gear-rpc-runtime-api = { workspace = true, features = ["std"] }
pallet-gear-staking-rewards-rpc.workspace = true
pallet-gear-staking-rewards-rpc-runtime-api = { workspace = true, features = ["std"] }
runtime-primitives = { workspace = true, features = ["std"] }
gear-runtime-interface = { workspace = true, features = ["std"] }
authorship.workspace = true
Expand Down
4 changes: 3 additions & 1 deletion node/service/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ pub trait RuntimeApiCollection:
+ sp_offchain::OffchainWorkerApi<Block>
+ sp_session::SessionKeys<Block>
+ pallet_gear_rpc_runtime_api::GearApi<Block>
+ pallet_gear_staking_rewards_rpc_runtime_api::GearStakingRewardsApi<Block>
where
<Self as sp_api::ApiExt<Block>>::StateBackend: sp_api::StateBackend<BlakeTwo256>,
{
Expand All @@ -136,7 +137,8 @@ where
+ sp_api::Metadata<Block>
+ sp_offchain::OffchainWorkerApi<Block>
+ sp_session::SessionKeys<Block>
+ pallet_gear_rpc_runtime_api::GearApi<Block>,
+ pallet_gear_rpc_runtime_api::GearApi<Block>
+ pallet_gear_staking_rewards_rpc_runtime_api::GearStakingRewardsApi<Block>,
<Self as sp_api::ApiExt<Block>>::StateBackend: sp_api::StateBackend<BlakeTwo256>,
{
}
Expand Down
6 changes: 5 additions & 1 deletion node/service/src/rpc/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ where
+ 'static,
C::Api: substrate_frame_rpc_system::AccountNonceApi<Block, AccountId, Index>,
C::Api: pallet_gear_rpc::GearRuntimeApi<Block>,
C::Api: pallet_gear_staking_rewards_rpc::GearStakingRewardsRuntimeApi<Block>,
C::Api: pallet_transaction_payment_rpc::TransactionPaymentRuntimeApi<Block, Balance>,
C::Api: BabeApi<Block>,
C::Api: BlockBuilder<Block>,
Expand All @@ -110,6 +111,7 @@ where
B::State: sc_client_api::backend::StateBackend<sp_runtime::traits::HashFor<Block>>,
{
use pallet_gear_rpc::{Gear, GearApiServer};
use pallet_gear_staking_rewards_rpc::{GearStakingRewards, GearStakingRewardsApiServer};
use pallet_transaction_payment_rpc::{TransactionPayment, TransactionPaymentApiServer};
use runtime_info::{RuntimeInfoApi, RuntimeInfoServer};
use sc_consensus_babe_rpc::{Babe, BabeApiServer};
Expand Down Expand Up @@ -192,7 +194,9 @@ where

io.merge(Gear::new(client.clone()).into_rpc())?;

io.merge(RuntimeInfoApi::<C, Block, B>::new(client).into_rpc())?;
io.merge(RuntimeInfoApi::<C, Block, B>::new(client.clone()).into_rpc())?;

io.merge(GearStakingRewards::new(client).into_rpc())?;

Ok(io)
}
19 changes: 19 additions & 0 deletions pallets/staking-rewards/rpc/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
[package]
name = "pallet-gear-staking-rewards-rpc"
version = "1.0.0"
authors.workspace = true
edition.workspace = true
license.workspace = true
homepage = "https://gear-tech.io"
repository = "https://github.com/gear-tech/gear"

[dependencies]
jsonrpsee = { workspace = true, features = ["server", "macros"] }

# Substrate packages
sp-api.workspace = true
sp-blockchain.workspace = true
sp-runtime.workspace = true

# Local packages
pallet-gear-staking-rewards-rpc-runtime-api.workspace = true
19 changes: 19 additions & 0 deletions pallets/staking-rewards/rpc/runtime-api/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
[package]
name = "pallet-gear-staking-rewards-rpc-runtime-api"
version = "1.0.0"
authors.workspace = true
edition.workspace = true
license.workspace = true
homepage = "https://gear-tech.io"
repository = "https://github.com/gear-tech/gear"

[dependencies]
sp-api.workspace = true
pallet-gear-staking-rewards.workspace = true

[features]
default = ["std"]
std = [
"sp-api/std",
"pallet-gear-staking-rewards/std",
]
28 changes: 28 additions & 0 deletions pallets/staking-rewards/rpc/runtime-api/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// This file is part of Gear.

// Copyright (C) 2021-2023 Gear Technologies Inc.
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0

// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.

#![cfg_attr(not(feature = "std"), no_std)]

pub use pallet_gear_staking_rewards::InflationInfo;

sp_api::decl_runtime_apis! {
pub trait GearStakingRewardsApi {
/// Calculate token economics related data.
fn inflation_info() -> InflationInfo;
}
}
96 changes: 96 additions & 0 deletions pallets/staking-rewards/rpc/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
// This file is part of Gear.

// Copyright (C) 2021-2023 Gear Technologies Inc.
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0

// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.

//! RPC interface for the gear module.

use jsonrpsee::{
core::{Error as JsonRpseeError, RpcResult},
proc_macros::rpc,
types::error::{CallError, ErrorObject},
};
pub use pallet_gear_staking_rewards_rpc_runtime_api::GearStakingRewardsApi as GearStakingRewardsRuntimeApi;
use pallet_gear_staking_rewards_rpc_runtime_api::InflationInfo;
use sp_api::ProvideRuntimeApi;
use sp_blockchain::HeaderBackend;
use sp_runtime::traits::Block as BlockT;
use std::sync::Arc;

#[rpc(server)]
pub trait GearStakingRewardsApi<BlockHash, ResponseType> {
#[method(name = "stakingRewards_inflationInfo")]
fn query_inflation_info(&self, at: Option<BlockHash>) -> RpcResult<ResponseType>;
}

/// Provides RPC methods to query token economics related data.
pub struct GearStakingRewards<C, P> {
/// Shared reference to the client.
client: Arc<C>,
_marker: std::marker::PhantomData<P>,
}

impl<C, P> GearStakingRewards<C, P> {
/// Creates a new instance of the GearStakingRewards Rpc helper.
pub fn new(client: Arc<C>) -> Self {
Self {
client,
_marker: Default::default(),
}
}
}

/// Error type of this RPC api.
pub enum Error {
/// The transaction was not decodable.
DecodeError,
/// The call to runtime failed.
RuntimeError,
}

impl From<Error> for i32 {
fn from(e: Error) -> i32 {
match e {
Error::RuntimeError => 1,
Error::DecodeError => 2,
}
}
}

impl<C, Block> GearStakingRewardsApiServer<<Block as BlockT>::Hash, InflationInfo>
for GearStakingRewards<C, Block>
where
Block: BlockT,
C: 'static + ProvideRuntimeApi<Block> + HeaderBackend<Block>,
C::Api: GearStakingRewardsRuntimeApi<Block>,
{
fn query_inflation_info(&self, at: Option<Block::Hash>) -> RpcResult<InflationInfo> {
let api = self.client.runtime_api();
let at_hash = at.unwrap_or_else(|| self.client.info().best_hash);

fn map_err(err: impl std::fmt::Debug, desc: &'static str) -> JsonRpseeError {
CallError::Custom(ErrorObject::owned(
Error::RuntimeError.into(),
desc,
Some(format!("{err:?}")),
))
.into()
}

api.inflation_info(at_hash)
.map_err(|e| map_err(e, "Unable to query inflation info"))
}
}
40 changes: 40 additions & 0 deletions pallets/staking-rewards/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ use frame_support::{
PalletId,
};
use pallet_staking::EraPayout;
use parity_scale_codec::{Decode, Encode};
pub use scale_info::TypeInfo;
use sp_runtime::{
traits::{AccountIdConversion, Saturating, StaticLookup},
PerThing, Perquintill,
Expand All @@ -79,6 +81,16 @@ pub type NegativeImbalanceOf<T> = <<T as pallet_staking::Config>::Currency as Cu
>>::NegativeImbalance;
type AccountIdLookupOf<T> = <<T as frame_system::Config>::Lookup as StaticLookup>::Source;

/// Token economics related details.
#[derive(Clone, Decode, Encode, Eq, PartialEq, TypeInfo)]
#[cfg_attr(feature = "std", derive(Debug, serde::Deserialize, serde::Serialize))]
pub struct InflationInfo {
/// Inflation
pub inflation: Perquintill,
/// ROI
pub roi: Perquintill,
}

#[frame_support::pallet]
pub mod pallet {
use super::*;
Expand Down Expand Up @@ -333,11 +345,39 @@ pub mod pallet {
.saturating_sub(T::Currency::minimum_balance())
}

/// Return the current total stakeable tokens amount.
///
/// This value is not calculated but rather updated manually in line with tokenomics model.
pub fn total_stakeable_tokens() -> BalanceOf<T> {
// Should never be 0 but in theory could
(Self::non_stakeable_share().left_from_one() * T::Currency::total_issuance())
.saturating_sub(Self::pool())
}

/// Calculate actual infaltion and ROI parameters.
pub fn inflation_info() -> InflationInfo {
let total_staked = pallet_staking::Pallet::<T>::eras_total_stake(
pallet_staking::Pallet::<T>::current_era().unwrap_or(0),
);
let total_issuance = T::Currency::total_issuance();

let (payout, _) = inflation::compute_total_payout(
total_staked,
Self::total_stakeable_tokens(),
total_issuance,
Self::ideal_staking_ratio(),
T::MinInflation::get(),
Self::target_inflation(),
T::Falloff::get(),
T::MaxROI::get(),
Perquintill::one(),
);

let inflation = Perquintill::from_rational(payout, total_issuance);
let roi = Perquintill::from_rational(payout, total_staked);

InflationInfo { inflation, roi }
}
}
}

Expand Down
4 changes: 4 additions & 0 deletions runtime/gear/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ pallet-gear-payment.workspace = true
pallet-gear-voucher.workspace = true
pallet-gear-rpc-runtime-api.workspace = true
runtime-primitives.workspace = true
pallet-gear-staking-rewards.workspace = true
pallet-gear-staking-rewards-rpc-runtime-api.workspace = true

[build-dependencies]
substrate-build-script-utils.workspace = true
Expand Down Expand Up @@ -126,6 +128,8 @@ std = [
"sp-transaction-pool/std",
"sp-version/std",
"substrate-wasm-builder",
"pallet-gear-staking-rewards-rpc-runtime-api/std",
"pallet-gear-staking-rewards/std",
]
runtime-benchmarks = [
"frame-benchmarking/runtime-benchmarks",
Expand Down
6 changes: 6 additions & 0 deletions runtime/gear/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -806,4 +806,10 @@ impl_runtime_apis_plus_common! {
Executive::try_execute_block(block, state_root_check, signature_check, select).unwrap()
}
}

impl pallet_gear_staking_rewards_rpc_runtime_api::GearStakingRewardsApi<Block> for Runtime {
fn inflation_info() -> pallet_gear_staking_rewards::InflationInfo {
unimplemented!();
}
}
}
2 changes: 2 additions & 0 deletions runtime/vara/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ pallet-gear-payment.workspace = true
pallet-gear-staking-rewards.workspace = true
pallet-gear-voucher.workspace = true
pallet-gear-rpc-runtime-api.workspace = true
pallet-gear-staking-rewards-rpc-runtime-api.workspace = true
runtime-primitives.workspace = true

[dev-dependencies]
Expand Down Expand Up @@ -143,6 +144,7 @@ std = [
"pallet-gear-program/std",
"pallet-gear-staking-rewards/std",
"pallet-gear-rpc-runtime-api/std",
"pallet-gear-staking-rewards-rpc-runtime-api/std",
"pallet-grandpa/std",
"pallet-identity/std",
"pallet-im-online/std",
Expand Down
Loading

0 comments on commit 1b7340f

Please sign in to comment.