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)
#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
crowxmr)
project(${PROJECT_NAME})
set(CMAKE_CXX_FLAGS
@ -82,24 +88,70 @@ add_subdirectory(src/)
set(SOURCE_FILES
main.cpp)
ADD_CUSTOM_TARGET(driver DEPENDS src/templates/index.html)
#ADD_CUSTOM_TARGET(driver DEPENDS src/templates/index.html)
add_executable(${PROJECT_NAME}
${SOURCE_FILES})
#add_custom_command(OUTPUT template_folder
# COMMAND ${CMAKE_COMMAND} -E
# copy_directory "${CMAKE_CURRENT_SOURCE_DIR}/src/templates" "${CMAKE_CURRENT_BINARY_DIR}"
# DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/src/templates")
#add_custom_command(TARGET template_folder POST_BUILD
# COMMAND ${CMAKE_COMMAND} -E copy_directory
# "${CMAKE_CURRENT_SOURCE_DIR}/src/templates" "${CMAKE_CURRENT_BINARY_DIR}")
#
#add_custom_target(index_html
#add_custom_target(template_folder
# ALL DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/templates")
#
#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"
DESTINATION "${CMAKE_CURRENT_BINARY_DIR}")
macro(configure_files srcDir destDir)
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}
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();
});
CROW_ROUTE(app, "/css/style.css")
([&]() {
return xmreg::read("./templates/css/style.css");
});
app.port(8080).multithreaded().run();
return 0;

@ -19,12 +19,16 @@
#include "tools.h"
#include <algorithm>
#include<ctime>
#define TMPL_DIR "./templates"
#define TMPL_INDEX TMPL_DIR "/index.html"
#define TMPL_HEADER TMPL_DIR "/header.html"
#define TMPL_FOOTER TMPL_DIR "/footer.html"
#define READ_TMPL(tmpl_path) xmreg::read(tmpl_path)
namespace xmreg {
@ -49,50 +53,102 @@ namespace xmreg {
string
index()
{
//get current server timestamp
time_t server_timestamp = std::time(nullptr);
// get the current blockchain height. Just to check if it reads ok.
uint64_t height = core_storage->get_current_blockchain_height() - 1;
// initalise page tempate map with basic info about blockchain
mstch::map context {
{"height", fmt::format("{:d}", height)},
{"server_timestamp", xmreg::timestamp_to_str(server_timestamp)},
{"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"]);
// iterate over last no_of_last_blocks of blocks
for (size_t i = height; i > height - no_of_last_blocks; --i)
{
// get block at the given height i
block blk;
mcore->get_block_by_height(i, blk);
// get block's hash
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 {
{"height" , to_string(i)},
{"timestamp" , xmreg::timestamp_to_str(blk.timestamp)},
{"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);
return mstch::render(view, context);
// render the page
return mstch::render(full_page, context);
}
private:
string
get_full_page(string& middle)
{
return READ_TMPL(TMPL_HEADER)
return xmreg::read(TMPL_HEADER)
+ 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">
<head>
<meta charset="UTF-8">
<title>Monero blocks</title>
<title>Hidden Monero Explorer</title>
<link rel="stylesheet" type="text/css" href="/css/style.css">
</head>
<body>
<div>

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

@ -307,6 +307,36 @@ namespace xmreg
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>>
get_ouputs(const transaction& tx)
{
@ -363,6 +393,19 @@ namespace xmreg
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>
get_key_images(const transaction& tx)
@ -461,10 +504,11 @@ namespace xmreg
{
if (!bf::exists(bf::path(filename)))
{
cerr << "File does not exist: " << filename << endl;
return string();
}
std::ifstream t("./templates/index.html");
std::ifstream t(filename);
return string(std::istreambuf_iterator<char>(t),
std::istreambuf_iterator<char>());
}

@ -7,10 +7,14 @@
#define PATH_SEPARARTOR '/'
#define XMR_AMOUNT(value) \
static_cast<double>(value) / 1e12
#include "monero_headers.h"
#include "tx_details.h"
#include "../ext/dateparser.h"
#include "../ext/infix_iterator.h"
#include <boost/filesystem.hpp>
#include <boost/optional.hpp>
@ -128,9 +132,18 @@ namespace xmreg
uint64_t
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
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>>
get_ouputs(const transaction& tx);
@ -162,6 +175,22 @@ namespace xmreg
string
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

Loading…
Cancel
Save