more info on index site and css added

master
moneroexamples 9 years ago
parent 69d6b27f31
commit 9b30acc5e2

@ -1,8 +1,14 @@
cmake_minimum_required(VERSION 3.5) cmake_minimum_required(VERSION 3.5)
#list(INSERT
# CMAKE_MODULE_PATH 0 ${PROJECT_SOURCE_DIR}/cmake)
set(CMAKE_MODULE_PATH
${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
set(PROJECT_NAME set(PROJECT_NAME
crowxmr) crowxmr)
project(${PROJECT_NAME}) project(${PROJECT_NAME})
set(CMAKE_CXX_FLAGS set(CMAKE_CXX_FLAGS
@ -82,24 +88,70 @@ add_subdirectory(src/)
set(SOURCE_FILES set(SOURCE_FILES
main.cpp) main.cpp)
ADD_CUSTOM_TARGET(driver DEPENDS src/templates/index.html) #ADD_CUSTOM_TARGET(driver DEPENDS src/templates/index.html)
add_executable(${PROJECT_NAME} add_executable(${PROJECT_NAME}
${SOURCE_FILES}) ${SOURCE_FILES})
#add_custom_command(OUTPUT template_folder #add_custom_command(TARGET template_folder POST_BUILD
# COMMAND ${CMAKE_COMMAND} -E # COMMAND ${CMAKE_COMMAND} -E copy_directory
# copy_directory "${CMAKE_CURRENT_SOURCE_DIR}/src/templates" "${CMAKE_CURRENT_BINARY_DIR}" # "${CMAKE_CURRENT_SOURCE_DIR}/src/templates" "${CMAKE_CURRENT_BINARY_DIR}")
# DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/src/templates")
# #
#add_custom_target(index_html #add_custom_target(template_folder
# ALL DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/templates") # ALL DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/templates")
# #
#ADD_DEPENDENCIES(${PROJECT_NAME} #ADD_DEPENDENCIES(${PROJECT_NAME}
# index_html) # template_folder)
#file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/src/templates"
# DESTINATION "${CMAKE_CURRENT_BINARY_DIR}")
#
#include(copy_files)
#copy_files(${CMAKE_CURRENT_SOURCE_DIR}/src/templates/ *.html ${CMAKE_CURRENT_BINARY_DIR})
#
file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/src/templates" macro(configure_files srcDir destDir)
DESTINATION "${CMAKE_CURRENT_BINARY_DIR}") message(STATUS "Configuring directory ${destDir}")
make_directory(${destDir})
file(GLOB templateFiles RELATIVE ${srcDir} ${srcDir}/*)
foreach(templateFile ${templateFiles})
set(srcTemplatePath ${srcDir}/${templateFile})
if(NOT IS_DIRECTORY ${srcTemplatePath})
message(STATUS "Configuring file ${templateFile}")
configure_file(
${srcTemplatePath}
${destDir}/${templateFile}
@ONLY)
endif(NOT IS_DIRECTORY ${srcTemplatePath})
endforeach(templateFile)
endmacro(configure_files)
configure_files(${CMAKE_CURRENT_SOURCE_DIR}/src/templates ${CMAKE_CURRENT_BINARY_DIR}/templates)
configure_files(${CMAKE_CURRENT_SOURCE_DIR}/src/templates/css ${CMAKE_CURRENT_BINARY_DIR}/templates/css)
#macro(copy_files GLOBPAT DESTINATION)
#
# message(STATUS "Configuring directory ${DESTINATION}")
#
# file(GLOB COPY_FILES
# RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
# ${GLOBPAT})
# add_custom_target(copy ALL
# COMMENT "Copying files: ${GLOBPAT}")
#
# foreach(FILENAME ${COPY_FILES})
# set(SRC "${CMAKE_CURRENT_SOURCE_DIR}/${FILENAME}")
# set(DST "${DESTINATION}/${FILENAME}")
#
# add_custom_command(
# TARGET copy
# COMMAND ${CMAKE_COMMAND} -E copy ${SRC} ${DST}
# )
# endforeach(FILENAME)
#endmacro(copy_files)
#
#copy_files(${CMAKE_CURRENT_SOURCE_DIR}/src/templates ${CMAKE_CURRENT_BINARY_DIR})
target_link_libraries(${PROJECT_NAME} target_link_libraries(${PROJECT_NAME}
myxrm myxrm

@ -0,0 +1,96 @@
#
# Utility macros for copying files
#
# Last update: 9th January 2013
#
#
# Create a target for copying files.
#
if (NOT TARGET copy_files)
add_custom_target(copy_files ALL)
endif()
#
# Create a variable to keep track of the number of copy files targets created.
#
if (NOT copy_target_count)
set(copy_target_count 0)
endif (NOT copy_target_count)
set(copy_target_count ${copy_target_count} CACHE INTERNAL "" FORCE)
#-------------------------------------------------------------------------------
# Macro: COPY_FILES
#-------------------------------------------------------------------------------
#
# Description:
# Adds a command to the build target 'copy_files' which copies files matching
# the specifeid globbing expression from the specified source directory to
# the specified destination directory.
#
# Usage:
# COPY_FILES(SRC_DIR GLOB_PAT DST_DIR)
#
# Arguments:
# - SRC_DIR : The source directory containging files to be copied.
# - GLOB_PAT : globbing expression used to match files for copying.
# - DST_DIR : The destination directory where files are to be copied to.
#
# Example:
# copy_files(${CMAKE_CURRENT_SOURCE_DIR} *.dat ${CMAKE_CURRENT_BINARY_DIR})
# Will copy all files in the current source directory with the extension
# '.dat' into the current binary directory.
#
macro(COPY_FILES SRC_DIR GLOB_PAT DST_DIR)
file(GLOB file_list
RELATIVE ${SRC_DIR}
${SRC_DIR}/${GLOB_PAT})
math(EXPR copy_target_count '${copy_target_count}+1')
set(copy_target_count ${copy_target_count} CACHE INTERNAL "" FORCE)
set(target "copy_files_${copy_target_count}")
add_custom_target(${target})
foreach(filename ${file_list})
set(src "${SRC_DIR}/${filename}")
set(dst "${DST_DIR}/${filename}")
add_custom_command(TARGET ${target} PRE_BUILD
COMMAND ${CMAKE_COMMAND} -E copy ${src} ${dst}
COMMENT "copying: ${src} to ${dst} " VERBATIM
)
endforeach(filename)
#add_dependencies(copy_files ${target})
add_dependencies(copy_files crowxmr)
endmacro(COPY_FILES)
#-------------------------------------------------------------------------------
# Macro: COPY_FILE
#-------------------------------------------------------------------------------
#
# Description:
# Adds a command to the build target 'copy_files' which copies the specified
# file to the specified destination.
#
# Usage:
# COPY_FILE(SRC DST)
#
# Arguments:
# - SRC : The source filename path (the file to be copied).
# - DST : The destiation filename path.
#
# Example:
# copy_file(
# ${CMAKE_CURRENT_SOURCE_DIR}/myfile.txt
# ${CMAKE_CURRENT_BINARY_DIR}/myfile.txt
# )
#
macro(COPY_FILE SRC DST)
math(EXPR copy_target_count '${copy_target_count}+1')
set(copy_target_count ${copy_target_count} CACHE INTERNAL "" FORCE)
set(target "copy_files_${copy_target_count}")
add_custom_target(${target})
add_custom_command(TARGET ${target} PRE_BUILD
COMMAND ${CMAKE_COMMAND} -E copy ${SRC} ${DST}
COMMENT "copying: ${SRC} to ${DST}" VERBATIM
)
add_dependencies(copy_files ${target})
endmacro(COPY_FILE)

@ -0,0 +1,57 @@
//
// Created by mwo on 24/05/15.
//
// source: http://codereview.stackexchange.com/questions/13176/infix-iterator-code
// infix_iterator.h
#if !defined(INFIX_ITERATOR_H_)
#define INFIX_ITERATOR_H_
#include <ostream>
#include <iterator>
#include <string>
template <class T, class charT=char, class traits=std::char_traits<charT> >
class infix_ostream_iterator :
public std::iterator<std::output_iterator_tag, void, void, void, void>
{
std::basic_ostream<charT,traits> *os;
std::basic_string<charT> delimiter;
std::basic_string<charT> real_delim;
public:
typedef charT char_type;
typedef traits traits_type;
typedef std::basic_ostream<charT, traits> ostream_type;
infix_ostream_iterator(ostream_type &s)
: os(&s)
{}
infix_ostream_iterator(ostream_type &s, charT const *d)
: os(&s),
real_delim(d)
{}
infix_ostream_iterator<T, charT, traits> &operator=(T const &item)
{
*os << delimiter << item;
delimiter = real_delim;
return *this;
}
infix_ostream_iterator<T, charT, traits> &operator*() {
return *this;
}
infix_ostream_iterator<T, charT, traits> &operator++() {
return *this;
}
infix_ostream_iterator<T, charT, traits> &operator++(int) {
return *this;
}
};
#endif

@ -47,6 +47,13 @@ int main() {
return xmrblocks.index(); return xmrblocks.index();
}); });
CROW_ROUTE(app, "/css/style.css")
([&]() {
return xmreg::read("./templates/css/style.css");
});
app.port(8080).multithreaded().run(); app.port(8080).multithreaded().run();
return 0; return 0;

@ -19,12 +19,16 @@
#include "tools.h" #include "tools.h"
#include <algorithm>
#include<ctime>
#define TMPL_DIR "./templates" #define TMPL_DIR "./templates"
#define TMPL_INDEX TMPL_DIR "/index.html" #define TMPL_INDEX TMPL_DIR "/index.html"
#define TMPL_HEADER TMPL_DIR "/header.html" #define TMPL_HEADER TMPL_DIR "/header.html"
#define TMPL_FOOTER TMPL_DIR "/footer.html" #define TMPL_FOOTER TMPL_DIR "/footer.html"
#define READ_TMPL(tmpl_path) xmreg::read(tmpl_path)
namespace xmreg { namespace xmreg {
@ -49,50 +53,102 @@ namespace xmreg {
string string
index() index()
{ {
//get current server timestamp
time_t server_timestamp = std::time(nullptr);
// get the current blockchain height. Just to check if it reads ok. // get the current blockchain height. Just to check if it reads ok.
uint64_t height = core_storage->get_current_blockchain_height() - 1; uint64_t height = core_storage->get_current_blockchain_height() - 1;
// initalise page tempate map with basic info about blockchain
mstch::map context { mstch::map context {
{"height", fmt::format("{:d}", height)}, {"height", fmt::format("{:d}", height)},
{"server_timestamp", xmreg::timestamp_to_str(server_timestamp)},
{"blocks", mstch::array()} {"blocks", mstch::array()}
}; };
size_t no_of_last_blocks {50}; // number of last blocks to show
size_t no_of_last_blocks {100};
// get reference to blocks template map to be field below
mstch::array& blocks = boost::get<mstch::array>(context["blocks"]); mstch::array& blocks = boost::get<mstch::array>(context["blocks"]);
// iterate over last no_of_last_blocks of blocks
for (size_t i = height; i > height - no_of_last_blocks; --i) for (size_t i = height; i > height - no_of_last_blocks; --i)
{ {
// get block at the given height i
block blk; block blk;
mcore->get_block_by_height(i, blk); mcore->get_block_by_height(i, blk);
// get block's hash
crypto::hash blk_hash = core_storage->get_block_id_by_height(i); crypto::hash blk_hash = core_storage->get_block_id_by_height(i);
// get xmr in the block reward
array<uint64_t, 2> coinbase_tx = sum_money_in_tx(blk.miner_tx);
// get transactions in the block
const vector<cryptonote::transaction>& txs_in_blk =
core_storage->get_db().get_tx_list(blk.tx_hashes);
// sum xmr in the inputs and ouputs of all transactions
array<uint64_t, 2> sum_xmr_in_out = sum_money_in_txs(txs_in_blk);
// get mixin number in each transaction
vector<uint64_t> mixin_numbers = get_mixin_no_in_txs(txs_in_blk);
// find minimum and maxium mixin numbers
int mixin_min {-1};
int mixin_max {-1};
if (!mixin_numbers.empty())
{
mixin_min = static_cast<int>(
*std::min_element(mixin_numbers.begin(), mixin_numbers.end()));
mixin_max = static_cast<int>(
*max_element(mixin_numbers.begin(), mixin_numbers.end()));
}
auto mixin_format = [=]() -> mstch::node
{
if (mixin_min < 0)
{
return string("N/A");
}
return fmt::format("{:d} - {:d}", mixin_min, mixin_max);
};
// set output page template map
blocks.push_back(mstch::map { blocks.push_back(mstch::map {
{"height" , to_string(i)}, {"height" , to_string(i)},
{"timestamp" , xmreg::timestamp_to_str(blk.timestamp)}, {"timestamp" , xmreg::timestamp_to_str(blk.timestamp)},
{"hash" , fmt::format("{:s}", blk_hash)}, {"hash" , fmt::format("{:s}", blk_hash)},
{"notx" , fmt::format("{:d}", blk.tx_hashes.size())} {"block_reward", fmt::format("{:0.4f}", XMR_AMOUNT(coinbase_tx[1]))},
{"notx" , fmt::format("{:d}", blk.tx_hashes.size())},
{"xmr_inputs" , fmt::format("{:0.4f}", XMR_AMOUNT(sum_xmr_in_out[0]))},
{"xmr_outputs" , fmt::format("{:0.4f}", XMR_AMOUNT(sum_xmr_in_out[1]))},
{"mixin_range" , mstch::lambda {mixin_format}}
}); });
} }
// read index.html
std::string index_html = xmreg::read(TMPL_INDEX);
std::string view = READ_TMPL(TMPL_INDEX); // add header and footer
string full_page = get_full_page(index_html);
string full_page = get_full_page(view); // render the page
return mstch::render(full_page, context);
return mstch::render(view, context);
} }
private: private:
string string
get_full_page(string& middle) get_full_page(string& middle)
{ {
return READ_TMPL(TMPL_HEADER) return xmreg::read(TMPL_HEADER)
+ middle + middle
+ READ_TMPL(TMPL_FOOTER); + xmreg::read(TMPL_FOOTER);
} }
}; };

@ -0,0 +1,5 @@
tr {
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
font-size : 14px;
height: 22px;
}

@ -2,7 +2,8 @@
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<title>Monero blocks</title> <title>Hidden Monero Explorer</title>
<link rel="stylesheet" type="text/css" href="/css/style.css">
</head> </head>
<body> <body>
<div> <div>

@ -1,15 +1,28 @@
<h1>Hidden Monero blockchain explorer</h1> <h1>Hidden Monero blockchain explorer</h1>
<h2>Current height: {{height}}</h2> <h2>Current height: {{height}} | Server time {{server_timestamp}}</h2>
<div> <div>
<ul> <ul>
<table> <table>
<tr>
<td>height</td>
<td>timestamp</td>
<td>block_hash</td>
<td>block_reward</td>
<td>no_of_txs</td>
<td>xmr_inputs</td>
<td>xmr_outputs</td>
<td>mixin_range</td>
</tr>
{{#blocks}} {{#blocks}}
<tr> <tr>
<td>{{height}}</td> <td>{{height}}</td>
<td>{{timestamp}}</td> <td>{{timestamp}}</td>
<td>{{hash}}</td> <td>{{hash}}</td>
<td>{{block_reward}}</td>
<td>{{notx}}</td> <td>{{notx}}</td>
<td>{{xmr_outputs}}</td>
<td>{{mixin_range}}</td>
</tr> </tr>
{{/blocks}} {{/blocks}}
</table> </table>

@ -307,6 +307,36 @@ namespace xmreg
return sum_xmr; return sum_xmr;
} }
array<uint64_t, 2>
sum_money_in_tx(const transaction& tx)
{
array<uint64_t, 2> sum_xmr;
sum_xmr[0] = sum_money_in_inputs(tx);
sum_xmr[1] = sum_money_in_outputs(tx);
return sum_xmr;
};
array<uint64_t, 2>
sum_money_in_txs(const vector<transaction>& txs)
{
array<uint64_t, 2> sum_xmr {0,0};
for (const transaction& tx: txs)
{
sum_xmr[0] += sum_money_in_inputs(tx);
sum_xmr[1] += sum_money_in_outputs(tx);
}
return sum_xmr;
};
vector<pair<txout_to_key, uint64_t>> vector<pair<txout_to_key, uint64_t>>
get_ouputs(const transaction& tx) get_ouputs(const transaction& tx)
{ {
@ -363,6 +393,19 @@ namespace xmreg
return mixin_no; return mixin_no;
} }
vector<uint64_t>
get_mixin_no_in_txs(const vector<transaction>& txs)
{
vector<uint64_t> mixin_no;
for (const transaction& tx: txs)
{
mixin_no.push_back(get_mixin_no(tx));
}
return mixin_no;
}
vector<txin_to_key> vector<txin_to_key>
get_key_images(const transaction& tx) get_key_images(const transaction& tx)
@ -461,10 +504,11 @@ namespace xmreg
{ {
if (!bf::exists(bf::path(filename))) if (!bf::exists(bf::path(filename)))
{ {
cerr << "File does not exist: " << filename << endl;
return string(); return string();
} }
std::ifstream t("./templates/index.html"); std::ifstream t(filename);
return string(std::istreambuf_iterator<char>(t), return string(std::istreambuf_iterator<char>(t),
std::istreambuf_iterator<char>()); std::istreambuf_iterator<char>());
} }

@ -7,10 +7,14 @@
#define PATH_SEPARARTOR '/' #define PATH_SEPARARTOR '/'
#define XMR_AMOUNT(value) \
static_cast<double>(value) / 1e12
#include "monero_headers.h" #include "monero_headers.h"
#include "tx_details.h" #include "tx_details.h"
#include "../ext/dateparser.h" #include "../ext/dateparser.h"
#include "../ext/infix_iterator.h"
#include <boost/filesystem.hpp> #include <boost/filesystem.hpp>
#include <boost/optional.hpp> #include <boost/optional.hpp>
@ -128,9 +132,18 @@ namespace xmreg
uint64_t uint64_t
sum_money_in_inputs(const transaction& tx); sum_money_in_inputs(const transaction& tx);
array<uint64_t, 2>
sum_money_in_tx(const transaction& tx);
array<uint64_t, 2>
sum_money_in_txs(const vector<transaction>& txs);
uint64_t uint64_t
get_mixin_no(const transaction& tx); get_mixin_no(const transaction& tx);
vector<uint64_t>
get_mixin_no_in_txs(const vector<transaction>& txs);
vector<pair<txout_to_key, uint64_t>> vector<pair<txout_to_key, uint64_t>>
get_ouputs(const transaction& tx); get_ouputs(const transaction& tx);
@ -162,6 +175,22 @@ namespace xmreg
string string
read(string filename); read(string filename);
/**
* prints an iterable such as vector
*/
template<typename T>
void print_iterable(const T & elems) {
infix_ostream_iterator<typename T::value_type>
oiter(std::cout, ",");
std::cout << "[";
std::copy(elems.begin(), elems.end(),oiter);
std::cout << "]" << std::endl;
}
} }
#endif //XMREG01_TOOLS_H #endif //XMREG01_TOOLS_H

Loading…
Cancel
Save