Added kernel page, respect id field in api

This commit is contained in:
aglkm
2024-05-24 15:14:16 +03:00
parent 7aadd85e19
commit 2aaebee5f4
5 changed files with 124 additions and 32 deletions

View File

@@ -111,6 +111,29 @@ impl Block {
}
// Kernel data
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Kernel {
pub height: String,
pub excess: String,
pub ker_type: String,
pub fee: String,
pub raw_data: String,
}
impl Kernel {
pub fn new() -> Kernel {
Kernel {
height: String::new(),
excess: String::new(),
ker_type: String::new(),
fee: String::new(),
raw_data: String::new(),
}
}
}
// Transactions data
#[derive(Debug)]
pub struct Transactions {

View File

@@ -18,6 +18,7 @@ mod data;
use crate::data::Dashboard;
use crate::data::Block;
use crate::data::Transactions;
use crate::data::Kernel;
// Rendering main (Dashboard) page.
@@ -119,21 +120,22 @@ async fn block_header_by_hash(hash: &str) -> Either<Template, Redirect> {
// Rendering page for a specified kernel.
#[get("/kernel/<kernel>")]
async fn kernel(kernel: &str) -> Either<Template, Redirect> {
let mut height = String::new();
#[get("/kernel/<excess>")]
async fn kernel(excess: &str) -> Template {
let mut kernel = Kernel::new();
let _ = requests::get_kernel(&kernel, &mut height).await;
let _ = requests::get_kernel(&excess, &mut kernel).await;
if kernel.is_empty() == false {
if height.is_empty() == false {
return Either::Right(Redirect::to(uri!(block_details_by_height(height.as_str()))));
}
if kernel.height.is_empty() == false {
return Template::render("kernel", context! {
route: "kernel",
kernel,
})
}
return Either::Left(Template::render("error", context! {
return Template::render("error", context! {
route: "error",
}))
})
}
@@ -183,10 +185,10 @@ async fn api_owner(data: &str) -> String {
Some(value) => value,
_ => return "{\"error\":\"bad syntax\"}".to_string(),
};
// Whitelisted methods: get_connected_peer, get_peers, get_status.
if method == "get_connected_peers" || method == "get_peers" || method == "get_status" {
let resp = requests::call(method, v["params"].to_string().as_str(), "owner").await;
let resp = requests::call(method, v["params"].to_string().as_str(), v["id"].to_string().as_str(), "owner").await;
let result = match resp {
Ok(value) => value,
@@ -216,7 +218,9 @@ async fn api_foreign(data: &str) -> String {
_ => return "{\"error\":\"bad syntax\"}".to_string(),
};
let resp = requests::call(method, v["params"].to_string().as_str(), "foreign").await;
println!("{}", method);
println!("{}", data);
let resp = requests::call(method, v["params"].to_string().as_str(), v["id"].to_string().as_str(), "foreign").await;
let result = match resp {
Ok(value) => value,

View File

@@ -16,6 +16,7 @@ use crate::data::Dashboard;
use crate::data::Block;
use crate::data::Transactions;
use crate::data::ExplorerConfig;
use crate::Kernel;
// Static explorer config structure
@@ -53,7 +54,7 @@ lazy_static! {
// RPC requests to grin node.
pub async fn call(method: &str, params: &str, rpc_type: &str) -> Result<Value, anyhow::Error> {
pub async fn call(method: &str, params: &str, id: &str, rpc_type: &str) -> Result<Value, anyhow::Error> {
let rpc_url;
let secret;
@@ -68,7 +69,7 @@ pub async fn call(method: &str, params: &str, rpc_type: &str) -> Result<Value, a
let client = reqwest::Client::new();
let result = client.post(rpc_url)
.body(format!("{{\"method\": \"{}\", \"params\": {}, \"id\":1}}", method, params))
.body(format!("{{\"method\": \"{}\", \"params\": {}, \"id\": {}}}", method, params, id))
.basic_auth(CONFIG.user.clone(), Some(secret))
.header("content-type", "plain/text")
.send()
@@ -82,7 +83,7 @@ pub async fn call(method: &str, params: &str, rpc_type: &str) -> Result<Value, a
// Collecting: height, sync, node_ver, proto_ver.
pub async fn get_status(dashboard: Arc<Mutex<Dashboard>>) -> Result<(), anyhow::Error> {
let resp = call("get_status", "[]", "owner").await?;
let resp = call("get_status", "[]", "1", "owner").await?;
let mut data = dashboard.lock().unwrap();
@@ -102,8 +103,8 @@ pub async fn get_status(dashboard: Arc<Mutex<Dashboard>>) -> Result<(), anyhow::
// Collecting: txns, stem.
pub async fn get_mempool(dashboard: Arc<Mutex<Dashboard>>) -> Result<(), anyhow::Error> {
let resp1 = call("get_pool_size", "[]", "foreign").await?;
let resp2 = call("get_stempool_size", "[]", "foreign").await?;
let resp1 = call("get_pool_size", "[]", "1", "foreign").await?;
let resp2 = call("get_stempool_size", "[]", "1", "foreign").await?;
let mut data = dashboard.lock().unwrap();
@@ -119,7 +120,7 @@ pub async fn get_mempool(dashboard: Arc<Mutex<Dashboard>>) -> Result<(), anyhow:
// Collecting: inbound, outbound.
pub async fn get_connected_peers(dashboard: Arc<Mutex<Dashboard>>)
-> Result<(), anyhow::Error> {
let resp = call("get_connected_peers", "[]", "owner").await?;
let resp = call("get_connected_peers", "[]", "1", "owner").await?;
let mut data = dashboard.lock().unwrap();
@@ -225,8 +226,8 @@ pub async fn get_mining_stats(dashboard: Arc<Mutex<Dashboard>>) -> Result<(), an
let params1 = &format!("[{}, null, null]", height)[..];
let params2 = &format!("[{}, null, null]", height.parse::<u64>().unwrap()
- difficulty_window)[..];
let resp1 = call("get_block", params1, "foreign").await?;
let resp2 = call("get_block", params2, "foreign").await?;
let resp1 = call("get_block", params1, "1", "foreign").await?;
let resp2 = call("get_block", params2, "1", "foreign").await?;
let mut data = dashboard.lock().unwrap();
@@ -283,7 +284,7 @@ pub async fn get_block_list_data(height: &String, block: &mut Block)
if height.is_empty() == false {
let params = &format!("[{}, null, null]", height)[..];
let resp = call("get_block", params, "foreign").await?;
let resp = call("get_block", params, "1", "foreign").await?;
if resp["result"]["Ok"].is_null() == false {
block.height = resp["result"]["Ok"]["header"]["height"].to_string();
@@ -343,7 +344,7 @@ pub async fn get_block_data(height: &str, block: &mut Block)
if height.is_empty() == false {
let params = &format!("[{}, null, null]", height)[..];
let resp = call("get_block", params, "foreign").await?;
let resp = call("get_block", params, "1", "foreign").await?;
if resp["result"]["Ok"].is_null() == false {
block.hash = resp["result"]["Ok"]["header"]["hash"].as_str().unwrap().to_string();
@@ -392,7 +393,7 @@ pub async fn get_block_header(hash: &str, height: &mut String)
-> Result<(), anyhow::Error> {
let params = &format!("[null, \"{}\", null]", hash)[..];
let resp = call("get_header", params, "foreign").await?;
let resp = call("get_header", params, "1", "foreign").await?;
if resp["result"]["Ok"].is_null() == false {
*height = resp["result"]["Ok"]["height"].to_string();
@@ -403,14 +404,26 @@ pub async fn get_block_header(hash: &str, height: &mut String)
// Get kernel.
pub async fn get_kernel(kernel: &str, height: &mut String)
pub async fn get_kernel(excess: &str, kernel: &mut Kernel)
-> Result<(), anyhow::Error> {
let params = &format!("[\"{}\", null, null]", kernel)[..];
let params = &format!("[\"{}\", null, null]", excess)[..];
let resp = call("get_kernel", params, "foreign").await?;
let resp = call("get_kernel", params, "1", "foreign").await?;
if resp["result"]["Ok"].is_null() == false {
*height = resp["result"]["Ok"]["height"].to_string();
kernel.height = resp["result"]["Ok"]["height"].to_string();
kernel.excess = resp["result"]["Ok"]["tx_kernel"]["excess"].as_str().unwrap().to_string();
if resp["result"]["Ok"]["tx_kernel"]["features"]["Plain"].is_null() == false {
kernel.ker_type = "Plain".to_string();
kernel.fee = format!("{}",
resp["result"]["Ok"]["tx_kernel"]["features"]["Plain"]["fee"]
.to_string().parse::<f64>().unwrap() / 1000000000.0);
} else {
kernel.ker_type = resp["result"]["Ok"]["tx_kernel"]["features"].as_str().unwrap().to_string();
kernel.fee = "ツ 0".to_string();
}
kernel.raw_data = serde_json::to_string_pretty(&resp).unwrap()
}
Ok(())
@@ -423,7 +436,7 @@ pub async fn get_block_kernels(height: &String, blocks: &mut Vec<Block>)
if height.is_empty() == false {
let params = &format!("[{}, {}, 720, false]", height.parse::<u64>().unwrap() - 720,
height)[..];
let resp = call("get_blocks", params, "foreign").await?;
let resp = call("get_blocks", params, "1", "foreign").await?;
for resp_block in resp["result"]["Ok"]["blocks"].as_array().unwrap() {
let mut block = Block::new();
@@ -541,7 +554,7 @@ pub async fn get_block_list_by_height(height: &str, blocks: &mut Vec<Block>,
let mut i = 0;
let height = height.to_string();
let resp = call("get_status", "[]", "owner").await?;
let resp = call("get_status", "[]", "1", "owner").await?;
if resp != Value::Null {
*latest_height = resp["result"]["Ok"]["tip"]["height"].to_string().parse::<u64>().unwrap();

View File

@@ -1,5 +1,5 @@
<!doctype html>
<html>
<html lang="en" class="h-100">
<head>
<title>Grin Blockchain Explorer</title>
<meta property="og:site_name" content="Grincoin.org (GRIN) Blockchain Explorer" />
@@ -78,7 +78,7 @@
{% block content %}{% endblock content %}
</div>
<footer class="shadow">
<footer class="shadow mt-auto">
<code>
<br>
<div class="container-fluid">

View File

@@ -0,0 +1,52 @@
{% extends "base" %}
{% block content %}
<code>
<div class="card">
<div class="card-body">
<div class="darkorange-text"><i class="bi bi-card-text"></i> KERNEL</div>
<br>
<div class="d-flex justify-content-between">
<div class="value-text">Excess&nbsp;</div>
<div class="value-text text-break text-end">{{ kernel.excess }}</div>
</div>
<br>
<div class="d-flex justify-content-between">
<div class="value-text">Block Height&nbsp;</div>
<div class="value-text text-end">
<a class="text-decoration-none" href="/block/{{ kernel.height }}">
{{ kernel.height }} <i class="bi bi-box-arrow-up-right"></i>
</a>
</div>
</div>
<br>
<div class="d-flex justify-content-between">
<div class="value-text">Type&nbsp;</div>
<div class="value-text text-end">{{ kernel.ker_type }}</div>
</div>
<br>
<div class="d-flex justify-content-between">
<div class="value-text">Fee&nbsp;</div>
<div class="value-text text-end">{{ kernel.fee }}</div>
</div>
</div>
</div>
<br>
<div class="card">
<div class="card-body" align="left">
<div class="darkorange-text"><i class="bi bi-layout-text-sidebar-reverse"></i> RAW DATA</div>
<br>
<div class="value-text">{{ kernel.raw_data }}</div>
</div>
</div>
<br>
</code>
{% endblock %}