extending templates, fixing search/routes/structs

master
lalanza808 5 years ago
parent 58c93f8cba
commit 917ba7baa2

@ -1,4 +1,4 @@
#[derive(Serialize, Deserialize)]
#[derive(Serialize, Deserialize, Hash, Eq, PartialEq, Debug)]
pub struct RPCPayload {
pub jsonrpc: String,
pub id: String,
@ -17,7 +17,7 @@ impl Default for RPCPayload {
}
}
#[derive(Serialize, Deserialize)]
#[derive(Serialize, Deserialize, Hash, Eq, PartialEq, Debug)]
pub struct RPCParams {
pub hash: Option<String>,
pub txs_hashes: Option<Vec<String>>,
@ -84,21 +84,21 @@ pub struct GetInfoResult {
pub wide_difficulty: String
}
#[derive(Serialize, Deserialize)]
#[derive(Serialize, Deserialize, Hash, Eq, PartialEq, Debug)]
pub struct BlockByHeaderHash {
pub id: String,
pub jsonrpc: String,
pub result: BlockByHeaderHashResult
}
#[derive(Serialize, Deserialize)]
#[derive(Serialize, Deserialize, Hash, Eq, PartialEq, Debug)]
pub struct BlockByHeaderHashResult {
pub status: String,
pub untrusted: bool,
pub block_header: BlockHeader
}
#[derive(Serialize, Deserialize)]
#[derive(Serialize, Deserialize, Hash, Eq, PartialEq, Debug)]
pub struct BlockHeader {
pub block_size: u32,
pub depth: u32,
@ -116,12 +116,12 @@ pub struct BlockHeader {
pub timestamp: i64
}
#[derive(Serialize, Deserialize)]
#[derive(Serialize, Deserialize, Hash, Eq, PartialEq, Debug)]
pub struct GetTransactions {
pub txs: Vec<GetTransactionsTxs>
}
#[derive(Serialize, Deserialize)]
#[derive(Serialize, Deserialize, Hash, Eq, PartialEq, Debug)]
pub struct GetTransactionsTxs {
pub block_height: u32,
pub block_timestamp: i64,
@ -130,16 +130,15 @@ pub struct GetTransactionsTxs {
pub output_indices: Vec<u32>,
}
#[derive(Serialize, Deserialize)]
#[derive(Serialize, Deserialize, Hash, Eq, PartialEq, Debug)]
pub struct GetBlock {
pub id: String,
pub jsonrpc: String,
pub result: GetBlockResult
}
#[derive(Serialize, Deserialize)]
#[derive(Serialize, Deserialize, Hash, Eq, PartialEq, Debug)]
pub struct GetBlockResult {
pub blob: String,
pub block_header: BlockHeader,
pub credits: u8,
pub miner_tx_hash: String,

@ -4,12 +4,14 @@
#[macro_use] extern crate serde_derive;
extern crate reqwest;
mod data_types;
use rocket::http::RawStr;
use rocket::response::Redirect;
use rocket_contrib::json::{Json, JsonValue};
use rocket_contrib::templates::Template;
use rocket_contrib::serve::StaticFiles;
use reqwest::blocking::{RequestBuilder, Client};
use reqwest::Error;
use std::env;
use data_types::*;
@ -38,30 +40,29 @@ fn issue_raw_rpc(method: &str, params: JsonValue) -> RequestBuilder {
}
#[get("/block/hash/<block_hash>")]
fn get_block_header_by_block_hash(block_hash: String) -> Json<BlockHeader> {
fn get_block_by_hash(block_hash: String) -> Json<GetBlockResult> {
let params = RPCParams {
hash: Some(block_hash),
..Default::default()
};
let res: BlockByHeaderHash = issue_rpc(&"get_block_header_by_hash", Some(params))
let res: GetBlock = issue_rpc(&"get_block", Some(params))
.send().unwrap().json().unwrap();
Json(res.result.block_header)
Json(res.result)
}
#[get("/block/height/<block_height>")]
fn get_block_by_height(block_height: String) -> String {
fn get_block_by_height(block_height: String) -> Json<GetBlockResult> {
let params = RPCParams {
height: Some(block_height),
..Default::default()
};
let res: GetBlock = issue_rpc(&"get_block", Some(params))
.send().unwrap().json().unwrap();
// Json(res.result.block_header)
serde_json::to_string(&res).unwrap()
Json(res.result)
}
#[get("/transaction/<tx_hash>")]
fn get_block_header_by_transaction_hash(tx_hash: String) -> Json<GetTransactions> {
fn get_transaction_by_hash(tx_hash: String) -> Json<GetTransactions> {
let params: JsonValue = json!({"txs_hashes": [&tx_hash]});
let res: GetTransactions = issue_raw_rpc(&"get_transactions", params)
.send().unwrap().json().unwrap();
@ -70,68 +71,53 @@ fn get_block_header_by_transaction_hash(tx_hash: String) -> Json<GetTransactions
#[get("/search?<value>")]
fn search(value: &RawStr) -> Redirect {
// This search implementation is not ideal but it works.
// We basically check the length of the search value and
// attempt to redirect to the appropriate route.
let sl: usize = value.len();
let first_byte = value.get(0..1).unwrap();
println!("Search value: {}", value);
println!("First byte: {}", first_byte);
println!("{}", sl);
if sl < 10 {
// Less than 10 characters is probably a block height. If it can
// be parsed as valid u32 then redirect to `get_block_by_height`,
// otherwise redirect to the error response.
match value.parse::<u32>() {
Ok(v) => {
println!("Found: {}", v);
// "this looks like a block height"
return Redirect::found(uri!(get_block_by_height: value.as_str()));
},
Err(e) => {
println!("Error: {}", e);
// "this is an invalid search query"
return Redirect::found(uri!(index));
}
Ok(_) => return Redirect::found(uri!(get_block_by_height: value.as_str())),
Err(_) => return Redirect::found(uri!(error))
}
} else if sl < 95 {
// "this looks like a tx or block hash"
return Redirect::found(uri!(index));
} else if sl == 95 {
match first_byte {
"9" => {
println!("This looks like a testnet address");
return Redirect::found(uri!(index));
},
"A" => {
println!("This looks like a testnet subaddress");
return Redirect::found(uri!(index));
},
"5" => {
println!("This looks like a stagenet address");
return Redirect::found(uri!(index));
},
"7" => {
println!("This looks like a stagenet subaddress");
return Redirect::found(uri!(index));
},
"4" => {
println!("This looks like a mainnet address");
return Redirect::found(uri!(index));
},
"8" => {
println!("This looks like a mainnet subaddress");
return Redirect::found(uri!(index));
},
_ => {
println!("Not sure what this is");
return Redirect::found(uri!(index));
} else if sl == 64 {
// Equal to 64 characters is probably a hash; block or tx.
// For this we attempt to query for a block with
// given hash. If we don't receive a valid/expected
// response then we attempt to query for a transaction hash.
// If neither works then redirect to error response.
let block_hash_params = RPCParams {
hash: Some(value.to_string()),
..Default::default()
};
let check_valid_block_hash: Result<GetBlock, Error> = issue_rpc(
&"get_block", Some(block_hash_params)
).send().unwrap().json();
match check_valid_block_hash {
Ok(_) => return Redirect::found(uri!(get_block_by_hash: value.as_str())),
Err(_) => {
let tx_hash_params: JsonValue = json!({"txs_hashes": [&value.as_str()]});
let check_valid_tx_hash: Result<GetTransactions, Error> = issue_raw_rpc(
&"get_transactions", tx_hash_params
).send().unwrap().json();
match check_valid_tx_hash {
Ok(_) => return Redirect::found(uri!(get_transaction_by_hash: value.as_str())),
Err(_) => return Redirect::found(uri!(error))
}
}
}
} else if sl == 105 {
// "this looks like an integrated address"
return Redirect::found(uri!(index));
} else {
// "no idea what this is"
return Redirect::found(uri!(index));
// Anything else hasn't been implemented yet
// so redirect to error response.
return Redirect::found(uri!(error));
};
// println!("No if stmt matched");
// return Redirect::found(uri!(index));
}
#[get("/")]
@ -141,6 +127,14 @@ fn index() -> Template {
Template::render("index", &res.result)
}
#[get("/error", )]
fn error() -> JsonValue {
json!({
"status": "error",
"reason": "There was an error while searching the provided values."
})
}
#[catch(404)]
fn not_found() -> JsonValue {
json!({
@ -158,8 +152,9 @@ fn main() {
index,
search,
get_block_by_height,
get_block_header_by_block_hash,
get_block_header_by_transaction_hash,
get_block_by_hash,
get_transaction_by_hash,
error
])
.mount("/static", StaticFiles::from("./static"))
.register(catchers![not_found])

@ -0,0 +1,15 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Monero Block Explorer</title>
<link rel="stylesheet" href="/static/css/main.css"/>
<link rel="stylesheet" href="/static/css/normalize.css"/>
</head>
<body>
<div class="container">
{% block content %}
{% endblock content %}
</div>
</body>
</html>

@ -1,78 +1,71 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Monero Block Explorer</title>
<link rel="stylesheet" href="/static/css/main.css"/>
<link rel="stylesheet" href="/static/css/normalize.css"/>
</head>
<body>
<div class="title">
<h1>Monero Block Explorer</h1>
</div>
<div class="search">
<h2>Search</h2>
<form action="/search" method="get">
<input type="text" name="value" placeholder="Enter a transaction hash, block hash, or block height.">
<input type="submit" value="Search">
</form>
</div>
<div class="server-info">
<h2>Server Info</h2>
</div>
<div class="network-stats">
<h2>Network Stats</h2>
</div>
<div class="tx-pool">
<h2>Transaction Pool</h2>
</div>
<div class="">
<h2>Top Block</h2>
</div>
<div class="">
<h2>Previous Block</h2>
</div>
{% extends "base" %}
<h1>get_info</h1>
<p>alt_blocks_count: {{ alt_blocks_count }}</p>
<p>block_size_limit: {{ block_size_limit }}</p>
<p>block_size_median: {{ block_size_median }}</p>
<p>block_weight_limit: {{ block_weight_limit }}</p>
<p>block_weight_median: {{ block_weight_median }}</p>
<p>bootstrap_daemon_address: {{ bootstrap_daemon_address }}</p>
<p>credits: {{ credits }}</p>
<p>cumulative_difficulty: {{ cumulative_difficulty }}</p>
<p>cumulative_difficulty_top64: {{ cumulative_difficulty_top64 }}</p>
<p>database_size: {{ database_size }}</p>
<p>difficulty: {{ difficulty }}</p>
<p>difficulty_top64: {{ difficulty_top64 }}</p>
<p>free_space: {{ free_space }}</p>
<p>grey_peerlist_size: {{ grey_peerlist_size }}</p>
<p>height: {{ height }}</p>
<p>height_without_bootstrap: {{ height_without_bootstrap }}</p>
<p>incoming_connections_count: {{ incoming_connections_count }}</p>
<p>mainnet: {{ mainnet }}</p>
<p>nettype: {{ nettype }}</p>
<p>offline: {{ offline }}</p>
<p>outgoing_connections_count: {{ outgoing_connections_count }}</p>
<p>rpc_connections_count: {{ rpc_connections_count }}</p>
<p>stagenet: {{ stagenet }}</p>
<p>start_time: {{ start_time }}</p>
<p>status: {{ status }}</p>
<p>target: {{ target }}</p>
<p>target_height: {{ target_height }}</p>
<p>testnet: {{ testnet }}</p>
<p>top_block_hash: {{ top_block_hash }}</p>
<p>top_hash: {{ top_hash }}</p>
<p>tx_count: {{ tx_count }}</p>
<p>tx_pool_size: {{ tx_pool_size }}</p>
<p>untrusted: {{ untrusted }}</p>
<p>update_available: {{ update_available }}</p>
<p>version: {{ version }}</p>
<p>was_bootstrap_ever_used: {{ was_bootstrap_ever_used }}</p>
<p>white_peerlist_size: {{ white_peerlist_size }}</p>
<p>wide_cumulative_difficulty: {{ wide_cumulative_difficulty }}</p>
<p>wide_difficulty: {{ wide_difficulty }}</p>
{% block content %}
<div class="title">
<h1>Monero Block Explorer</h1>
</div>
<div class="search">
<h2>Search</h2>
<form action="/search" method="get">
<input type="text" name="value" placeholder="Enter a transaction hash, block hash, or block height.">
<input type="submit" value="Search">
</form>
</div>
<div class="server-info">
<h2>Server Info</h2>
</div>
<div class="network-stats">
<h2>Network Stats</h2>
</div>
<div class="tx-pool">
<h2>Transaction Pool</h2>
</div>
<div class="">
<h2>Top Block</h2>
</div>
<div class="">
<h2>Previous Block</h2>
</div>
</body>
</html>
<h1>get_info</h1>
<p>alt_blocks_count: {{ alt_blocks_count }}</p>
<p>block_size_limit: {{ block_size_limit }}</p>
<p>block_size_median: {{ block_size_median }}</p>
<p>block_weight_limit: {{ block_weight_limit }}</p>
<p>block_weight_median: {{ block_weight_median }}</p>
<p>bootstrap_daemon_address: {{ bootstrap_daemon_address }}</p>
<p>credits: {{ credits }}</p>
<p>cumulative_difficulty: {{ cumulative_difficulty }}</p>
<p>cumulative_difficulty_top64: {{ cumulative_difficulty_top64 }}</p>
<p>database_size: {{ database_size }}</p>
<p>difficulty: {{ difficulty }}</p>
<p>difficulty_top64: {{ difficulty_top64 }}</p>
<p>free_space: {{ free_space }}</p>
<p>grey_peerlist_size: {{ grey_peerlist_size }}</p>
<p>height: {{ height }}</p>
<p>height_without_bootstrap: {{ height_without_bootstrap }}</p>
<p>incoming_connections_count: {{ incoming_connections_count }}</p>
<p>mainnet: {{ mainnet }}</p>
<p>nettype: {{ nettype }}</p>
<p>offline: {{ offline }}</p>
<p>outgoing_connections_count: {{ outgoing_connections_count }}</p>
<p>rpc_connections_count: {{ rpc_connections_count }}</p>
<p>stagenet: {{ stagenet }}</p>
<p>start_time: {{ start_time }}</p>
<p>status: {{ status }}</p>
<p>target: {{ target }}</p>
<p>target_height: {{ target_height }}</p>
<p>testnet: {{ testnet }}</p>
<p>top_block_hash: {{ top_block_hash }}</p>
<p>top_hash: {{ top_hash }}</p>
<p>tx_count: {{ tx_count }}</p>
<p>tx_pool_size: {{ tx_pool_size }}</p>
<p>untrusted: {{ untrusted }}</p>
<p>update_available: {{ update_available }}</p>
<p>version: {{ version }}</p>
<p>was_bootstrap_ever_used: {{ was_bootstrap_ever_used }}</p>
<p>white_peerlist_size: {{ white_peerlist_size }}</p>
<p>wide_cumulative_difficulty: {{ wide_cumulative_difficulty }}</p>
<p>wide_difficulty: {{ wide_difficulty }}</p>
{% endblock content %}

Loading…
Cancel
Save