feat: Add endpoint for circulating supply
This commit is contained in:
parent
552923ae40
commit
d22fe50de6
@ -13,6 +13,7 @@ use neptune_explorer::model::app_state::AppState;
|
|||||||
use neptune_explorer::neptune_rpc;
|
use neptune_explorer::neptune_rpc;
|
||||||
use neptune_explorer::rpc::block_digest::block_digest;
|
use neptune_explorer::rpc::block_digest::block_digest;
|
||||||
use neptune_explorer::rpc::block_info::block_info;
|
use neptune_explorer::rpc::block_info::block_info;
|
||||||
|
use neptune_explorer::rpc::circulating_supply::circulating_supply;
|
||||||
use neptune_explorer::rpc::pow_puzzle::pow_puzzle;
|
use neptune_explorer::rpc::pow_puzzle::pow_puzzle;
|
||||||
use neptune_explorer::rpc::provide_pow_solution::provide_pow_solution;
|
use neptune_explorer::rpc::provide_pow_solution::provide_pow_solution;
|
||||||
use neptune_explorer::rpc::utxo_digest::utxo_digest;
|
use neptune_explorer::rpc::utxo_digest::utxo_digest;
|
||||||
@ -58,6 +59,7 @@ pub fn setup_routes(app_state: AppState) -> Router {
|
|||||||
.route("/rpc/block_digest/*selector", get(block_digest))
|
.route("/rpc/block_digest/*selector", get(block_digest))
|
||||||
.route("/rpc/utxo_digest/:index", get(utxo_digest))
|
.route("/rpc/utxo_digest/:index", get(utxo_digest))
|
||||||
.route("/rpc/pow_puzzle/*address", get(pow_puzzle))
|
.route("/rpc/pow_puzzle/*address", get(pow_puzzle))
|
||||||
|
.route("/rpc/circulating_supply", get(circulating_supply))
|
||||||
.route("/rpc/provide_pow_solution", post(provide_pow_solution))
|
.route("/rpc/provide_pow_solution", post(provide_pow_solution))
|
||||||
// -- Dynamic HTML pages --
|
// -- Dynamic HTML pages --
|
||||||
.route("/", get(root))
|
.route("/", get(root))
|
||||||
|
|||||||
69
src/rpc/circulating_supply.rs
Normal file
69
src/rpc/circulating_supply.rs
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use axum::extract::State;
|
||||||
|
use axum::response::Json;
|
||||||
|
use axum::response::Response;
|
||||||
|
use neptune_cash::api::export::BlockHeight;
|
||||||
|
use neptune_cash::protocol::consensus::block::block_height::BLOCKS_PER_GENERATION;
|
||||||
|
use neptune_cash::protocol::consensus::block::block_height::NUM_BLOCKS_SKIPPED_BECAUSE_REBOOT;
|
||||||
|
use neptune_cash::protocol::consensus::block::Block;
|
||||||
|
use neptune_cash::protocol::consensus::block::PREMINE_MAX_SIZE;
|
||||||
|
use tarpc::context;
|
||||||
|
|
||||||
|
use crate::http_util::rpc_err;
|
||||||
|
use crate::http_util::rpc_method_err;
|
||||||
|
use crate::model::app_state::AppState;
|
||||||
|
|
||||||
|
/// Return the number of coins that are liquid, assuming all redemptions on the
|
||||||
|
/// old chain have successfully been made.
|
||||||
|
#[axum::debug_handler]
|
||||||
|
pub async fn circulating_supply(State(state): State<Arc<AppState>>) -> Result<Json<f64>, Response> {
|
||||||
|
let s = state.load();
|
||||||
|
|
||||||
|
// TODO: Remove this local declaration once version of neptune-core with
|
||||||
|
// this value public is released.
|
||||||
|
let generation_0_subsidy = Block::block_subsidy(BlockHeight::genesis().next());
|
||||||
|
let block_height: u64 = s
|
||||||
|
.rpc_client
|
||||||
|
.block_height(context::current(), s.token())
|
||||||
|
.await
|
||||||
|
.map_err(rpc_err)?
|
||||||
|
.map_err(rpc_method_err)?
|
||||||
|
.into();
|
||||||
|
let effective_block_height = block_height + NUM_BLOCKS_SKIPPED_BECAUSE_REBOOT;
|
||||||
|
let (num_generations, num_blocks_in_generation): (u64, u32) = (
|
||||||
|
effective_block_height / BLOCKS_PER_GENERATION,
|
||||||
|
(effective_block_height % BLOCKS_PER_GENERATION)
|
||||||
|
.try_into()
|
||||||
|
.expect("There are fewer than u32::MAX blocks per generation"),
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut liquid_supply = PREMINE_MAX_SIZE;
|
||||||
|
let mut liquid_subsidy = generation_0_subsidy.half();
|
||||||
|
let blocks_per_generation: u32 = BLOCKS_PER_GENERATION
|
||||||
|
.try_into()
|
||||||
|
.expect("There are fewer than u32::MAX blocks per generation");
|
||||||
|
for _ in 0..num_generations {
|
||||||
|
liquid_supply += liquid_subsidy.scalar_mul(blocks_per_generation);
|
||||||
|
liquid_subsidy = liquid_subsidy.half();
|
||||||
|
}
|
||||||
|
|
||||||
|
liquid_supply += liquid_subsidy.scalar_mul(num_blocks_in_generation);
|
||||||
|
|
||||||
|
// How much of timelocked miner rewards have been unlocked? Assume that the
|
||||||
|
// timelock is exactly one generation long. In reality the timelock is
|
||||||
|
// is defined in relation to timestamp and not block heights, so this is
|
||||||
|
// only a (pretty good) approximation.
|
||||||
|
|
||||||
|
let mut released_subsidy = generation_0_subsidy.half();
|
||||||
|
for _ in 1..num_generations {
|
||||||
|
liquid_supply += released_subsidy.scalar_mul(blocks_per_generation);
|
||||||
|
released_subsidy = released_subsidy.half();
|
||||||
|
}
|
||||||
|
|
||||||
|
if num_generations > 0 {
|
||||||
|
liquid_supply += released_subsidy.scalar_mul(num_blocks_in_generation);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Json(liquid_supply.to_nau_f64()))
|
||||||
|
}
|
||||||
@ -1,5 +1,6 @@
|
|||||||
pub mod block_digest;
|
pub mod block_digest;
|
||||||
pub mod block_info;
|
pub mod block_info;
|
||||||
|
pub mod circulating_supply;
|
||||||
pub mod pow_puzzle;
|
pub mod pow_puzzle;
|
||||||
pub mod provide_pow_solution;
|
pub mod provide_pow_solution;
|
||||||
pub mod utxo_digest;
|
pub mod utxo_digest;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user