mirror of
https://github.com/transatoshi-mw/grin-explorer.git
synced 2025-10-21 13:33:41 +00:00
93
Cargo.lock
generated
93
Cargo.lock
generated
@@ -41,6 +41,55 @@ dependencies = [
|
|||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anstream"
|
||||||
|
version = "0.6.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b"
|
||||||
|
dependencies = [
|
||||||
|
"anstyle",
|
||||||
|
"anstyle-parse",
|
||||||
|
"anstyle-query",
|
||||||
|
"anstyle-wincon",
|
||||||
|
"colorchoice",
|
||||||
|
"is_terminal_polyfill",
|
||||||
|
"utf8parse",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anstyle"
|
||||||
|
version = "1.0.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anstyle-parse"
|
||||||
|
version = "0.2.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4"
|
||||||
|
dependencies = [
|
||||||
|
"utf8parse",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anstyle-query"
|
||||||
|
version = "1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ad186efb764318d35165f1758e7dcef3b10628e26d41a44bc5550652e6804391"
|
||||||
|
dependencies = [
|
||||||
|
"windows-sys 0.52.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anstyle-wincon"
|
||||||
|
version = "3.0.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19"
|
||||||
|
dependencies = [
|
||||||
|
"anstyle",
|
||||||
|
"windows-sys 0.52.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "anyhow"
|
name = "anyhow"
|
||||||
version = "1.0.86"
|
version = "1.0.86"
|
||||||
@@ -234,6 +283,12 @@ dependencies = [
|
|||||||
"phf_codegen",
|
"phf_codegen",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "colorchoice"
|
||||||
|
version = "1.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "colored"
|
name = "colored"
|
||||||
version = "2.1.0"
|
version = "2.1.0"
|
||||||
@@ -482,6 +537,29 @@ dependencies = [
|
|||||||
"cfg-if",
|
"cfg-if",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "env_filter"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a009aa4810eb158359dda09d0c87378e4bbb89b5a801f016885a4707ba24f7ea"
|
||||||
|
dependencies = [
|
||||||
|
"log",
|
||||||
|
"regex",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "env_logger"
|
||||||
|
version = "0.11.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "38b35839ba51819680ba087cd351788c9a3c476841207e0b8cee0b04722343b9"
|
||||||
|
dependencies = [
|
||||||
|
"anstream",
|
||||||
|
"anstyle",
|
||||||
|
"env_filter",
|
||||||
|
"humantime",
|
||||||
|
"log",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "equivalent"
|
name = "equivalent"
|
||||||
version = "1.0.1"
|
version = "1.0.1"
|
||||||
@@ -736,13 +814,14 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "grin-explorer"
|
name = "grin-explorer"
|
||||||
version = "0.1.4"
|
version = "0.1.5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"chrono",
|
"chrono",
|
||||||
"colored",
|
"colored",
|
||||||
"config",
|
"config",
|
||||||
"either",
|
"either",
|
||||||
|
"env_logger",
|
||||||
"fs_extra",
|
"fs_extra",
|
||||||
"futures",
|
"futures",
|
||||||
"humantime",
|
"humantime",
|
||||||
@@ -982,6 +1061,12 @@ dependencies = [
|
|||||||
"windows-sys 0.52.0",
|
"windows-sys 0.52.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "is_terminal_polyfill"
|
||||||
|
version = "1.70.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "itoa"
|
name = "itoa"
|
||||||
version = "1.0.11"
|
version = "1.0.11"
|
||||||
@@ -2540,6 +2625,12 @@ dependencies = [
|
|||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "utf8parse"
|
||||||
|
version = "0.2.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "valuable"
|
name = "valuable"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "grin-explorer"
|
name = "grin-explorer"
|
||||||
version = "0.1.4"
|
version = "0.1.5"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
@@ -20,6 +20,7 @@ lazy_static = "1.4.0"
|
|||||||
shellexpand = "3.1.0"
|
shellexpand = "3.1.0"
|
||||||
either = "1.11.0"
|
either = "1.11.0"
|
||||||
anyhow = "1.0.86"
|
anyhow = "1.0.86"
|
||||||
|
env_logger = "0.11.3"
|
||||||
|
|
||||||
[dependencies.reqwest]
|
[dependencies.reqwest]
|
||||||
version = "0.11.23"
|
version = "0.11.23"
|
||||||
|
@@ -7,20 +7,38 @@ port = "3413"
|
|||||||
# Node protocol. Either HTTP or HTTPS.
|
# Node protocol. Either HTTP or HTTPS.
|
||||||
proto = "http"
|
proto = "http"
|
||||||
|
|
||||||
# API username.
|
# API username. Comment out if user is not required.
|
||||||
user = "grin"
|
user = "grin"
|
||||||
|
|
||||||
# API secret path.
|
# API secret path. Comment out if secret is not required.
|
||||||
api_secret_path = "~/.grin/main/.api_secret"
|
api_secret_path = "~/.grin/main/.api_secret"
|
||||||
|
|
||||||
# Foreign API secret path.
|
# Foreign API secret path. Comment out if secret is not required.
|
||||||
foreign_api_secret_path = "~/.grin/main/.foreign_api_secret"
|
foreign_api_secret_path = "~/.grin/main/.foreign_api_secret"
|
||||||
|
|
||||||
# Path to Grin directory.
|
# Path to Grin directory.
|
||||||
grin_dir = "~/.grin"
|
grin_dir = "~/.grin"
|
||||||
|
|
||||||
# CoinGecko API on/off switch.
|
# Enable or disable CoinGecko API.
|
||||||
coingecko_api = "on"
|
coingecko_api = "enabled"
|
||||||
|
|
||||||
|
# Enable or disable node POST API public access.
|
||||||
|
public_api = "enabled"
|
||||||
|
|
||||||
|
|
||||||
|
# Grinnode config
|
||||||
|
# ip = "grinnode.live"
|
||||||
|
# port = "3413"
|
||||||
|
# proto = "https"
|
||||||
|
# coingecko_api = "enabled"
|
||||||
|
# public_api = "enabled"
|
||||||
|
|
||||||
|
|
||||||
|
# Grincoin config
|
||||||
|
# ip = "grincoin.org"
|
||||||
|
# proto = "https"
|
||||||
|
# coingecko_api = "enabled"
|
||||||
|
# public_api = "enabled"
|
||||||
|
|
||||||
|
|
||||||
# Testnet config
|
# Testnet config
|
||||||
@@ -31,5 +49,6 @@ coingecko_api = "on"
|
|||||||
# api_secret_path = "~/.grin/test/.api_secret"
|
# api_secret_path = "~/.grin/test/.api_secret"
|
||||||
# foreign_api_secret_path = "~/.grin/test/.foreign_api_secret"
|
# foreign_api_secret_path = "~/.grin/test/.foreign_api_secret"
|
||||||
# grin_dir = "~/.grin"
|
# grin_dir = "~/.grin"
|
||||||
# coingecko_api = "off"
|
# coingecko_api = "disabled"
|
||||||
|
# public_api = "enabled"
|
||||||
|
|
||||||
|
@@ -22,15 +22,14 @@ Grin is the very first, simple and fair MimbleWimble blockchain implementation.
|
|||||||
cd grin-explorer
|
cd grin-explorer
|
||||||
cargo build --release
|
cargo build --release
|
||||||
```
|
```
|
||||||
4. Run executable: `./target/release/grin-explorer`
|
4. Run executable: `RUST_LOG=rocket=warn,grin_explorer ./target/release/grin-explorer`
|
||||||
|
|
||||||
You will see the following output:
|
You will see the following output:
|
||||||
|
|
||||||
```
|
```
|
||||||
[ INFO ] Starting up Explorer.
|
[2024-06-19T13:12:34Z INFO grin_explorer] starting up.
|
||||||
[ INFO ] Starting up Rocket engine.
|
[2024-06-19T13:12:34Z WARN rocket::launch] 🚀 Rocket has launched from http://127.0.0.1:8000
|
||||||
🚀 Rocket has launched from http://127.0.0.1:8000
|
[2024-06-19T13:12:34Z INFO grin_explorer] ready.
|
||||||
[ OK ] Explorer Ready.
|
|
||||||
```
|
```
|
||||||
|
|
||||||
5. Open explorer in your browser: http://127.0.0.1:8000
|
5. Open explorer in your browser: http://127.0.0.1:8000
|
||||||
|
@@ -1,6 +1,5 @@
|
|||||||
[default]
|
[default]
|
||||||
address = "127.0.0.1"
|
address = "127.0.0.1"
|
||||||
log_level = "critical"
|
|
||||||
|
|
||||||
# Uncomment and change default port number (8000) if another instance of the explorer is needed to run.
|
# Uncomment and change default port number (8000) if another instance of the explorer is needed to run.
|
||||||
# E.g. Mainnet (8000) and Testnet (8001) instances.
|
# E.g. Mainnet (8000) and Testnet (8001) instances.
|
||||||
|
27
src/data.rs
27
src/data.rs
@@ -35,8 +35,6 @@ pub struct Dashboard {
|
|||||||
// mempool
|
// mempool
|
||||||
pub txns: String,
|
pub txns: String,
|
||||||
pub stem: String,
|
pub stem: String,
|
||||||
// coingecko api
|
|
||||||
pub cg_api: String,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Dashboard {
|
impl Dashboard {
|
||||||
@@ -66,7 +64,6 @@ impl Dashboard {
|
|||||||
breakeven_cost: String::new(),
|
breakeven_cost: String::new(),
|
||||||
txns: String::new(),
|
txns: String::new(),
|
||||||
stem: String::new(),
|
stem: String::new(),
|
||||||
cg_api: String::new(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -170,6 +167,7 @@ pub struct ExplorerConfig {
|
|||||||
pub api_secret: String,
|
pub api_secret: String,
|
||||||
pub foreign_api_secret: String,
|
pub foreign_api_secret: String,
|
||||||
pub coingecko_api: String,
|
pub coingecko_api: String,
|
||||||
|
pub public_api: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ExplorerConfig {
|
impl ExplorerConfig {
|
||||||
@@ -185,6 +183,29 @@ impl ExplorerConfig {
|
|||||||
api_secret: String::new(),
|
api_secret: String::new(),
|
||||||
foreign_api_secret: String::new(),
|
foreign_api_secret: String::new(),
|
||||||
coingecko_api: String::new(),
|
coingecko_api: String::new(),
|
||||||
|
public_api: String::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output data
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct Output {
|
||||||
|
pub height: String,
|
||||||
|
pub commit: String,
|
||||||
|
pub out_type: String,
|
||||||
|
pub status: String,
|
||||||
|
pub raw_data: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Output {
|
||||||
|
pub fn new() -> Output {
|
||||||
|
Output {
|
||||||
|
height: String::new(),
|
||||||
|
commit: String::new(),
|
||||||
|
out_type: String::new(),
|
||||||
|
status: String::new(),
|
||||||
|
raw_data: String::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
181
src/main.rs
181
src/main.rs
@@ -5,7 +5,6 @@ use rocket::fs::FileServer;
|
|||||||
use rocket::State;
|
use rocket::State;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use colored::Colorize;
|
|
||||||
use rocket::tokio;
|
use rocket::tokio;
|
||||||
use rocket::response::Redirect;
|
use rocket::response::Redirect;
|
||||||
use either::Either;
|
use either::Either;
|
||||||
@@ -19,6 +18,8 @@ use crate::data::Dashboard;
|
|||||||
use crate::data::Block;
|
use crate::data::Block;
|
||||||
use crate::data::Transactions;
|
use crate::data::Transactions;
|
||||||
use crate::data::Kernel;
|
use crate::data::Kernel;
|
||||||
|
use crate::data::Output;
|
||||||
|
use crate::requests::CONFIG;
|
||||||
|
|
||||||
|
|
||||||
// Rendering main (Dashboard) page.
|
// Rendering main (Dashboard) page.
|
||||||
@@ -30,7 +31,7 @@ fn index(dashboard: &State<Arc<Mutex<Dashboard>>>) -> Template {
|
|||||||
route: "index",
|
route: "index",
|
||||||
node_ver: &data.node_ver,
|
node_ver: &data.node_ver,
|
||||||
proto_ver: &data.proto_ver,
|
proto_ver: &data.proto_ver,
|
||||||
cg_api: &data.cg_api,
|
cg_api: CONFIG.coingecko_api.clone(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -39,7 +40,8 @@ fn index(dashboard: &State<Arc<Mutex<Dashboard>>>) -> Template {
|
|||||||
#[get("/block_list")]
|
#[get("/block_list")]
|
||||||
fn block_list() -> Template {
|
fn block_list() -> Template {
|
||||||
Template::render("block_list", context! {
|
Template::render("block_list", context! {
|
||||||
route: "block_list",
|
route: "block_list",
|
||||||
|
cg_api: CONFIG.coingecko_api.clone(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,11 +62,13 @@ async fn block_list_by_height(input_height: &str) -> Template {
|
|||||||
|
|
||||||
if index >= height {
|
if index >= height {
|
||||||
Template::render("block_list", context! {
|
Template::render("block_list", context! {
|
||||||
route: "block_list",
|
route: "block_list",
|
||||||
|
cg_api: CONFIG.coingecko_api.clone(),
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
Template::render("block_list", context! {
|
Template::render("block_list", context! {
|
||||||
route: "block_list_by_height",
|
route: "block_list_by_height",
|
||||||
|
cg_api: CONFIG.coingecko_api.clone(),
|
||||||
index,
|
index,
|
||||||
blocks,
|
blocks,
|
||||||
height,
|
height,
|
||||||
@@ -72,7 +76,8 @@ async fn block_list_by_height(input_height: &str) -> Template {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Template::render("block_list", context! {
|
Template::render("block_list", context! {
|
||||||
route: "block_list",
|
route: "block_list",
|
||||||
|
cg_api: CONFIG.coingecko_api.clone(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -88,14 +93,16 @@ async fn block_details_by_height(height: &str) -> Template {
|
|||||||
|
|
||||||
if block.height.is_empty() == false {
|
if block.height.is_empty() == false {
|
||||||
return Template::render("block_details", context! {
|
return Template::render("block_details", context! {
|
||||||
route: "block_details",
|
route: "block_details",
|
||||||
|
cg_api: CONFIG.coingecko_api.clone(),
|
||||||
block,
|
block,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Template::render("error", context! {
|
Template::render("error", context! {
|
||||||
route: "error",
|
route: "error",
|
||||||
|
cg_api: CONFIG.coingecko_api.clone(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -114,7 +121,8 @@ async fn block_header_by_hash(hash: &str) -> Either<Template, Redirect> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return Either::Left(Template::render("error", context! {
|
return Either::Left(Template::render("error", context! {
|
||||||
route: "error",
|
route: "error",
|
||||||
|
cg_api: CONFIG.coingecko_api.clone(),
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -128,13 +136,37 @@ async fn kernel(excess: &str) -> Template {
|
|||||||
|
|
||||||
if kernel.excess.is_empty() == false {
|
if kernel.excess.is_empty() == false {
|
||||||
return Template::render("kernel", context! {
|
return Template::render("kernel", context! {
|
||||||
route: "kernel",
|
route: "kernel",
|
||||||
|
cg_api: CONFIG.coingecko_api.clone(),
|
||||||
kernel,
|
kernel,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return Template::render("error", context! {
|
return Template::render("error", context! {
|
||||||
route: "error",
|
route: "error",
|
||||||
|
cg_api: CONFIG.coingecko_api.clone(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Rendering page for a specified output.
|
||||||
|
#[get("/output/<commit>")]
|
||||||
|
async fn output(commit: &str) -> Template {
|
||||||
|
let mut output = Output::new();
|
||||||
|
|
||||||
|
let _ = requests::get_output(&commit, &mut output).await;
|
||||||
|
|
||||||
|
if output.commit.is_empty() == false {
|
||||||
|
return Template::render("output", context! {
|
||||||
|
route: "output",
|
||||||
|
cg_api: CONFIG.coingecko_api.clone(),
|
||||||
|
output,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return Template::render("error", context! {
|
||||||
|
route: "error",
|
||||||
|
cg_api: CONFIG.coingecko_api.clone(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -143,11 +175,14 @@ async fn kernel(excess: &str) -> Template {
|
|||||||
// Using Option<&str> to match '/search' query without input params.
|
// Using Option<&str> to match '/search' query without input params.
|
||||||
// https://github.com/rwf2/Rocket/issues/608
|
// https://github.com/rwf2/Rocket/issues/608
|
||||||
#[get("/search?<input>")]
|
#[get("/search?<input>")]
|
||||||
fn search(input: Option<&str>) -> Either<Template, Redirect> {
|
pub async fn search(input: Option<&str>) -> Either<Template, Redirect> {
|
||||||
// Unwrap Option and forward to Search page if no parameters
|
// Unwrap Option and forward to Search page if no parameters
|
||||||
let input = match input {
|
let input = match input {
|
||||||
Some(value) => value,
|
Some(value) => value,
|
||||||
None => return Either::Left(Template::render("search", context! { route: "search", })),
|
None => return Either::Left(Template::render("search", context! {
|
||||||
|
route: "search",
|
||||||
|
cg_api: CONFIG.coingecko_api.clone(),
|
||||||
|
})),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Check for valid chars
|
// Check for valid chars
|
||||||
@@ -161,46 +196,68 @@ fn search(input: Option<&str>) -> Either<Template, Redirect> {
|
|||||||
} else if input.len() == 64 {
|
} else if input.len() == 64 {
|
||||||
return Either::Right(Redirect::to(uri!(block_header_by_hash(input))));
|
return Either::Right(Redirect::to(uri!(block_header_by_hash(input))));
|
||||||
|
|
||||||
// Kernel
|
// Kernel or Unspent Output
|
||||||
} else if input.len() == 66 {
|
} else if input.len() == 66 {
|
||||||
return Either::Right(Redirect::to(uri!(kernel(input))));
|
// First search for Kernel.
|
||||||
|
// If found, redirect to Kernel page, otherwise search for Unspent Output.
|
||||||
|
// As we can't distinguish between Kernel and Output, this will produce a redundant
|
||||||
|
// get_kernel call, but will allow for better UI (no need to ask user to input the type
|
||||||
|
// of the search request).
|
||||||
|
let mut kernel = Kernel::new();
|
||||||
|
|
||||||
|
let _ = requests::get_kernel(&input, &mut kernel).await;
|
||||||
|
|
||||||
|
if kernel.excess.is_empty() == false {
|
||||||
|
// Here we are redirecting to kernel page and call get_kernel again there.
|
||||||
|
// Kernel page is a separate route and we want it to be accessed directly and
|
||||||
|
// via search functionality.
|
||||||
|
return Either::Right(Redirect::to(uri!(kernel(input))));
|
||||||
|
} else {
|
||||||
|
// If Kernel not found, then search for Unspent Output
|
||||||
|
return Either::Right(Redirect::to(uri!(output(input))));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Either::Left(Template::render("error", context! {
|
Either::Left(Template::render("error", context! {
|
||||||
route: "error",
|
route: "error",
|
||||||
|
cg_api: CONFIG.coingecko_api.clone(),
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Owner API.
|
// Owner API.
|
||||||
|
// Whitelisted methods: get_connected_peers, get_peers, get_status.
|
||||||
#[post("/v2/owner", data="<data>")]
|
#[post("/v2/owner", data="<data>")]
|
||||||
async fn api_owner(data: &str) -> String {
|
async fn api_owner(data: &str) -> String {
|
||||||
let result = serde_json::from_str(data);
|
if CONFIG.public_api == "enabled" {
|
||||||
|
let result = serde_json::from_str(data);
|
||||||
|
|
||||||
let v: Value = match result {
|
let v: Value = match result {
|
||||||
Ok(value) => value,
|
|
||||||
Err(_err) => return "{\"error\":\"bad syntax\"}".to_string(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let method = match v["method"].as_str() {
|
|
||||||
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(), v["id"].to_string().as_str(), "owner").await;
|
|
||||||
|
|
||||||
let result = match resp {
|
|
||||||
Ok(value) => value,
|
Ok(value) => value,
|
||||||
Err(_err) => return "{\"error\":\"rpc call failed\"}".to_string(),
|
Err(_err) => return "{\"error\":\"bad syntax\"}".to_string(),
|
||||||
};
|
};
|
||||||
|
|
||||||
return result.to_string();
|
let method = match v["method"].as_str() {
|
||||||
}
|
Some(value) => value,
|
||||||
|
_ => return "{\"error\":\"bad syntax\"}".to_string(),
|
||||||
|
};
|
||||||
|
|
||||||
|
if method == "get_connected_peers" || method == "get_peers" || method == "get_status" {
|
||||||
|
let resp = requests::call(method, v["params"].to_string().as_str(), v["id"].to_string().as_str(), "owner").await;
|
||||||
|
|
||||||
"{\"error\":\"not allowed\"}".to_string()
|
let result = match resp {
|
||||||
|
Ok(value) => value,
|
||||||
|
Err(_err) => return "{\"error\":\"rpc call failed\"}".to_string(),
|
||||||
|
};
|
||||||
|
|
||||||
|
return result.to_string();
|
||||||
|
}
|
||||||
|
|
||||||
|
"{\"error\":\"not allowed\"}".to_string()
|
||||||
|
} else {
|
||||||
|
"{\"error\":\"not allowed\"}".to_string()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -208,26 +265,30 @@ async fn api_owner(data: &str) -> String {
|
|||||||
// All methods are whitelisted.
|
// All methods are whitelisted.
|
||||||
#[post("/v2/foreign", data="<data>")]
|
#[post("/v2/foreign", data="<data>")]
|
||||||
async fn api_foreign(data: &str) -> String {
|
async fn api_foreign(data: &str) -> String {
|
||||||
let result = serde_json::from_str(data);
|
if CONFIG.public_api == "enabled" {
|
||||||
|
let result = serde_json::from_str(data);
|
||||||
|
|
||||||
let v: Value = match result {
|
let v: Value = match result {
|
||||||
Ok(value) => value,
|
Ok(value) => value,
|
||||||
Err(_err) => return "{\"error\":\"bad syntax\"}".to_string(),
|
Err(_err) => return "{\"error\":\"bad syntax\"}".to_string(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let method = match v["method"].as_str() {
|
let method = match v["method"].as_str() {
|
||||||
Some(value) => value,
|
Some(value) => value,
|
||||||
_ => return "{\"error\":\"bad syntax\"}".to_string(),
|
_ => return "{\"error\":\"bad syntax\"}".to_string(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let resp = requests::call(method, v["params"].to_string().as_str(), v["id"].to_string().as_str(), "foreign").await;
|
let resp = requests::call(method, v["params"].to_string().as_str(), v["id"].to_string().as_str(), "foreign").await;
|
||||||
|
|
||||||
let result = match resp {
|
let result = match resp {
|
||||||
Ok(value) => value,
|
Ok(value) => value,
|
||||||
Err(_err) => return "{\"error\":\"rpc call failed\"}".to_string(),
|
Err(_err) => return "{\"error\":\"rpc call failed\"}".to_string(),
|
||||||
};
|
};
|
||||||
|
|
||||||
result.to_string()
|
return result.to_string();
|
||||||
|
} else {
|
||||||
|
"{\"error\":\"not allowed\"}".to_string()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -369,7 +430,11 @@ fn last_block_age(blocks: &State<Arc<Mutex<Vec<Block>>>>) -> String {
|
|||||||
fn disk_usage(dashboard: &State<Arc<Mutex<Dashboard>>>) -> String {
|
fn disk_usage(dashboard: &State<Arc<Mutex<Dashboard>>>) -> String {
|
||||||
let data = dashboard.lock().unwrap();
|
let data = dashboard.lock().unwrap();
|
||||||
|
|
||||||
format!("{} GB", data.disk_usage)
|
if data.disk_usage.is_empty() == false {
|
||||||
|
return format!("{} GB", data.disk_usage);
|
||||||
|
} else {
|
||||||
|
return format!("<i class=\"bi bi-x-lg\"></i>");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -575,7 +640,9 @@ fn block_list_index(dashboard: &State<Arc<Mutex<Dashboard>>>) -> String {
|
|||||||
// Main
|
// Main
|
||||||
#[rocket::main]
|
#[rocket::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
println!("{} Starting up Explorer.", "[ INFO ]".cyan());
|
env_logger::init();
|
||||||
|
|
||||||
|
info!("starting up.");
|
||||||
|
|
||||||
let dash = Arc::new(Mutex::new(Dashboard::new()));
|
let dash = Arc::new(Mutex::new(Dashboard::new()));
|
||||||
let dash_clone = dash.clone();
|
let dash_clone = dash.clone();
|
||||||
@@ -595,12 +662,12 @@ async fn main() {
|
|||||||
Ok(_v) => {
|
Ok(_v) => {
|
||||||
if ready == false {
|
if ready == false {
|
||||||
ready = true;
|
ready = true;
|
||||||
println!("{} Explorer Ready.", "[ OK ]".green());
|
info!("ready.");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
ready = false;
|
ready = false;
|
||||||
println!("{} {}.", "[ ERROR ]".red(), e);
|
error!("{}", e);
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -608,8 +675,6 @@ async fn main() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
println!("{} Starting up Rocket engine.", "[ INFO ]".cyan());
|
|
||||||
|
|
||||||
// Starting Rocket engine.
|
// Starting Rocket engine.
|
||||||
let _ = rocket::build()
|
let _ = rocket::build()
|
||||||
.manage(dash)
|
.manage(dash)
|
||||||
@@ -624,7 +689,7 @@ async fn main() {
|
|||||||
block_weight, block_details_by_height, block_header_by_hash,
|
block_weight, block_details_by_height, block_header_by_hash,
|
||||||
soft_supply, production_cost, reward_ratio, breakeven_cost,
|
soft_supply, production_cost, reward_ratio, breakeven_cost,
|
||||||
last_block_age, block_list_by_height, block_list_index, search, kernel,
|
last_block_age, block_list_by_height, block_list_index, search, kernel,
|
||||||
api_owner, api_foreign])
|
output, api_owner, api_foreign])
|
||||||
.mount("/static", FileServer::from("static"))
|
.mount("/static", FileServer::from("static"))
|
||||||
.attach(Template::fairing())
|
.attach(Template::fairing())
|
||||||
.launch()
|
.launch()
|
||||||
|
136
src/requests.rs
136
src/requests.rs
@@ -16,12 +16,13 @@ use crate::data::Dashboard;
|
|||||||
use crate::data::Block;
|
use crate::data::Block;
|
||||||
use crate::data::Transactions;
|
use crate::data::Transactions;
|
||||||
use crate::data::ExplorerConfig;
|
use crate::data::ExplorerConfig;
|
||||||
use crate::Kernel;
|
use crate::data::Kernel;
|
||||||
|
use crate::data::Output;
|
||||||
|
|
||||||
|
|
||||||
// Static explorer config structure
|
// Static explorer config structure
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
static ref CONFIG: ExplorerConfig = {
|
pub static ref CONFIG: ExplorerConfig = {
|
||||||
let mut cfg = ExplorerConfig::new();
|
let mut cfg = ExplorerConfig::new();
|
||||||
let settings = Config::builder().add_source(config::File::with_name("Explorer"))
|
let settings = Config::builder().add_source(config::File::with_name("Explorer"))
|
||||||
.build().unwrap();
|
.build().unwrap();
|
||||||
@@ -38,15 +39,22 @@ lazy_static! {
|
|||||||
"foreign_api_secret_path" => cfg.foreign_api_secret_path = value,
|
"foreign_api_secret_path" => cfg.foreign_api_secret_path = value,
|
||||||
"grin_dir" => cfg.grin_dir = value,
|
"grin_dir" => cfg.grin_dir = value,
|
||||||
"coingecko_api" => cfg.coingecko_api = value,
|
"coingecko_api" => cfg.coingecko_api = value,
|
||||||
|
"public_api" => cfg.public_api = value,
|
||||||
_ => println!("{} Unknown config setting '{}'.", "[ ERROR ]".red(), name),
|
_ => println!("{} Unknown config setting '{}'.", "[ ERROR ]".red(), name),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg.api_secret = fs::read_to_string(format!("{}",
|
if cfg.api_secret_path.is_empty() == false {
|
||||||
shellexpand::tilde(&cfg.api_secret_path))).unwrap();
|
cfg.api_secret = fs::read_to_string(format!("{}", shellexpand::tilde(&cfg.api_secret_path))).unwrap();
|
||||||
cfg.foreign_api_secret = fs::read_to_string(format!("{}",
|
}
|
||||||
shellexpand::tilde(&cfg.foreign_api_secret_path))).unwrap();
|
|
||||||
cfg.grin_dir = format!("{}", shellexpand::tilde(&cfg.grin_dir));
|
if cfg.foreign_api_secret_path.is_empty() == false {
|
||||||
|
cfg.foreign_api_secret = fs::read_to_string(format!("{}", shellexpand::tilde(&cfg.foreign_api_secret_path))).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
if cfg.grin_dir.is_empty() == false {
|
||||||
|
cfg.grin_dir = format!("{}", shellexpand::tilde(&cfg.grin_dir));
|
||||||
|
}
|
||||||
|
|
||||||
cfg
|
cfg
|
||||||
};
|
};
|
||||||
@@ -58,13 +66,16 @@ pub async fn call(method: &str, params: &str, id: &str, rpc_type: &str) -> Resul
|
|||||||
let rpc_url;
|
let rpc_url;
|
||||||
let secret;
|
let secret;
|
||||||
|
|
||||||
if rpc_type == "owner" {
|
if CONFIG.port.is_empty() == false {
|
||||||
rpc_url = format!("{}://{}:{}/v2/owner", CONFIG.proto, CONFIG.ip, CONFIG.port);
|
rpc_url = format!("{}://{}:{}/v2/{}", CONFIG.proto, CONFIG.ip, CONFIG.port, rpc_type);
|
||||||
secret = CONFIG.api_secret.clone();
|
} else {
|
||||||
|
rpc_url = format!("{}://{}/v2/{}", CONFIG.proto, CONFIG.ip, rpc_type);
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
rpc_url = format!("{}://{}:{}/v2/foreign", CONFIG.proto, CONFIG.ip, CONFIG.port);
|
if rpc_type == "owner" {
|
||||||
secret = CONFIG.foreign_api_secret.clone();
|
secret = CONFIG.api_secret.clone();
|
||||||
|
} else {
|
||||||
|
secret = CONFIG.foreign_api_secret.clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
let client = reqwest::Client::new();
|
let client = reqwest::Client::new();
|
||||||
@@ -75,6 +86,11 @@ pub async fn call(method: &str, params: &str, id: &str, rpc_type: &str) -> Resul
|
|||||||
.send()
|
.send()
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
match result.error_for_status_ref() {
|
||||||
|
Ok(_res) => (),
|
||||||
|
Err(err) => { error!("rpc failed, status code: {:?}", err.status().unwrap()); },
|
||||||
|
}
|
||||||
|
|
||||||
let val: Value = serde_json::from_str(&result.text().await.unwrap())?;
|
let val: Value = serde_json::from_str(&result.text().await.unwrap())?;
|
||||||
|
|
||||||
Ok(val)
|
Ok(val)
|
||||||
@@ -94,9 +110,6 @@ pub async fn get_status(dashboard: Arc<Mutex<Dashboard>>) -> Result<(), anyhow::
|
|||||||
data.proto_ver = resp["result"]["Ok"]["protocol_version"].to_string();
|
data.proto_ver = resp["result"]["Ok"]["protocol_version"].to_string();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Also set cg_api value
|
|
||||||
data.cg_api = CONFIG.coingecko_api.clone();
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -150,7 +163,7 @@ pub async fn get_market(dashboard: Arc<Mutex<Dashboard>>) -> Result<(), Error> {
|
|||||||
let result;
|
let result;
|
||||||
let mut val = Value::Null;
|
let mut val = Value::Null;
|
||||||
|
|
||||||
if CONFIG.coingecko_api == "on" {
|
if CONFIG.coingecko_api == "enabled" {
|
||||||
client = reqwest::Client::new();
|
client = reqwest::Client::new();
|
||||||
result = client.get("https://api.coingecko.com/api/v3/simple/price?ids=grin&vs_currencies=usd%2Cbtc&include_24hr_vol=true").send().await?;
|
result = client.get("https://api.coingecko.com/api/v3/simple/price?ids=grin&vs_currencies=usd%2Cbtc&include_24hr_vol=true").send().await?;
|
||||||
val = serde_json::from_str(&result.text().await.unwrap()).unwrap();
|
val = serde_json::from_str(&result.text().await.unwrap()).unwrap();
|
||||||
@@ -170,23 +183,18 @@ pub async fn get_market(dashboard: Arc<Mutex<Dashboard>>) -> Result<(), Error> {
|
|||||||
data.supply = supply.to_formatted_string(&Locale::en);
|
data.supply = supply.to_formatted_string(&Locale::en);
|
||||||
|
|
||||||
// https://john-tromp.medium.com/a-case-for-using-soft-total-supply-1169a188d153
|
// https://john-tromp.medium.com/a-case-for-using-soft-total-supply-1169a188d153
|
||||||
data.soft_supply = format!("{:.2}",
|
data.soft_supply = format!("{:.2}", supply.to_string().parse::<f64>().unwrap() / 3150000000.0 * 100.0);
|
||||||
supply.to_string().parse::<f64>().unwrap() / 3150000000.0 * 100.0);
|
|
||||||
|
|
||||||
if CONFIG.coingecko_api == "on" && val != Value::Null {
|
if CONFIG.coingecko_api == "enabled" && val != Value::Null {
|
||||||
// Check if CoingGecko API returned error
|
// Check if CoingGecko API returned error
|
||||||
if let Some(status) = val.get("status") {
|
if let Some(status) = val.get("status") {
|
||||||
println!("{} {}.", "[ WARNING ]".yellow(),
|
warn!("{}", status["error_message"].as_str().unwrap().to_string());
|
||||||
status["error_message"].as_str().unwrap().to_string());
|
|
||||||
} else {
|
} else {
|
||||||
data.price_usd = format!("{:.3}", val["grin"]["usd"].to_string().parse::<f64>()
|
data.price_usd = format!("{:.3}", val["grin"]["usd"].to_string().parse::<f64>().unwrap());
|
||||||
.unwrap());
|
data.price_btc = format!("{:.8}", val["grin"]["btc"].to_string().parse::<f64>().unwrap());
|
||||||
data.price_btc = format!("{:.8}", val["grin"]["btc"].to_string().parse::<f64>()
|
|
||||||
.unwrap());
|
|
||||||
data.volume_usd = (val["grin"]["usd_24h_vol"].to_string().parse::<f64>().unwrap() as u64)
|
data.volume_usd = (val["grin"]["usd_24h_vol"].to_string().parse::<f64>().unwrap() as u64)
|
||||||
.to_formatted_string(&Locale::en);
|
.to_formatted_string(&Locale::en);
|
||||||
data.volume_btc = format!("{:.2}", val["grin"]["btc_24h_vol"].to_string().parse::<f64>()
|
data.volume_btc = format!("{:.2}", val["grin"]["btc_24h_vol"].to_string().parse::<f64>().unwrap());
|
||||||
.unwrap());
|
|
||||||
data.cap_usd = (((supply as f64) * data.price_usd.parse::<f64>().unwrap()) as u64)
|
data.cap_usd = (((supply as f64) * data.price_usd.parse::<f64>().unwrap()) as u64)
|
||||||
.to_formatted_string(&Locale::en);
|
.to_formatted_string(&Locale::en);
|
||||||
data.cap_btc = (((supply as f64) * data.price_btc.parse::<f64>().unwrap()) as u64)
|
data.cap_btc = (((supply as f64) * data.price_btc.parse::<f64>().unwrap()) as u64)
|
||||||
@@ -202,16 +210,24 @@ pub async fn get_market(dashboard: Arc<Mutex<Dashboard>>) -> Result<(), Error> {
|
|||||||
// Collecting: disk_usage.
|
// Collecting: disk_usage.
|
||||||
pub fn get_disk_usage(dashboard: Arc<Mutex<Dashboard>>) -> Result<(), Error> {
|
pub fn get_disk_usage(dashboard: Arc<Mutex<Dashboard>>) -> Result<(), Error> {
|
||||||
let mut data = dashboard.lock().unwrap();
|
let mut data = dashboard.lock().unwrap();
|
||||||
let chain_data;
|
let chain_dir;
|
||||||
|
|
||||||
if CONFIG.coingecko_api == "on" {
|
if CONFIG.coingecko_api == "enabled" {
|
||||||
chain_data = format!("{}/main/chain_data", CONFIG.grin_dir);
|
chain_dir = format!("{}/main/chain_data", CONFIG.grin_dir);
|
||||||
} else {
|
} else {
|
||||||
chain_data = format!("{}/test/chain_data", CONFIG.grin_dir);
|
chain_dir = format!("{}/test/chain_data", CONFIG.grin_dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
data.disk_usage = format!("{:.2}", (get_size(chain_data).unwrap() as f64)
|
match get_size(chain_dir.clone()) {
|
||||||
/ 1000.0 / 1000.0 / 1000.0);
|
Ok(chain_size) => data.disk_usage = format!("{:.2}", (chain_size as f64) / 1000.0 / 1000.0 / 1000.0),
|
||||||
|
Err(e) => {
|
||||||
|
if CONFIG.ip == "127.0.0.1" || CONFIG.ip == "0.0.0.0" {
|
||||||
|
error!("{}: \"{}\"", e, chain_dir);
|
||||||
|
} else {
|
||||||
|
// Ignore error for external node connection
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -224,8 +240,7 @@ pub async fn get_mining_stats(dashboard: Arc<Mutex<Dashboard>>) -> Result<(), an
|
|||||||
|
|
||||||
if height.is_empty() == false && height.parse::<u64>().unwrap() > 1440 {
|
if height.is_empty() == false && height.parse::<u64>().unwrap() > 1440 {
|
||||||
let params1 = &format!("[{}, null, null]", height)[..];
|
let params1 = &format!("[{}, null, null]", height)[..];
|
||||||
let params2 = &format!("[{}, null, null]", height.parse::<u64>().unwrap()
|
let params2 = &format!("[{}, null, null]", height.parse::<u64>().unwrap() - difficulty_window)[..];
|
||||||
- difficulty_window)[..];
|
|
||||||
let resp1 = call("get_block", params1, "1", "foreign").await?;
|
let resp1 = call("get_block", params1, "1", "foreign").await?;
|
||||||
let resp2 = call("get_block", params2, "1", "foreign").await?;
|
let resp2 = call("get_block", params2, "1", "foreign").await?;
|
||||||
|
|
||||||
@@ -243,9 +258,9 @@ pub async fn get_mining_stats(dashboard: Arc<Mutex<Dashboard>>) -> Result<(), an
|
|||||||
// https://forum.grin.mw/t/difference-c31-and-c32-c33/7018/7
|
// https://forum.grin.mw/t/difference-c31-and-c32-c33/7018/7
|
||||||
let hashrate = (net_diff as f64) * 42.0 / 60.0 / 16384.0;
|
let hashrate = (net_diff as f64) * 42.0 / 60.0 / 16384.0;
|
||||||
|
|
||||||
// KG/s
|
// kG/s
|
||||||
if hashrate > 1000.0 {
|
if hashrate > 1000.0 {
|
||||||
data.hashrate = format!("{:.2} KG/s", hashrate / 1000.0);
|
data.hashrate = format!("{:.2} kG/s", hashrate / 1000.0);
|
||||||
// G/s
|
// G/s
|
||||||
} else {
|
} else {
|
||||||
data.hashrate = format!("{:.2} G/s", hashrate);
|
data.hashrate = format!("{:.2} G/s", hashrate);
|
||||||
@@ -253,7 +268,7 @@ pub async fn get_mining_stats(dashboard: Arc<Mutex<Dashboard>>) -> Result<(), an
|
|||||||
|
|
||||||
data.difficulty = net_diff.to_string();
|
data.difficulty = net_diff.to_string();
|
||||||
|
|
||||||
if CONFIG.coingecko_api == "on" {
|
if CONFIG.coingecko_api == "enabled" {
|
||||||
// Calculating G1-mini production per hour
|
// Calculating G1-mini production per hour
|
||||||
let coins_per_hour = 1.2 / hashrate * 60.0 * 60.0;
|
let coins_per_hour = 1.2 / hashrate * 60.0 * 60.0;
|
||||||
|
|
||||||
@@ -261,10 +276,12 @@ pub async fn get_mining_stats(dashboard: Arc<Mutex<Dashboard>>) -> Result<(), an
|
|||||||
// Assuming $0.07 per kW/h
|
// Assuming $0.07 per kW/h
|
||||||
data.production_cost = format!("{:.3}", 120.0 / 1000.0 * 0.07 * (1.0 / coins_per_hour));
|
data.production_cost = format!("{:.3}", 120.0 / 1000.0 * 0.07 * (1.0 / coins_per_hour));
|
||||||
|
|
||||||
data.reward_ratio = format!("{:.2}", data.price_usd.parse::<f64>().unwrap()
|
if data.price_usd.is_empty() == false {
|
||||||
|
data.reward_ratio = format!("{:.2}", data.price_usd.parse::<f64>().unwrap()
|
||||||
/ data.production_cost.parse::<f64>().unwrap());
|
/ data.production_cost.parse::<f64>().unwrap());
|
||||||
data.breakeven_cost = format!("{:.2}", data.price_usd.parse::<f64>().unwrap()
|
data.breakeven_cost = format!("{:.2}", data.price_usd.parse::<f64>().unwrap()
|
||||||
/ (120.0 / 1000.0 * (1.0 / coins_per_hour)));
|
/ (120.0 / 1000.0 * (1.0 / coins_per_hour)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -403,6 +420,41 @@ pub async fn get_block_header(hash: &str, height: &mut String)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Get output.
|
||||||
|
pub async fn get_output(commit: &str, output: &mut Output) -> Result<(), anyhow::Error> {
|
||||||
|
// First check whether output is broadcasted but not confirmed yet (in mempool)
|
||||||
|
let mut resp = call("get_unconfirmed_transactions", "[]", "1", "foreign").await?;
|
||||||
|
|
||||||
|
if resp["result"]["Ok"].is_null() == false {
|
||||||
|
for tx in resp["result"]["Ok"].as_array().unwrap() {
|
||||||
|
for out in tx["tx"]["body"]["outputs"].as_array().unwrap() {
|
||||||
|
if out["commit"].as_str().unwrap() == commit {
|
||||||
|
// Only Plain outputs in the mempool
|
||||||
|
output.out_type = "Plain".to_string();
|
||||||
|
output.commit = out["commit"].as_str().unwrap().to_string();
|
||||||
|
output.status = "Unconfirmed".to_string();
|
||||||
|
// Found it, no need to continue
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let params = &format!("[[\"{}\"], null, null, true, true]", commit)[..];
|
||||||
|
|
||||||
|
resp = call("get_outputs", params, "1", "foreign").await?;
|
||||||
|
|
||||||
|
if resp["result"]["Ok"][0].is_null() == false {
|
||||||
|
output.height = resp["result"]["Ok"][0]["block_height"].to_string();
|
||||||
|
output.commit = resp["result"]["Ok"][0]["commit"].as_str().unwrap().to_string();
|
||||||
|
output.out_type = resp["result"]["Ok"][0]["output_type"].as_str().unwrap().to_string();
|
||||||
|
output.raw_data = serde_json::to_string_pretty(&resp).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Get kernel.
|
// Get kernel.
|
||||||
pub async fn get_kernel(excess: &str, kernel: &mut Kernel) -> Result<(), anyhow::Error> {
|
pub async fn get_kernel(excess: &str, kernel: &mut Kernel) -> Result<(), anyhow::Error> {
|
||||||
// First check whether kernel is broadcasted but not confirmed yet (in mempool)
|
// First check whether kernel is broadcasted but not confirmed yet (in mempool)
|
||||||
|
@@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
<body class="d-flex flex-column min-vh-100 dark-mode">
|
<body class="d-flex flex-column min-vh-100 dark-mode">
|
||||||
|
|
||||||
<nav class="navbar bg-style navbar-expand-lg shadow-sm py-0">
|
<nav class="navbar bg-style navbar-expand-lg shadow-sm py-0">
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
<code><a class="navbar-brand fs-2" href="/"><svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 191 191" height="35" width="35" style="enable-background:new 0 0 191 191;" xml:space="preserve"><style type="text/css">.st0{fill:#f2a900;}</style><circle cx="95.5" cy="95.5" r="95.5"/><circle class="st0" cx="95.3" cy="95.5" r="85.3"/><path d="M135.7,63.5c-2-4.6-3.9-13.6-9.1-15.6c-6.7-2.6-10.9,14.3-11.9,18.6h-1c-1.7-7.3-4-17.7-12-20c-3.7,15.6,3.9,32.5,11,46
|
<code><a class="navbar-brand fs-2" href="/"><svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 191 191" height="35" width="35" style="enable-background:new 0 0 191 191;" xml:space="preserve"><style type="text/css">.st0{fill:#f2a900;}</style><circle cx="95.5" cy="95.5" r="95.5"/><circle class="st0" cx="95.3" cy="95.5" r="85.3"/><path d="M135.7,63.5c-2-4.6-3.9-13.6-9.1-15.6c-6.7-2.6-10.9,14.3-11.9,18.6h-1c-1.7-7.3-4-17.7-12-20c-3.7,15.6,3.9,32.5,11,46
|
||||||
c7.6-3.6,11.3-15,12-23h1l8,24c6.4-1.8,8.7-8.2,11-14c5-12.4,9.2-27.7,6-41C141.1,41.2,138.2,55,135.7,63.5 M39.7,95.5
|
c7.6-3.6,11.3-15,12-23h1l8,24c6.4-1.8,8.7-8.2,11-14c5-12.4,9.2-27.7,6-41C141.1,41.2,138.2,55,135.7,63.5 M39.7,95.5
|
||||||
@@ -72,16 +72,22 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<div class="container-fluid">
|
|
||||||
<br>
|
|
||||||
{% block content %}{% endblock content %}
|
{% block content %}{% endblock content %}
|
||||||
</div>
|
|
||||||
|
|
||||||
<footer class="shadow mt-auto">
|
<footer class="shadow mt-auto">
|
||||||
<code>
|
<code>
|
||||||
<br>
|
<br>
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
|
<div class="d-flex justify-content-center mb-2">
|
||||||
|
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 191 191" height="35" width="35" style="enable-background:new 0 0 191 191;" xml:space="preserve"><style type="text/css">.st0{fill:#f2a900;}</style><circle cx="95.5" cy="95.5" r="95.5"/><circle class="st0" cx="95.3" cy="95.5" r="85.3"/><path d="M135.7,63.5c-2-4.6-3.9-13.6-9.1-15.6c-6.7-2.6-10.9,14.3-11.9,18.6h-1c-1.7-7.3-4-17.7-12-20c-3.7,15.6,3.9,32.5,11,46
|
||||||
|
c7.6-3.6,11.3-15,12-23h1l8,24c6.4-1.8,8.7-8.2,11-14c5-12.4,9.2-27.7,6-41C141.1,41.2,138.2,55,135.7,63.5 M39.7,95.5
|
||||||
|
c8.6-4.1,12.7-17.1,14-26h1c1,4.3,3.7,15.4,9.1,16.1c6.8,0.9,10.4-14.3,10.9-19.1h1c2.2,7.5,4.5,17.3,12,21
|
||||||
|
c2.8-11.7-0.5-24.1-4.8-35c-1.1-2.8-3.3-10.4-7.2-10.4c-6.3,0-9.9,16.7-11,21.4h-1l-8-24C41.6,46.2,34,82,39.7,95.5 M24.7,107.5
|
||||||
|
c10.4,45.6,58.6,71.4,102,52.1c15.8-7,28.3-19.5,35.5-35.1c1.9-4,5.5-11.4,3.4-16.7c-2.1-5.3-22.8,3.4-27.9,5.6
|
||||||
|
c-0.7,0.3-1.2,1-1.4,1.8c-0.3,2.2,1.2,4.3,3.4,4.6c0.1,0,0.2,0,0.3,0l8.7,0.7c-15.7,30.4-58.1,43.8-88,19.5
|
||||||
|
C54,134.6,48,128.2,44,120.5c-1.9-3.7-3.7-8.4-7-11C33.8,107.1,29,106.3,24.7,107.5L24.7,107.5z"/></svg>
|
||||||
|
</div>
|
||||||
<div class="card-group">
|
<div class="card-group">
|
||||||
<div class="card border-0">
|
<div class="card border-0">
|
||||||
<div class="card-body" align="left">
|
<div class="card-body" align="left">
|
||||||
@@ -212,20 +218,22 @@
|
|||||||
<div class="row mb-2">
|
<div class="row mb-2">
|
||||||
<div class="col d-flex justify-content-center">
|
<div class="col d-flex justify-content-center">
|
||||||
<a class="text-decoration-none me-2" href="https://github.com/aglkm/grin-explorer">
|
<a class="text-decoration-none me-2" href="https://github.com/aglkm/grin-explorer">
|
||||||
<span style="color:grey"><i class="bi bi-github me-1"></i>v.0.1.4</span>
|
<span style="color:grey"><i class="bi bi-github me-1"></i>v.0.1.5</span>
|
||||||
</a>
|
</a>
|
||||||
<a class="text-decoration-none" href="/search">
|
<a class="text-decoration-none" href="/search">
|
||||||
<span style="color:grey"><i class="bi bi-search me-1"></i>search</span>
|
<span style="color:grey"><i class="bi bi-search me-1"></i>Search</span>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{% if cg_api == "enabled" %}
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col d-flex justify-content-center" style="color:grey">
|
<div class="col d-flex justify-content-center" style="color:grey">
|
||||||
Powered by CoinGecko
|
Powered by CoinGecko
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<br>
|
<br>
|
||||||
</code>
|
</code>
|
||||||
</footer>
|
</footer>
|
||||||
|
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
<code>
|
<code>
|
||||||
|
|
||||||
<div class="card">
|
<div class="card border-start-0 border-end-0 rounded-0">
|
||||||
<div class="card-body" align="left">
|
<div class="card-body" align="left">
|
||||||
<div class="darkorange-text"><i class="bi bi-box"></i> BLOCK {{ block.height }}</div>
|
<div class="darkorange-text"><i class="bi bi-box"></i> BLOCK {{ block.height }}</div>
|
||||||
<br>
|
<br>
|
||||||
@@ -35,9 +35,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<br>
|
<div class="card border-top-0 border-start-0 border-end-0 rounded-0">
|
||||||
|
|
||||||
<div class="card">
|
|
||||||
<div class="card-body mb-2" align="left">
|
<div class="card-body mb-2" align="left">
|
||||||
<div class="darkorange-text"><i class="bi bi-receipt"></i> TRANSACTIONS</div>
|
<div class="darkorange-text"><i class="bi bi-receipt"></i> TRANSACTIONS</div>
|
||||||
<br>
|
<br>
|
||||||
@@ -110,9 +108,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<br>
|
<div class="card border-top-0 border-start-0 border-end-0 rounded-0">
|
||||||
|
|
||||||
<div class="card">
|
|
||||||
<div class="card-body" align="left">
|
<div class="card-body" align="left">
|
||||||
<div class="darkorange-text"><i class="bi bi-layout-text-sidebar-reverse"></i> RAW DATA</div>
|
<div class="darkorange-text"><i class="bi bi-layout-text-sidebar-reverse"></i> RAW DATA</div>
|
||||||
<br>
|
<br>
|
||||||
@@ -120,8 +116,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<br>
|
|
||||||
|
|
||||||
</code>
|
</code>
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
@@ -4,51 +4,51 @@
|
|||||||
|
|
||||||
<code>
|
<code>
|
||||||
|
|
||||||
<div class="d-none d-md-block mb-4"> <!-- Show on >= md screens -->
|
<div class="d-none d-md-block"> <!-- Show on >= md screens -->
|
||||||
<div class="card-group">
|
<div class="card-group">
|
||||||
<div class="card rounded-0">
|
<div class="card border-bottom-0 border-start-0 rounded-0">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="darkorange-text">
|
<div class="darkorange-text">
|
||||||
HEIGHT
|
HEIGHT
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card rounded-0">
|
<div class="card border-bottom-0 rounded-0">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="darkorange-text">
|
<div class="darkorange-text">
|
||||||
AGE
|
AGE
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card rounded-0">
|
<div class="card border-bottom-0 rounded-0">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="darkorange-text">
|
<div class="darkorange-text">
|
||||||
KERNELS
|
KERNELS
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card rounded-0">
|
<div class="card border-bottom-0 rounded-0">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="darkorange-text">
|
<div class="darkorange-text">
|
||||||
INPUTS
|
INPUTS
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card rounded-0">
|
<div class="card border-bottom-0 rounded-0">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="darkorange-text">
|
<div class="darkorange-text">
|
||||||
OUTPUTS
|
OUTPUTS
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card rounded-0">
|
<div class="card border-bottom-0 rounded-0">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="darkorange-text">
|
<div class="darkorange-text">
|
||||||
FEES
|
FEES
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card rounded-0">
|
<div class="card border-bottom-0 border-end-0 rounded-0">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="darkorange-text">
|
<div class="darkorange-text">
|
||||||
WEIGHT
|
WEIGHT
|
||||||
@@ -60,7 +60,7 @@
|
|||||||
|
|
||||||
{% for i in range(end=10) %}
|
{% for i in range(end=10) %}
|
||||||
<div class="card-group rounded-0">
|
<div class="card-group rounded-0">
|
||||||
<div class="card rounded-0 mt-1">
|
<div class="card border-bottom-0 border-start-0 rounded-0">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
{% if route == "block_list_by_height" %}
|
{% if route == "block_list_by_height" %}
|
||||||
<div class="value-text">
|
<div class="value-text">
|
||||||
@@ -73,7 +73,7 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card rounded-0 mt-1">
|
<div class="card border-bottom-0 rounded-0">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
{% if route == "block_list_by_height" %}
|
{% if route == "block_list_by_height" %}
|
||||||
<div class="value-text">{{ blocks[i].time }}</div>
|
<div class="value-text">{{ blocks[i].time }}</div>
|
||||||
@@ -82,7 +82,7 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card rounded-0 mt-1">
|
<div class="card border-bottom-0 rounded-0">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
{% if route == "block_list_by_height" %}
|
{% if route == "block_list_by_height" %}
|
||||||
<div class="value-text">{{ blocks[i].ker_len }}</div>
|
<div class="value-text">{{ blocks[i].ker_len }}</div>
|
||||||
@@ -91,7 +91,7 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card rounded-0 mt-1">
|
<div class="card border-bottom-0 rounded-0">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
{% if route == "block_list_by_height" %}
|
{% if route == "block_list_by_height" %}
|
||||||
<div class="value-text">{{ blocks[i].in_len }}</div>
|
<div class="value-text">{{ blocks[i].in_len }}</div>
|
||||||
@@ -100,7 +100,7 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card rounded-0 mt-1">
|
<div class="card border-bottom-0 rounded-0">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
{% if route == "block_list_by_height" %}
|
{% if route == "block_list_by_height" %}
|
||||||
<div class="value-text">{{ blocks[i].out_len }}</div>
|
<div class="value-text">{{ blocks[i].out_len }}</div>
|
||||||
@@ -109,7 +109,7 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card rounded-0 mt-1">
|
<div class="card border-bottom-0 rounded-0">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
{% if route == "block_list_by_height" %}
|
{% if route == "block_list_by_height" %}
|
||||||
<div class="value-text">ツ {{ blocks[i].fees / 1000000000.0 }}</div>
|
<div class="value-text">ツ {{ blocks[i].fees / 1000000000.0 }}</div>
|
||||||
@@ -118,7 +118,7 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card rounded-0 mt-1">
|
<div class="card border-bottom-0 border-end-0 rounded-0">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
{% if route == "block_list_by_height" %}
|
{% if route == "block_list_by_height" %}
|
||||||
<div class="value-text">{{ blocks[i].weight }} %</div>
|
<div class="value-text">{{ blocks[i].weight }} %</div>
|
||||||
@@ -133,12 +133,12 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<div class="d-md-none mb-4"> <!-- Show on < md screens-->
|
<div class="d-md-none"> <!-- Show on < md screens-->
|
||||||
{% for i in range(end=10) %}
|
{% for i in range(end=10) %}
|
||||||
<div class="card mb-3">
|
<div class="card border-bottom-0 border-start-0 border-end-0 rounded-0">
|
||||||
<div class="card-body" align="left">
|
<div class="card-body" align="left">
|
||||||
<div class="d-flex justify-content-between">
|
<div class="d-flex justify-content-start">
|
||||||
<div class="value-text">Block</div>
|
<i class="bi bi-box darkorange-text"></i>
|
||||||
{% if route == "block_list_by_height" %}
|
{% if route == "block_list_by_height" %}
|
||||||
<div class="value-text">
|
<div class="value-text">
|
||||||
<a class="text-decoration-none darkorange-text" href="/block/{{ blocks[i].height }}">
|
<a class="text-decoration-none darkorange-text" href="/block/{{ blocks[i].height }}">
|
||||||
@@ -211,49 +211,53 @@
|
|||||||
|
|
||||||
{% if route == "block_list_by_height" %}
|
{% if route == "block_list_by_height" %}
|
||||||
|
|
||||||
<div class="d-flex justify-content-center sticky-bottom mb-3">
|
<div class="card rounded-0 border-start-0 border-end-0 sticky-bottom">
|
||||||
<div class="me-5">
|
<div class="mt-2 d-flex justify-content-center">
|
||||||
{% if height >= (index + 10) %}
|
<div class="me-5">
|
||||||
<a class="text-decoration-none" href="/block_list/{{ index + 10 }}">
|
{% if height >= (index + 10) %}
|
||||||
{% elif height >= (index) and height < (index + 10) %}
|
<a class="text-decoration-none" href="/block_list/{{ index + 10 }}">
|
||||||
<a class="text-decoration-none" href="/block_list/{{ height }}">
|
{% elif height >= (index) and height < (index + 10) %}
|
||||||
{% endif %}
|
<a class="text-decoration-none" href="/block_list/{{ height }}">
|
||||||
<h2><i class="bi bi-arrow-left-square"></i></h2>
|
{% endif %}
|
||||||
</a>
|
<h2><i class="bi bi-arrow-left-square"></i></h2>
|
||||||
</div>
|
</a>
|
||||||
<div class="me-5">
|
</div>
|
||||||
<a class="text-decoration-none" href="/block_list">
|
<div class="me-5">
|
||||||
<h2><i class="bi bi-house"></i></h2>
|
<a class="text-decoration-none" href="/block_list">
|
||||||
</a>
|
<h2><i class="bi bi-house"></i></h2>
|
||||||
</div>
|
</a>
|
||||||
<div>
|
</div>
|
||||||
{% if index >= 20 %}
|
<div>
|
||||||
<a class="text-decoration-none" href="/block_list/{{ index - 10 }}">
|
{% if index >= 20 %}
|
||||||
{% elif index >= 10 and index < 20 %}
|
<a class="text-decoration-none" href="/block_list/{{ index - 10 }}">
|
||||||
<a class="text-decoration-none" href="/block_list/{{ 9 }}">
|
{% elif index >= 10 and index < 20 %}
|
||||||
{% else %}
|
<a class="text-decoration-none" href="/block_list/{{ 9 }}">
|
||||||
<a class="text-decoration-none disabled" href="">
|
{% else %}
|
||||||
{% endif %}
|
<a class="text-decoration-none disabled" href="">
|
||||||
<h2><i class="bi bi-arrow-right-square"></i></h2>
|
{% endif %}
|
||||||
</a>
|
<h2><i class="bi bi-arrow-right-square"></i></h2>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% else %}
|
{% else %}
|
||||||
|
|
||||||
<div class="d-flex justify-content-center sticky-bottom mb-3">
|
<div class="card rounded-0 border-start-0 border-end-0 sticky-bottom">
|
||||||
<div class="me-5">
|
<div class="mt-2 d-flex justify-content-center">
|
||||||
<a class="text-decoration-none disabled" href="">
|
<div class="me-5">
|
||||||
<h2><i class="bi bi-arrow-left-square"></i></h2>
|
<a class="text-decoration-none disabled" href="">
|
||||||
</a>
|
<h2><i class="bi bi-arrow-left-square"></i></h2>
|
||||||
</div>
|
</a>
|
||||||
<div class="me-5">
|
</div>
|
||||||
<a class="text-decoration-none" href="/block_list">
|
<div class="me-5">
|
||||||
<h2><i class="bi bi-house"></i></h2>
|
<a class="text-decoration-none" href="/block_list">
|
||||||
</a>
|
<h2><i class="bi bi-house"></i></h2>
|
||||||
</div>
|
</a>
|
||||||
<div>
|
</div>
|
||||||
<div hx-get="/rpc/block_list/index" hx-trigger="load, every 10s"></div>
|
<div>
|
||||||
|
<div hx-get="/rpc/block_list/index" hx-trigger="load, every 10s"></div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@@ -4,19 +4,18 @@
|
|||||||
|
|
||||||
<code>
|
<code>
|
||||||
|
|
||||||
<div class="card">
|
<div class="card border-start-0 border-end-0 rounded-0">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<h4>No results found.</h4><br>
|
<h4>No results found.</h4><br>
|
||||||
<div class="value-text mb-2">Supported search inputs:</div>
|
<div class="value-text mb-2">Supported search inputs:</div>
|
||||||
<div class="value-text"><i class="bi bi-dot"></i> block number</div>
|
<div class="value-text"><i class="bi bi-dot"></i> Block Number</div>
|
||||||
<div class="value-text"><i class="bi bi-dot"></i> block hash</div>
|
<div class="value-text"><i class="bi bi-dot"></i> Block Hash</div>
|
||||||
<div class="value-text"><i class="bi bi-dot"></i> kernel</div>
|
<div class="value-text"><i class="bi bi-dot"></i> Kernel</div>
|
||||||
|
<div class="value-text"><i class="bi bi-dot"></i> Unspent Output</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</code>
|
</code>
|
||||||
|
|
||||||
<br>
|
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
@@ -6,12 +6,12 @@
|
|||||||
|
|
||||||
{# We have different UI to display if CoinGecko API is disabled by user #}
|
{# We have different UI to display if CoinGecko API is disabled by user #}
|
||||||
|
|
||||||
{% if cg_api == "on" %}
|
{% if cg_api == "enabled" %}
|
||||||
{# CoinGecko API is enabled #}
|
{# CoinGecko API is enabled #}
|
||||||
|
|
||||||
<div class="d-none d-md-block"> <!-- Show on >= md screens -->
|
<div class="d-none d-md-block"> <!-- Show on >= md screens -->
|
||||||
<div class="card-group mb-2">
|
<div class="card-group">
|
||||||
<div class="card me-2">
|
<div class="card border-bottom-0 border-start-0 rounded-0">
|
||||||
<div class="card-body" align="left">
|
<div class="card-body" align="left">
|
||||||
<div class="darkorange-text"><i class="bi bi-cash-coin"></i> PRICE</div>
|
<div class="darkorange-text"><i class="bi bi-cash-coin"></i> PRICE</div>
|
||||||
<br>
|
<br>
|
||||||
@@ -33,7 +33,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="card">
|
<div class="card border-bottom-0 border-end-0 rounded-0">
|
||||||
<div class="card-body" align="left">
|
<div class="card-body" align="left">
|
||||||
<div class="darkorange-text"><i class="bi bi-bank"></i> MARKET</div>
|
<div class="darkorange-text"><i class="bi bi-bank"></i> MARKET</div>
|
||||||
<br>
|
<br>
|
||||||
@@ -65,10 +65,9 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="card-group">
|
||||||
<div class="card-group mb-2">
|
<div class="card card-background border-0">
|
||||||
<div class="card card-background border-0 me-2">
|
<div class="card border-bottom-0 border-start-0 rounded-0 mx-0 mt-0">
|
||||||
<div class="card rounded-end-0 mx-0 mt-0 mb-2">
|
|
||||||
<div class="card-body" align="left">
|
<div class="card-body" align="left">
|
||||||
<div class="darkorange-text"><i class="bi bi-grid"></i> BLOCKCHAIN</div>
|
<div class="darkorange-text"><i class="bi bi-grid"></i> BLOCKCHAIN</div>
|
||||||
<br>
|
<br>
|
||||||
@@ -85,7 +84,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card rounded-end-0 mx-0 my-0">
|
<div class="card border-bottom-0 border-start-0 rounded-0 mx-0 my-0">
|
||||||
<div class="card-body" align="left">
|
<div class="card-body" align="left">
|
||||||
<div class="darkorange-text"><i class="bi bi-speedometer2"></i> TRANSACTIONS & FEES</div>
|
<div class="darkorange-text"><i class="bi bi-speedometer2"></i> TRANSACTIONS & FEES</div>
|
||||||
<br>
|
<br>
|
||||||
@@ -100,7 +99,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="card">
|
<div class="card border-bottom-0 border-end-0 rounded-0">
|
||||||
<div class="card-body" align="left">
|
<div class="card-body" align="left">
|
||||||
<div class="darkorange-text"><i class="bi bi-hammer"></i> MINING</div>
|
<div class="darkorange-text"><i class="bi bi-hammer"></i> MINING</div>
|
||||||
<br>
|
<br>
|
||||||
@@ -146,9 +145,8 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="card-group">
|
||||||
<div class="card-group mb-4">
|
<div class="card rounded-0 border-start-0">
|
||||||
<div class="card me-2">
|
|
||||||
<div class="card-body" align="left">
|
<div class="card-body" align="left">
|
||||||
<div class="darkorange-text"><i class="bi bi-receipt"></i> MEMPOOL</div>
|
<div class="darkorange-text"><i class="bi bi-receipt"></i> MEMPOOL</div>
|
||||||
<br>
|
<br>
|
||||||
@@ -161,7 +159,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card me-2">
|
<div class="card rounded-0">
|
||||||
<div class="card-body" align="left">
|
<div class="card-body" align="left">
|
||||||
<div class="darkorange-text"><i class="bi bi-diagram-3"></i> CONNECTIONS</div>
|
<div class="darkorange-text"><i class="bi bi-diagram-3"></i> CONNECTIONS</div>
|
||||||
<br>
|
<br>
|
||||||
@@ -174,7 +172,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card">
|
<div class="card rounded-0 border-end-0">
|
||||||
<div class="card-body" align="left">
|
<div class="card-body" align="left">
|
||||||
<div class="darkorange-text"><i class="bi bi-pc-display-horizontal"></i> NODE</div>
|
<div class="darkorange-text"><i class="bi bi-pc-display-horizontal"></i> NODE</div>
|
||||||
<br>
|
<br>
|
||||||
@@ -196,7 +194,7 @@
|
|||||||
|
|
||||||
<div class="d-md-none"> <!-- Show on < md screens-->
|
<div class="d-md-none"> <!-- Show on < md screens-->
|
||||||
|
|
||||||
<div class="card mb-3">
|
<div class="card border-bottom-0 border-start-0 border-end-0 rounded-0">
|
||||||
<div class="card-body" align="left">
|
<div class="card-body" align="left">
|
||||||
<div class="darkorange-text"><i class="bi bi-cash-coin"></i> PRICE</div>
|
<div class="darkorange-text"><i class="bi bi-cash-coin"></i> PRICE</div>
|
||||||
<br>
|
<br>
|
||||||
@@ -218,7 +216,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="card mb-3">
|
<div class="card border-bottom-0 border-start-0 border-end-0 rounded-0">
|
||||||
<div class="card-body" align="left">
|
<div class="card-body" align="left">
|
||||||
<div class="darkorange-text"><i class="bi bi-bank"></i> MARKET</div>
|
<div class="darkorange-text"><i class="bi bi-bank"></i> MARKET</div>
|
||||||
<br>
|
<br>
|
||||||
@@ -249,8 +247,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="card border-bottom-0 border-start-0 border-end-0 rounded-0">
|
||||||
<div class="card mb-3">
|
|
||||||
<div class="card-body" align="left">
|
<div class="card-body" align="left">
|
||||||
<div class="d-flex justify-content-between">
|
<div class="d-flex justify-content-between">
|
||||||
<div class="darkorange-text"><i class="bi bi-grid"></i> BLOCKCHAIN</div>
|
<div class="darkorange-text"><i class="bi bi-grid"></i> BLOCKCHAIN</div>
|
||||||
@@ -269,7 +266,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card mb-3">
|
<div class="card border-bottom-0 border-start-0 border-end-0 rounded-0">
|
||||||
<div class="card-body" align="left">
|
<div class="card-body" align="left">
|
||||||
<div class="darkorange-text"><i class="bi bi-hammer"></i> MINING</div>
|
<div class="darkorange-text"><i class="bi bi-hammer"></i> MINING</div>
|
||||||
<br>
|
<br>
|
||||||
@@ -313,7 +310,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card mb-3">
|
<div class="card border-bottom-0 border-start-0 border-end-0 rounded-0">
|
||||||
<div class="card-body" align="left">
|
<div class="card-body" align="left">
|
||||||
<div class="darkorange-text"><i class="bi bi-speedometer2"></i> TRANSACTIONS & FEES</div>
|
<div class="darkorange-text"><i class="bi bi-speedometer2"></i> TRANSACTIONS & FEES</div>
|
||||||
<br>
|
<br>
|
||||||
@@ -327,9 +324,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="card border-bottom-0 border-start-0 border-end-0 rounded-0">
|
||||||
|
|
||||||
<div class="card mb-3">
|
|
||||||
<div class="card-body" align="left">
|
<div class="card-body" align="left">
|
||||||
<div class="darkorange-text"><i class="bi bi-receipt"></i> MEMPOOL</div>
|
<div class="darkorange-text"><i class="bi bi-receipt"></i> MEMPOOL</div>
|
||||||
<br>
|
<br>
|
||||||
@@ -342,7 +337,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card mb-3">
|
<div class="card border-bottom-0 border-start-0 border-end-0 rounded-0">
|
||||||
<div class="card-body" align="left">
|
<div class="card-body" align="left">
|
||||||
<div class="darkorange-text"><i class="bi bi-diagram-3"></i> CONNECTIONS</div>
|
<div class="darkorange-text"><i class="bi bi-diagram-3"></i> CONNECTIONS</div>
|
||||||
<br>
|
<br>
|
||||||
@@ -355,7 +350,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card mb-4">
|
<div class="card rounded-0 border-start-0 border-end-0">
|
||||||
<div class="card-body" align="left">
|
<div class="card-body" align="left">
|
||||||
<div class="darkorange-text"><i class="bi bi-pc-display-horizontal"></i> NODE</div>
|
<div class="darkorange-text"><i class="bi bi-pc-display-horizontal"></i> NODE</div>
|
||||||
<br>
|
<br>
|
||||||
@@ -465,8 +460,8 @@
|
|||||||
{# CoinGecko API is disabled #}
|
{# CoinGecko API is disabled #}
|
||||||
|
|
||||||
<div class="d-none d-md-block"> <!-- Show on >= md screens -->
|
<div class="d-none d-md-block"> <!-- Show on >= md screens -->
|
||||||
<div class="card-group mb-2">
|
<div class="card-group">
|
||||||
<div class="card me-2">
|
<div class="card border-bottom-0 border-start-0 rounded-0">
|
||||||
<div class="card-body" align="left">
|
<div class="card-body" align="left">
|
||||||
<div class="darkorange-text"><i class="bi bi-bank"></i> MARKET</div>
|
<div class="darkorange-text"><i class="bi bi-bank"></i> MARKET</div>
|
||||||
<br>
|
<br>
|
||||||
@@ -489,7 +484,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="card">
|
<div class="card border-bottom-0 border-end-0 rounded-0">
|
||||||
<div class="card-body" align="left">
|
<div class="card-body" align="left">
|
||||||
<div class="darkorange-text"><i class="bi bi-hammer"></i> MINING</div>
|
<div class="darkorange-text"><i class="bi bi-hammer"></i> MINING</div>
|
||||||
<br>
|
<br>
|
||||||
@@ -508,9 +503,8 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="card-group">
|
||||||
<div class="card-group mb-2">
|
<div class="card border-bottom-0 border-start-0 rounded-0">
|
||||||
<div class="card me-2">
|
|
||||||
<div class="card-body" align="left">
|
<div class="card-body" align="left">
|
||||||
<div class="darkorange-text"><i class="bi bi-grid"></i> BLOCKCHAIN</div>
|
<div class="darkorange-text"><i class="bi bi-grid"></i> BLOCKCHAIN</div>
|
||||||
<br>
|
<br>
|
||||||
@@ -527,7 +521,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card">
|
<div class="card border-bottom-0 border-end-0 rounded-0">
|
||||||
<div class="card-body" align="left">
|
<div class="card-body" align="left">
|
||||||
<div class="darkorange-text"><i class="bi bi-speedometer2"></i> TRANSACTIONS & FEES</div>
|
<div class="darkorange-text"><i class="bi bi-speedometer2"></i> TRANSACTIONS & FEES</div>
|
||||||
<br>
|
<br>
|
||||||
@@ -542,9 +536,8 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="card-group">
|
||||||
<div class="card-group mb-4">
|
<div class="card border-start-0 rounded-0">
|
||||||
<div class="card me-2">
|
|
||||||
<div class="card-body" align="left">
|
<div class="card-body" align="left">
|
||||||
<div class="darkorange-text"><i class="bi bi-receipt"></i> MEMPOOL</div>
|
<div class="darkorange-text"><i class="bi bi-receipt"></i> MEMPOOL</div>
|
||||||
<br>
|
<br>
|
||||||
@@ -557,7 +550,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card me-2">
|
<div class="card rounded-0">
|
||||||
<div class="card-body" align="left">
|
<div class="card-body" align="left">
|
||||||
<div class="darkorange-text"><i class="bi bi-diagram-3"></i> CONNECTIONS</div>
|
<div class="darkorange-text"><i class="bi bi-diagram-3"></i> CONNECTIONS</div>
|
||||||
<br>
|
<br>
|
||||||
@@ -570,7 +563,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card">
|
<div class="card border-end-0 rounded-0">
|
||||||
<div class="card-body" align="left">
|
<div class="card-body" align="left">
|
||||||
<div class="darkorange-text"><i class="bi bi-pc-display-horizontal"></i> NODE</div>
|
<div class="darkorange-text"><i class="bi bi-pc-display-horizontal"></i> NODE</div>
|
||||||
<br>
|
<br>
|
||||||
@@ -593,7 +586,7 @@
|
|||||||
|
|
||||||
<div class="d-md-none"> <!-- Show on < md screens-->
|
<div class="d-md-none"> <!-- Show on < md screens-->
|
||||||
|
|
||||||
<div class="card mb-3">
|
<div class="card border-bottom-0 border-start-0 border-end-0 rounded-0">
|
||||||
<div class="card-body" align="left">
|
<div class="card-body" align="left">
|
||||||
<div class="darkorange-text"><i class="bi bi-bank"></i> MARKET</div>
|
<div class="darkorange-text"><i class="bi bi-bank"></i> MARKET</div>
|
||||||
<br>
|
<br>
|
||||||
@@ -616,8 +609,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="card border-bottom-0 border-start-0 border-end-0 rounded-0">
|
||||||
<div class="card mb-3">
|
|
||||||
<div class="card-body" align="left">
|
<div class="card-body" align="left">
|
||||||
<div class="d-flex justify-content-between">
|
<div class="d-flex justify-content-between">
|
||||||
<div class="darkorange-text"><i class="bi bi-grid"></i> BLOCKCHAIN</div>
|
<div class="darkorange-text"><i class="bi bi-grid"></i> BLOCKCHAIN</div>
|
||||||
@@ -636,7 +628,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card mb-3">
|
<div class="card border-bottom-0 border-start-0 border-end-0 rounded-0">
|
||||||
<div class="card-body" align="left">
|
<div class="card-body" align="left">
|
||||||
<div class="darkorange-text"><i class="bi bi-hammer"></i> MINING</div>
|
<div class="darkorange-text"><i class="bi bi-hammer"></i> MINING</div>
|
||||||
<br>
|
<br>
|
||||||
@@ -653,7 +645,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card mb-3">
|
<div class="card border-bottom-0 border-start-0 border-end-0 rounded-0">
|
||||||
<div class="card-body" align="left">
|
<div class="card-body" align="left">
|
||||||
<div class="darkorange-text"><i class="bi bi-speedometer2"></i> TRANSACTIONS & FEES</div>
|
<div class="darkorange-text"><i class="bi bi-speedometer2"></i> TRANSACTIONS & FEES</div>
|
||||||
<br>
|
<br>
|
||||||
@@ -667,9 +659,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="card border-bottom-0 border-start-0 border-end-0 rounded-0">
|
||||||
|
|
||||||
<div class="card mb-3">
|
|
||||||
<div class="card-body" align="left">
|
<div class="card-body" align="left">
|
||||||
<div class="darkorange-text"><i class="bi bi-receipt"></i> MEMPOOL</div>
|
<div class="darkorange-text"><i class="bi bi-receipt"></i> MEMPOOL</div>
|
||||||
<br>
|
<br>
|
||||||
@@ -682,7 +672,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card mb-3">
|
<div class="card border-bottom-0 border-start-0 border-end-0 rounded-0">
|
||||||
<div class="card-body" align="left">
|
<div class="card-body" align="left">
|
||||||
<div class="darkorange-text"><i class="bi bi-diagram-3"></i> CONNECTIONS</div>
|
<div class="darkorange-text"><i class="bi bi-diagram-3"></i> CONNECTIONS</div>
|
||||||
<br>
|
<br>
|
||||||
@@ -695,7 +685,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card mb-4">
|
<div class="card border-start-0 border-end-0 rounded-0">
|
||||||
<div class="card-body" align="left">
|
<div class="card-body" align="left">
|
||||||
<div class="darkorange-text"><i class="bi bi-pc-display-horizontal"></i> NODE</div>
|
<div class="darkorange-text"><i class="bi bi-pc-display-horizontal"></i> NODE</div>
|
||||||
<br>
|
<br>
|
||||||
@@ -738,70 +728,8 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<div class="modal fade" id="mining_cost" tabindex="-1" aria-labelledby="mining_cost_label" aria-hidden="true">
|
|
||||||
<div class="modal-dialog modal-dialog-centered">
|
|
||||||
<div class="modal-content">
|
|
||||||
<div class="modal-header">
|
|
||||||
<h1 class="modal-title fs-5" id="mining_cost_label">Estimated Mining Cost</h1>
|
|
||||||
<div data-bs-theme="light">
|
|
||||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="modal-body">
|
|
||||||
Mining cost to produce 1 grin coin.<br>
|
|
||||||
Assuming that:<br>
|
|
||||||
Miner is G1-mini ASIC.<br>
|
|
||||||
Electricity cost is $0.07 per kW/h.<br>
|
|
||||||
<br>
|
|
||||||
<a class="text-decoration-none" href="https://ipollo.com/products/ipollo-g1-mini">https://ipollo.com/products/ipollo-g1-mini</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="modal fade" id="ratio" tabindex="-1" aria-labelledby="ratio_label" aria-hidden="true">
|
|
||||||
<div class="modal-dialog modal-dialog-centered">
|
|
||||||
<div class="modal-content">
|
|
||||||
<div class="modal-header">
|
|
||||||
<h1 class="modal-title fs-5" id="ratio_label">Reward/Cost Ratio</h1>
|
|
||||||
<div data-bs-theme="light">
|
|
||||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="modal-body">
|
|
||||||
Shows the result of the following formula:<br>
|
|
||||||
Price of 1 Grin (USD) / Mining Cost of 1 Grin (USD).<br>
|
|
||||||
<br>
|
|
||||||
<i class="bi bi-hand-thumbs-down"></i> - <= 1<br>
|
|
||||||
<i class="bi bi-hand-thumbs-up"></i> - from 1 to 2<br>
|
|
||||||
<i class="bi bi-emoji-sunglasses"></i> - from 2 to 3<br>
|
|
||||||
<i class='bi bi-rocket-takeoff'></i> - >= 3
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="modal fade" id="breakeven" tabindex="-1" aria-labelledby="breakeven_label" aria-hidden="true">
|
|
||||||
<div class="modal-dialog modal-dialog-centered">
|
|
||||||
<div class="modal-content">
|
|
||||||
<div class="modal-header">
|
|
||||||
<h1 class="modal-title fs-5" id="breakeven_label">Breakeven Electricity Cost</h1>
|
|
||||||
<div data-bs-theme="light">
|
|
||||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="modal-body">
|
|
||||||
Electricity threshold cost below which mining is profitable.<br>
|
|
||||||
Assuming G1-mini ASIC as a miner device.
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
</code>
|
</code>
|
||||||
|
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
<code>
|
<code>
|
||||||
|
|
||||||
<div class="card">
|
<div class="card border-start-0 border-end-0 rounded-0">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="d-flex justify-content-between">
|
<div class="d-flex justify-content-between">
|
||||||
<div class="darkorange-text"><i class="bi bi-card-text"></i> KERNEL</div>
|
<div class="darkorange-text"><i class="bi bi-card-text"></i> KERNEL</div>
|
||||||
@@ -44,8 +44,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% if kernel.status != "Unconfirmed" %}
|
{% if kernel.status != "Unconfirmed" %}
|
||||||
<br>
|
<div class="card border-top-0 border-start-0 border-end-0 rounded-0">
|
||||||
<div class="card">
|
|
||||||
<div class="card-body" align="left">
|
<div class="card-body" align="left">
|
||||||
<div class="darkorange-text"><i class="bi bi-layout-text-sidebar-reverse"></i> RAW DATA</div>
|
<div class="darkorange-text"><i class="bi bi-layout-text-sidebar-reverse"></i> RAW DATA</div>
|
||||||
<br>
|
<br>
|
||||||
@@ -54,8 +53,6 @@
|
|||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<br>
|
|
||||||
|
|
||||||
</code>
|
</code>
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
52
templates/output.html.tera
Normal file
52
templates/output.html.tera
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
{% extends "base" %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<code>
|
||||||
|
|
||||||
|
<div class="card rounded-0">
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="d-flex justify-content-between">
|
||||||
|
<div class="darkorange-text"><i class="bi bi-card-text"></i> OUTPUT</div>
|
||||||
|
{% if output.status == "Unconfirmed" %}
|
||||||
|
<span class="badge text-bg-warning px-2 py-2">UNCONFIRMED</span>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
<br>
|
||||||
|
<div class="d-flex justify-content-between">
|
||||||
|
<div class="value-text">Commitment </div>
|
||||||
|
<div class="value-text text-break text-end">{{ output.commit }}</div>
|
||||||
|
</div>
|
||||||
|
{% if output.status != "Unconfirmed" %}
|
||||||
|
<br>
|
||||||
|
<div class="d-flex justify-content-between">
|
||||||
|
<div class="value-text">Block Height </div>
|
||||||
|
<div class="value-text text-end">
|
||||||
|
<a class="text-decoration-none" href="/block/{{ output.height }}">
|
||||||
|
{{ output.height }} <i class="bi bi-box-arrow-up-right"></i>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
<br>
|
||||||
|
<div class="d-flex justify-content-between">
|
||||||
|
<div class="value-text">Type </div>
|
||||||
|
<div class="value-text text-end">{{ output.out_type }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% if output.status != "Unconfirmed" %}
|
||||||
|
<div class="card border-top-0 rounded-0">
|
||||||
|
<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">{{ output.raw_data }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
</code>
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
|
|
@@ -4,11 +4,11 @@
|
|||||||
|
|
||||||
<code>
|
<code>
|
||||||
|
|
||||||
<div class="card">
|
<div class="card border-start-0 border-end-0 rounded-0">
|
||||||
<div class="card-body mx-2 mt-2 mb-3">
|
<div class="card-body mx-2 mt-2 mb-3">
|
||||||
<div class="d-flex justify-content-start mb-1">
|
<div class="d-flex justify-content-start mb-1">
|
||||||
<i class="bi bi-box me-2"></i>
|
<i class="bi bi-box darkorange-text"></i>
|
||||||
<div class="value-text text-end" hx-get="/rpc/block/latest" hx-trigger="load, every 10s"></div>
|
<div class="darkorange-text text-end" hx-get="/rpc/block/latest" hx-trigger="load, every 10s"></div>
|
||||||
</div>
|
</div>
|
||||||
<form class="input-group" role="search" action="/search" method="GET" autocomplete="off">
|
<form class="input-group" role="search" action="/search" method="GET" autocomplete="off">
|
||||||
<input class="form-control text-center ms-0 me-2" type="search" placeholder="Explore Grin Network" aria-label="Search" name="input" required>
|
<input class="form-control text-center ms-0 me-2" type="search" placeholder="Explore Grin Network" aria-label="Search" name="input" required>
|
||||||
@@ -18,14 +18,13 @@
|
|||||||
</form>
|
</form>
|
||||||
<br><br>
|
<br><br>
|
||||||
<div class="value-text mb-2">Supported search inputs:</div>
|
<div class="value-text mb-2">Supported search inputs:</div>
|
||||||
<div class="value-text"><i class="bi bi-dot"></i> block number</div>
|
<div class="value-text"><i class="bi bi-dot"></i> Block Number</div>
|
||||||
<div class="value-text"><i class="bi bi-dot"></i> block hash</div>
|
<div class="value-text"><i class="bi bi-dot"></i> Block Hash</div>
|
||||||
<div class="value-text"><i class="bi bi-dot"></i> kernel</div>
|
<div class="value-text"><i class="bi bi-dot"></i> Kernel</div>
|
||||||
|
<div class="value-text"><i class="bi bi-dot"></i> Unspent Output</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<br>
|
|
||||||
|
|
||||||
</code>
|
</code>
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
Reference in New Issue
Block a user