Add process.cpp/hpp and auth_tests; Edit test/CMakeLists.txt

pull/1/head
Lartey D 2 years ago
parent e856ed30be
commit 0c005a41b0

3
.gitmodules vendored

@ -13,3 +13,6 @@
[submodule "external/raft"]
path = external/raft
url = https://github.com/willemt/raft.git
[submodule "external/stduuid"]
path = external/stduuid
url = https://github.com/mariusbancila/stduuid.git

@ -1,14 +1,18 @@
cmake_minimum_required(VERSION 3.1.0 FATAL_ERROR)
# Set cmake modules directory
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake" "${CMAKE_CURRENT_SOURCE_DIR}/external/monero-cpp/external/monero-project/cmake")
project(neroshop) # tested on Ubuntu 20.04 LTS (focal) with gcc (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0, manjaro-xfce-21.2.6 (Qonos) with gcc (GCC) 11.2.0
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(VERSION_MAJOR "0")
set(VERSION_MINOR "1")
set(VERSION_PATCH "0")
set(PROJECT_VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH})
option(NEROSHOP_BUILD_TESTS "Build neroshop tests" OFF)
option(NEROSHOP_BUILD_GUI "Build neroshop GUI" OFF) # CLI is built by default so it won't need an option
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake" "${CMAKE_CURRENT_SOURCE_DIR}/external/monero-cpp/external/monero-project/cmake" "${CMAKE_CURRENT_SOURCE_DIR}/external/dokun-ui/cmake")
######################################
if(WIN32)
endif()
@ -27,11 +31,6 @@ endif()
if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
endif()
######################################
# use a specific C++ version
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
######################################
######################################
set(MONERO_PROJECT "${CMAKE_SOURCE_DIR}/external/monero-cpp/external/monero-project")
set(MONERO_PROJECT_SRC "${MONERO_PROJECT}/src")
@ -69,14 +68,14 @@ endif()
message(STATUS EXTRA_LIBRARIES: ${EXTRA_LIBRARIES})
######################################
# Protobuf (recent)
# Protobuf
include(FindProtobuf)
find_package(Protobuf)
message(STATUS "Protobuf lib: ${Protobuf_LIBRARY}, inc: ${Protobuf_INCLUDE_DIR}, protoc: ${Protobuf_PROTOC_EXECUTABLE}")
include_directories(${Protobuf_INCLUDE_DIR})
######################################
# LibUSB (recent)
# LibUSB
find_library(usb_LIBRARY NAMES usb-1.0 libusb usb)
set(LibUSB_LIBRARIES ${usb_LIBRARY})
@ -311,11 +310,16 @@ if(NOT LIBUV_FOUND)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/external/libuv/include ${CMAKE_CURRENT_SOURCE_DIR}/external/libuv/src)
set(libuv_src ${CMAKE_CURRENT_SOURCE_DIR}/external/libuv/.libs/libuv.a) # In case user chooses to build libuv themselves instead of installing it on the system
endif()
######################################
# willemt/raft (BSD and has zero dependencies :D)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/external/raft/include)
set(raft_src ${CMAKE_CURRENT_SOURCE_DIR}/build/libraft.a)#set(raft_src ${CMAKE_CURRENT_SOURCE_DIR}/external/raft/src/raft_log.c ${CMAKE_CURRENT_SOURCE_DIR}/external/raft/src/raft_node.c ${CMAKE_CURRENT_SOURCE_DIR}/external/raft/src/raft_server.c ${CMAKE_CURRENT_SOURCE_DIR}/external/raft/src/raft_server_properties.c)
######################################
# stduuid (header-only MIT library for generating uuids)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/external/stduuid ${CMAKE_CURRENT_SOURCE_DIR}/external/stduuid/catch ${CMAKE_CURRENT_SOURCE_DIR}/external/stduuid/include)
######################################
# dokun-ui_dependencies
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/external/dokun-ui/external/lua/lua-5.4.1/src) # lua
@ -340,18 +344,18 @@ include_directories(#[[${CMAKE_CURRENT_SOURCE_DIR}/external/flac]] # config.h
${CMAKE_CURRENT_SOURCE_DIR}/external/dokun-ui/external/flac/include
${CMAKE_CURRENT_SOURCE_DIR}/external/dokun-ui/external/flac/src/libFLAC/include) # for "private/cpu.h"
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/external/dokun-ui/external/glm)
if(WIN32)
set(winsocket_src ws2_32.lib ) # -lglfw3 -lgdi32 -lopengl32 -limm32
endif()
if(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
set(OpenGL_GL_PREFERENCE "LEGACY" ) # LEGACY(libGL.so) OR GLVND(libOpenGL.so and libGLX.so)
set(posix_src libpthread.so libdl.so libm.so )
endif() # -framework OpenGL -framework Cocoa -framework IOKit -framework CoreVideo
######################################
# dokun-ui
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/external/dokun-ui/include)
set(dokun_ui_src ${CMAKE_CURRENT_SOURCE_DIR}/external/dokun-ui/src/libdokun-ui.a) # definitions added: DOKUN_OPENGL, DOKUN_BUILD_LIBRARY#add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/external/dokun-ui)
######################################
# neroshop tests
if(NEROSHOP_BUILD_TESTS)
message(STATUS "NEROSHOP_BUILD_TESTS option set to ON")
add_subdirectory(test)
endif()
######################################
# neroshop-daemon
set(daemon_executable "neromon")
@ -364,31 +368,54 @@ set(neroshop_executable "neroshop")
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/external)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
link_directories(${CMAKE_CURRENT_SOURCE_DIR}/src ${CMAKE_CURRENT_SOURCE_DIR}/build)
set(neroshop_src src/buyer.cpp #[[src/carrier.cpp]] src/cart.cpp src/catalog.cpp src/client.cpp src/converter.cpp src/database.cpp src/encryptor.cpp src/icon.cpp src/item.cpp src/main.cpp src/message.cpp src/order.cpp src/qr.cpp src/seller.cpp src/server.cpp src/user.cpp src/validator.cpp src/wallet.cpp)
add_definitions(-DNEROSHOP_DEBUG) # for more detailed debugging, use -DNEROSHOP_DEBUG0
set(neroshop_src src/buyer.cpp #[[src/carrier.cpp]] src/cart.cpp src/catalog.cpp src/client.cpp src/converter.cpp src/database.cpp src/encryptor.cpp src/icon.cpp src/item.cpp src/main.cpp src/message.cpp src/order.cpp src/process.cpp src/qr.cpp src/seller.cpp src/server.cpp src/user.cpp src/validator.cpp src/wallet.cpp)
add_definitions(-DNEROSHOP_DEBUG) # for more detailed debugging, use -DNEROSHOP_DEBUG0 # set_target_properties(${neroshop_executable} PROPERTIES COMPILE_DEFINITIONS "NEROSHOP_DEBUG")
add_executable(${neroshop_executable} ${neroshop_src})
target_link_libraries(${neroshop_executable} ${monero_cpp_src} ${sqlite_src} ${qr_code_generator_src} ${dokun_ui_src} ${raft_src} ${libuv_src} ${curl_src} ${monero_src})
# todo: create separate targets - neroshop-gui and neroshop-cli
######################################
# note: currently the CLI depends on dokun-ui for Window, File, Script (config.h), libpng (qr.cpp), lua (script.cpp), etc. (catalog.cpp also uses GUI features)
if(DEFINED NEROSHOP_USE_LIBBCRYPT) # -DNEROSHOP_USE_LIBBCRYPT=1
message(STATUS "Using libbcrypt: ${bcrypt_src}")
target_compile_definitions(${neroshop_executable} PUBLIC -DNEROSHOP_USE_LIBBCRYPT)
target_link_libraries(${neroshop_executable} ${bcrypt_src})
endif()
if(WIN32)
set(winsock2_src ws2_32.lib) # -lglfw3 -lgdi32 -lopengl32 -limm32
target_link_libraries(${neroshop_executable} ${winsock2_src})
target_link_libraries(${daemon_executable} ${winsock2_src})
endif()
if(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
set(posix_src libpthread.so libdl.so libm.so)
target_link_libraries(${neroshop_executable} ${posix_src})
target_link_libraries(${daemon_executable} ${posix_src})
find_package(X11 REQUIRED)
if(X11_FOUND)
#if(NEROSHOP_BUILD_GUI)
target_link_libraries(${neroshop_executable} ${X11_LIBRARIES})
target_link_libraries(${daemon_executable} ${X11_LIBRARIES})
#target_link_libraries(${daemon_executable} ${X11_LIBRARIES}) # todo: remove this. Daemon won't be using GUI features
#endif()
endif()
endif()
set(OpenGL_GL_PREFERENCE "LEGACY") # LEGACY (libGL.so) or GLVND (libOpenGL.so and libGLX.so)
find_package(OpenGL REQUIRED)
if(OPENGL_FOUND)
#if(NEROSHOP_BUILD_GUI)
target_compile_definitions(${neroshop_executable} PRIVATE DOKUN_USE_OPENGL)
target_link_libraries(${neroshop_executable} ${OPENGL_LIBRARIES})
target_link_libraries(${daemon_executable} ${OPENGL_LIBRARIES})
#endif()
endif()
find_package(GLFW3)
if(GLFW3_FOUND)
#if(NEROSHOP_BUILD_GUI)
target_compile_definitions(${neroshop_executable} PRIVATE DOKUN_USE_GLFW) # already defined in libdokun-ui.a
target_link_libraries(${neroshop_executable} ${GLFW3_LIBRARY})
#endif()
endif()
######################################

@ -6,38 +6,44 @@ set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ../build)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ../build)
# compile the source code of external dependencies into a static library so there won't be a need to recompile each time there's a change in the makefile
include_directories(monero-cpp/external/monero-project/contrib/epee/include/
set(monero_include_dirs monero-cpp/external/monero-project/contrib/epee/include/
monero-cpp/external/monero-project/external/easylogging++/
monero-cpp/external/monero-project/src/
monero-cpp/external/monero-project/external/rapidjson/include/
monero-cpp/external/monero-project/external/
)
include_directories(monero-cpp/src/)
set(monero_cpp "monero-cpp")
set(monero_cpp_srcs monero-cpp/src/utils/gen_utils.cpp monero-cpp/src/utils/monero_utils.cpp monero-cpp/src/daemon/monero_daemon_model.cpp monero-cpp/src/daemon/monero_daemon.cpp monero-cpp/src/wallet/monero_wallet_model.cpp monero-cpp/src/wallet/monero_wallet_keys.cpp monero-cpp/src/wallet/monero_wallet_full.cpp)
add_library(monero-cpp STATIC ${monero_cpp_srcs})
add_library(${monero_cpp} STATIC ${monero_cpp_srcs})
target_include_directories(${monero_cpp} PUBLIC monero-cpp/src/ ${monero_include_dirs})
if(DEFINED NEROSHOP_USE_LIBBCRYPT) # -DNEROSHOP_USE_LIBBCRYPT=1
include_directories(libbcrypt/)
set(bcrypt "bcrypt")
set(libbcrypt_srcs libbcrypt/crypt_blowfish/crypt_blowfish.c libbcrypt/crypt_blowfish/crypt_gensalt.c libbcrypt/crypt_blowfish/wrapper.c libbcrypt/bcrypt.c)
message(STATUS "Building libbcrypt: ${libbcrypt_srcs}")
add_library(bcrypt STATIC ${libbcrypt_srcs})
add_library(${bcrypt} STATIC ${libbcrypt_srcs})
target_include_directories(${bcrypt} PUBLIC libbcrypt/)
endif()
include_directories(QR-Code-generator/cpp/)
set(qrcodegen "qrcodegen")
set(QR_Code_generator_srcs QR-Code-generator/cpp/qrcodegen.cpp) # or QR-Code-generator/c/qrcodegen.c
add_library(qrcodegen STATIC ${QR_Code_generator_srcs})
add_library(${qrcodegen} STATIC ${QR_Code_generator_srcs})
target_include_directories(${qrcodegen} PUBLIC QR-Code-generator/cpp/)
include_directories(sqlite/)
set(sqlite3 "sqlite3")
set(sqlite_srcs sqlite/sqlite3.c)
add_library(sqlite3 STATIC ${sqlite_srcs})
add_library(${sqlite3} STATIC ${sqlite_srcs})
target_include_directories(${sqlite3} PUBLIC sqlite/)
include_directories(raft/include/)
set(raft "raft")
set(raft_srcs raft/src/raft_log.c raft/src/raft_node.c raft/src/raft_server.c raft/src/raft_server_properties.c)
add_library(raft STATIC ${raft_srcs})
add_library(${raft} STATIC ${raft_srcs})
target_include_directories(${raft} PUBLIC raft/include/)
#[[
include_directories()
set(_target "")
set(_srcs )
add_library( STATIC ${_srcs})
#set_target_properties( PROPERTIES PREFIX "")
add_library(${} STATIC ${_srcs})
target_include_directories(${} PUBLIC )
#set_target_properties(${} PROPERTIES PREFIX "")
]]

2
external/dokun-ui vendored

@ -1 +1 @@
Subproject commit 9139b628496693c228223bce5bc34694723d7844
Subproject commit bd1fce938d3dd0185769daaf37cb806b47a7a50c

1
external/stduuid vendored

@ -0,0 +1 @@
Subproject commit 3afe7193facd5d674de709fccc44d5055e144d7a

@ -7,7 +7,7 @@
#include "user.hpp" // includes "order.hpp"
namespace neroshop {
class Buyer : public User { // customers will not be required to register, unless they would like to save their order history
class Buyer : public User {
public:
Buyer();
Buyer(const std::string& name);
@ -20,6 +20,4 @@ private:
}; // save buyer's cart data, buyer can download order invoice
}
#endif
// https://calculator.academy/average-rating-calculator-star-rating/#f1p1|f2p0
// https://www.ebay.com/help/buying/resolving-issues-sellers/seller-ratings?id=4023&mkevt=1&mkcid=1&mkrid=711-53200-19255-0&campid=5336728181&customid=&toolid=10001

@ -2,12 +2,10 @@
#ifndef CART_HPP_NEROSHOP
#define CART_HPP_NEROSHOP
//#include <algorithm> // for std::find
//#include <chrono> // std::put_time
//#include <sstream> // std::stringstream
//#include <iomanip> // std::put_time
#include <iostream>
#include <memory> // std::shared_ptr, std::unique_ptr
#include <vector>
#include <algorithm> // std::find
#include "item.hpp"
#include "database.hpp"

@ -1,29 +1,25 @@
#ifndef CONFIG_HPP_NEROSHOP//DATABASE_LUA_HPP_NEROSHOP // recommended to add unique identifier like _NEROSHOP to avoid naming collision with other libraries
#define CONFIG_HPP_NEROSHOP//DATABASE_LUA_HPP_NEROSHOP
#pragma once
#ifndef CONFIG_HPP_NEROSHOP
#define CONFIG_HPP_NEROSHOP
#define LUA_TAG "\033[1;34m[lua]:\033[0m "
// configuration dir(s)
#ifdef _WIN32
#define NEROSHOP_PATH "" // haven't used windows in ages lol
#define NEROSHOP_CONFIG_PATH "" // haven't used windows in ages lol
#endif
#ifdef __gnu_linux__
#define NEROSHOP_CONFIG_PATH "/home/" + System::get_user() + "/.config/neroshop"
#define NEROSHOP_CONFIG_PATH "/home/" + neroshop::device::get_user() + "/.config/neroshop"
#endif
#define NEROSHOP_CONFIG_FILE "config.lua"
#include <script.hpp>
#include "debug.hpp"
//////////////////////////////
//extern lua_State * lua_state;// (luaL_newstate());//static lua_State * lua_state;// (luaL_newstate());//(nullptr);//should I use extern ?//because its in a namespace, there may not be a need to use extern // extern is for declaration in .h and then defined in a .cpp file
//////////////////////////////
namespace neroshop {
//namespace DB {
//class Lua {
//public:
//////////////////////////////
extern lua_State * lua_state;// (luaL_newstate());//static lua_State * lua_state;// (luaL_newstate());//(nullptr);//should I use extern ?//because its in a namespace, there may not be a need to use extern // extern is for declaration in .h and then defined in a .cpp file
extern lua_State * lua_state;// (luaL_newstate());//(nullptr);// extern is for declaration in .h and then defined in a .cpp file
//////////////////////////////
static bool load_config() {
std::string user = System::get_user();
@ -100,8 +96,6 @@ namespace neroshop {
static lua_State * get_lua_state() {
return lua_state;
}
//};
//}
}
#endif

@ -1,6 +1,9 @@
#ifndef DATABASE_HPP_NEROSHOP
#define DATABASE_HPP_NEROSHOP
#define NEROSHOP_DATABASE_PATH ""//#define NEROSHOP_DATABASE_NAME "data"
#define NEROSHOP_DATABASE_FILE "data.sqlite3"
#include "database/sqlite.hpp"
#endif

@ -1,12 +1,11 @@
#pragma once
#ifndef DATABASE_SQLITE_HPP_NEROSHOP
#define DATABASE_SQLITE_HPP_NEROSHOP
#define SQLITE3_TAG "\033[1;36m[sqlite3]:\033[0m "
#define SQLITE3_TAG_ERR "\033[1;36m[sqlite3]:\033[0;91m "
//#define NEROSHOP_DATABASE_PATH ""
#define NEROSHOP_DATABASE_FILE "data.sqlite3"
#include <sqlite3.h>
#include <iostream>
#include <cstdarg>
@ -20,22 +19,22 @@
#include "debug.hpp"
namespace neroshop {
namespace DB {
class SQLite3 {
namespace db {
class Sqlite3 {
public:
SQLite3();
SQLite3(const std::string& filename);
~SQLite3();
Sqlite3();
Sqlite3(const std::string& filename);
~Sqlite3();
bool open(const std::string& filename);
void close();
void execute(const std::string& command);
void execute_params(const std::string& command, const std::vector<std::string>& args);
// setters
//void set_singleton(const SQLite3& singleton); // transfer ownership of singleton to the SQLite3 unique_ptr
//void set_singleton(const Sqlite3& singleton); // transfer ownership of singleton to the Sqlite3 unique_ptr
// getters
static std::string get_sqlite_version();
sqlite3 * get_handle() const;
static SQLite3 * get_singleton();
static Sqlite3 * get_singleton();
void * get_blob(const std::string& command);
void * get_blob_params(const std::string& command, const std::vector<std::string>& args);
std::string get_text(const std::string& command);// const;
@ -50,7 +49,7 @@ public:
//bool rowid_exists(const std::string& table_name, int rowid);
private:
sqlite3 * handle;
static std::unique_ptr<SQLite3> singleton;
static std::unique_ptr<Sqlite3> singleton;
bool opened;
static int callback(void *not_used, int argc, char **argv, char **az_col_name);
};

@ -1,3 +1,5 @@
#pragma once
#ifndef DEBUG_HPP_NEROSHOP
#define DEBUG_HPP_NEROSHOP
@ -5,6 +7,9 @@
#define NEROSHOP_TAG_IN std::string("\033[1;35;49m[neroshop]: \033[0m") +
#define NEROSHOP_TAG NEROSHOP_TAG_IN
#define NEROSHOP_LOG_PATH ""
#define NEROSHOP_LOG_FILE "log.txt"
#include <iostream>
namespace neroshop {
@ -16,7 +21,7 @@ namespace neroshop {
if(code == 4) std::cout << "\033[1;35;49m" << "[neroshop]: " << "\033[1;34;49m" << text << "\033[0m" << std::endl;
}
inline void io_write(const std::string& text) {// like print but without a newline
std::cout << "\033[1;35;49m" << "[neroshop]: " << "\033[1;37;49m" << text << "\033[0m";// << std::endl; // magenta_text_bold
std::cout << "\033[1;35;49m" << "[neroshop]: " << "\033[1;37;49m" << text << "\033[0m";
}
}
#endif

@ -4,6 +4,7 @@
#include <openssl/rsa.h>
#include <openssl/pem.h> // includes "openssl/evp.h" which includes "openssl/bio.h"
#include <openssl/err.h>
#include <iostream>
#include <fstream>
#include <sstream>
@ -19,12 +20,9 @@ public:
static bool generate_key_pair();
static bool generate_key_pair_ex(); // requires openssl 3.0 // the _ex suffix is for extended versions of existing functions//static bool generate_public_key_from_private_key();
static EVP_PKEY * generate_key_pair_return();
static bool save_public_key(const EVP_PKEY * pkey);
static bool save_public_key(const EVP_PKEY * pkey, const std::string& filename);
static bool save_private_key(const EVP_PKEY * pkey);
static bool save_private_key(const EVP_PKEY * pkey, const std::string& filename);
static bool save_key_pair(const EVP_PKEY * pkey);
static bool save_key_pair(const EVP_PKEY * pkey, const std::string& filename);
static bool save_public_key(const EVP_PKEY * pkey, std::string filename = "public.pem");
static bool save_private_key(const EVP_PKEY * pkey, std::string filename = "private.pem");
static bool save_key_pair(const EVP_PKEY * pkey, std::string public_key_file = "public.pem", std::string private_key_file = "private.pem");
// encryption and decrypting functions - messages
static std::string public_encrypt(const std::string& public_key, const std::string& plain_text); // encrypts plain text with a receiver's public key then returns a cipher text otherwise it returns an empty string on failure
static std::string private_decrypt(const std::string& private_key, const std::string& cipher_text); // decrypts cipher text using the receiver's private key then returns a plain text otherwise it returns an empty string on failure

@ -1,9 +1,10 @@
//#pragma once
#pragma once
#ifndef ITEM_HPP_NEROSHOP
#define ITEM_HPP_NEROSHOP
#include <image.hpp>
#include <file.hpp> // for checking export file directory
#include <filesystem>
#include <iostream>
#include <vector>
#include <tuple> // std::tuple, std::get, std::tie, std::ignore

@ -30,5 +30,7 @@
#include "client.hpp"
#include "encryptor.hpp"
//#include "carrier.hpp" // not currently in use
#include "util.hpp"
#include "process.hpp"
#endif

@ -1,7 +1,13 @@
//#pragma once
#pragma once
#ifndef ORDER_HPP_NEROSHOP
#define ORDER_HPP_NEROSHOP
#if defined(__cplusplus) && (__cplusplus >= 201703L)
#include <uuid.h>
//#include <catch.hpp>
#endif
#include <iostream>
#include <map>
@ -46,39 +52,10 @@ public:
private:
void create_guest_order(const neroshop::Cart& cart, const std::string& shipping_address, std::string contact_info = ""); // order: order_id, [order_date], product, SKU, quantity, price (subtotal), discount (optional), shipping_cost/estimated_delivery, carrier[dhl, usps, etc.], payment method:monero[xmr], total
void create_registered_user_order(const neroshop::Cart& cart, const std::string& shipping_address, std::string contact_info = "");
static bool in_db(unsigned int order_number); // check if an order is in the order database // order #144
static bool in_db(unsigned int order_number); // check if an order is in the order database
unsigned int id;
order_status status; // order_status
// invoice: seller_username:layter, seller_receiver_subaddress:Axxxxxx, tx_status:processing(yellow),complete(green[paid]), confirmations:#, product_name:"Playstation 5" total_price:#xmr(#usd), currency:xmr, exchange_rate:1xmr=???usd, created_timestamp:YYYY-MM-DD HH:MM:SS, tx_speed:low,med,high shipping_to:10 rocket st boston ma 02115, tracking_number:####, carrier:usps, delivery_status:shipping_now|out_for_delivery|delivered|
// options:cancel_order|change_shipping_address,
order_status status;
void set_status(order_status status);
};
}
#endif
// https://support.bigcommerce.com/s/article/Orders?language=en_US
// https://docs.woocommerce.com/document/managing-orders/
/*
order_status:
pending // order created, but on hold/awaiting payment (unpaid) (yellow)
preparing // order received and now preparing item for shipment (green)
shipped // order shipped (can now be tracked and invoice can be printed)
ready // order ready for pick up (blue)
done // order delivered or picked_up (blue)
// in any event, an order can be cancelled or can failed ...
// user must specify reaason why order was cancelled
cancelled // order cancelled by buyer (can cancel order only before it ships) (gray)
failed // order failed due to payment not sent after 24 hours (red)
returned // order returned (returned does not necessarily mean refunded) (gray)
// just making sure enum contents are the same value
std::cout << "(order_status::ready == order_status::ready_for_pickup) : " << (order_status::ready == order_status::ready_for_pickup) << std::endl;
std::cout << "(order_status::done == order_status::delivered) : " << (order_status::done == order_status::delivered) << std::endl;
Categories:
Carriers: usps, fedex, ups, dhl (make a class Tracker for the carrier)
https://instantparcels.com/find-carrier-by-tracking-number
https://developers.facebook.com/docs/commerce-platform/order-management/carrier-codes
Payment methods: cryptocurrency (monero)
// NOTE: for every order, generate a new subaddress from seller's wallet
// order_cancellations: https://sellercentral.amazon.com/gp/help/external/G201722390?language=en_US
*/

@ -0,0 +1,65 @@
#pragma once
#ifndef PROCESS_HPP_NEROSHOP
#define PROCESS_HPP_NEROSHOP
#ifdef _WIN32
#include <windows.h>
#endif
#ifdef __gnu_linux__
#include <unistd.h> // fork, execvp
//#include <sys/types.h> // ?
#include <dirent.h> // closedir, opendir
#include <signal.h> // kill
#endif
//#include <uv.h>
#include <iostream>
#include <vector>
#include <tuple>
#include <filesystem>
#include <fstream>
#include "util.hpp"
#include "debug.hpp"
namespace neroshop {
class Process {
public:
Process();
Process(const std::string& program, const std::string& argument);
~Process();
void * open();
bool create(const std::string& program, const std::string& argument);
bool terminate();
static bool terminate(const Process& process);//void kill(); // linux
static void terminate_by_process_id(int process_id);
static void terminate_by_process_name(const std::string& process_name);
static void show_processes(); // pname, pid, pstatus
void exit(int code = 0);
// getters
#ifdef _WIN32
void * get_handle() const;
#endif
#ifdef __gnu_linux__
int get_handle() const;
std::string get_name() const;
static int get_process_by_name(const std::string& process_name);
#endif
static void * get_active();
///////////////////////////////
private:
#ifdef _WIN32
void * handle;
#endif
#ifdef __gnu_linux__
int handle;
std::string name;
#endif
static std::vector<std::tuple<std::string, int, bool>> process_list; // holds process_name (string) and process_id (int), process_status (bool)
}; // Process process("glue.exe", " srlua.exe test.lua test.exe");
}
#endif

@ -6,6 +6,7 @@ using std::uint8_t;
using qrcodegen::QrCode;
using qrcodegen::QrSegment;
#include <png.h>
#include <iostream>
#include <fstream>
#include <string>
@ -23,18 +24,23 @@ namespace neroshop {
class QR {
public:
QR();
QR(std::string fileName, int imgSize, std::string text,
bool overwriteExistingFile, QrCode::Ecc ecc);
QR(const std::string& filename, int image_size, const std::string& text,
bool overwrite, qrcodegen::QrCode::Ecc ecc);
~QR();
bool to_png() const;
bool write_to_png(const QrCode& qr_data, const int& multiplicator) const;
unsigned int image_size(const QrCode& qr_data) const;
unsigned int image_size_with_border(const QrCode& qr_data) const;
// getters
unsigned char * get_data() const; // pixel_data
std::string get_text() const;
unsigned int get_size() const; // image_size //unsigned int get_size_with_border() const;
std::string get_file() const; // file_name
// static
static bool export_png(const std::string& filename, int size, const std::string& text, bool overwrite, QrCode::Ecc ecc);
private:
bool write_to_png(const QrCode& qr_data, const int& multiplicator) const;
std::string filename;
int size;
std::string text;
bool overwrite_existing_file;
bool overwrite;
QrCode::Ecc ecc; // to-do: change this to a unique_ptr
};
}

@ -4,6 +4,8 @@
#include <cmath> // floor
#include <random>
#include <memory> // std::unique_ptr
#include <vector>
#include "wallet.hpp"
#include "user.hpp"

@ -5,6 +5,10 @@
#include <raft.h>
#include <unordered_map> // std::unordered_map
#include <functional> // std::function
//#if defined(__cplusplus) && (__cplusplus >= 201703L)
#include <any> // std::any (C++17)
//#endif
#include <stdexcept> // std::runtime_error
#include "database.hpp"
#include "debug.hpp"
@ -37,6 +41,7 @@ public:
//! \tparam F The type of the functor.
// bind function should work with lambdas too
template <typename F> void bind(std::string const &name, F functor) {
if(!functor) throw std::runtime_error("bind invalid function");
function_list[name] = functor;
}
@ -54,7 +59,12 @@ private:
// callbacks
void on_new_connection(uv_stream_t *server, int status);
// functors
std::unordered_map<std::string, std::function<void()>/*adaptor_type*/> function_list;
//#if defined(__cplusplus) && (__cplusplus < 201703L)
//std::unordered_map<std::string, std::function<void()>/*adaptor_type*/> function_list;
//#endif
//#if defined(__cplusplus) && (__cplusplus >= 201703L)
std::unordered_map<std::string, std::any> function_list;
//#endif
// references:
// https://github.com/rpclib/rpclib/blob/master/include/rpc/dispatcher.h
// https://github.com/rpclib/rpclib/blob/master/include/rpc/server.h

@ -0,0 +1,149 @@
#pragma once
#ifndef UTIL_HPP_NEROSHOP
#define UTIL_HPP_NEROSHOP
#ifdef _WIN32
#include <windows.h>
#include <Lmcons.h> // UNLEN
#endif
#ifdef __gnu_linux__
#include <unistd.h> // getcwd, getwd, get_current_dir_name, getpwnam, getpwnam_r, getpwuid, getpwuid_r
#include <sys/types.h> // ??
#include <dirent.h> // opendir, fdopendir, closedir
#include <pwd.h> // getpwnam, getpwnam_r, getpwuid, getpwuid_r
#include <sys/stat.h> // mkdir
#include <string.h> // strdup
#endif
#include <iostream>
#include <sstream> // std::ostringstream
#include <vector>
#include <algorithm> // std::transform
namespace neroshop {
namespace string {
static std::string lower(const std::string& str)
{
std::string temp_str = str;
std::transform(temp_str.begin(), temp_str.end(), temp_str.begin(), [](unsigned char c){ return std::tolower(c); });
return temp_str;
}
static std::string upper(const std::string& str)
{
std::string temp_str = str;
std::transform(temp_str.begin(), temp_str.end(), temp_str.begin(), [](unsigned char c){ return std::toupper(c); });
return temp_str;
}
template <typename T>
static std::string precision(const T value, const int n)
{
std::ostringstream out;
out.precision(n);
out << std::fixed << value;
return out.str();
}
static std::vector<std::string> split(const std::string& str, const std::string& delimiter)
{
std::vector<std::string> output;
char * dup = strdup(str.c_str());
char * token = strtok(dup, delimiter.c_str());
while(token != nullptr)
{
output.push_back(std::string(token));
token = strtok(nullptr, delimiter.c_str());
}
free(dup);
return output;
}
}
//-------------------------
namespace filesystem {
static bool is_file(const std::string& filename) { // checks if file exists
return std::filesystem::is_regular_file(filename);
}
static bool is_directory(const std::string& path) {
#if defined(__cplusplus) && (__cplusplus >= 201703L)
return std::filesystem::is_directory(path);
#endif
#ifdef _WIN32
DWORD dwAttrib = GetFileAttributes(path.c_str());
return (dwAttrib != INVALID_FILE_ATTRIBUTES && (dwAttrib & FILE_ATTRIBUTE_DIRECTORY));
#endif
#ifdef __gnu_linux__
DIR * dir = opendir(path.c_str());
if(dir) {
closedir(dir);
return true;
}
#endif
return false;
}
static bool make_directory(const std::string& path) {
if(is_directory(path)) {
std::cout << "\033[1;93mDirectory \"" << path << "\" already exists\033[0m" << std::endl;
return false;
}
#if defined(__cplusplus) && (__cplusplus >= 201703L)
return std::filesystem::create_directories(path.c_str());
#endif
#ifdef _WIN32
return (CreateDirectory(path.c_str(), nullptr) != 0);
#endif
#ifdef __gnu_linux__
return (mkdir(path.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) == 0);
#endif
return false;
}
static std::string current_directory() {
#if defined(__cplusplus) && (__cplusplus >= 201703L)
return std::filesystem::current_path();
#endif
#ifdef _WIN32
#endif
#ifdef __gnu_linux__
char buffer[1024];
if(getcwd(buffer, sizeof(buffer)) != nullptr)
return std::string(buffer);
#endif
return "";
}
//static std::vector<std::string> get_directory() { // return a list of filenames in a directory
//static dialog() {
// filename string manipulation
/*static std::string get_file_extension(const std::string& filename) {
std::string extension = filename.substr(filename.find_last_of(".") + 1);
return extension;
}*/
}
//-------------------------
namespace device {
static std::string get_user() {
#ifdef _WIN32
char username[UNLEN + 1];
DWORD username_len = UNLEN + 1;
if(GetUserName(username, &username_len) == 0)
return "";
return std::string(username);
#endif
#ifdef __gnu_linux__ // works!
uid_t uid = geteuid();
struct passwd * pw = getpwuid(uid);
if(!pw) return "";
return std::string(pw->pw_name);
#endif
return "";
}
}
}
#endif

@ -17,22 +17,17 @@
#include <iomanip> //std::put_time, std::setfill, std::setw
#include "database.hpp"
#include "encryptor.hpp"
// sha256 hash of wallet primary keys will be used to authenticate user
#include "config.hpp"
namespace neroshop {
class Validator {
class Validator {// Authenticator {
public:
static bool register_user(const std::string& username, const std::string& password, const std::string& confirm_pw, std::string opt_email = "");
static bool login(const std::string& username, const std::string& password);
static bool login_with_email(const std::string& email, const std::string& password);
static void save_user(const std::string& username, const char * pw_hash/*const char pw_hash[BCRYPT_HASHSIZE]*/, std::string email_hash = "");
static void change_pw(const std::string& old_pw, const std::string& new_pw, const std::string& confirm_new_pw);
// functions for P2P
static bool register_peer();
static bool login_peer();//(const std::string& username, const std::string&);
//static void save_peer();
//static void change_key();
// boolean
static bool validate_username(const std::string& username);
static bool validate_password(const std::string& password);

@ -1,4 +1,5 @@
//#pragma once
#pragma once
#ifndef WALLET_HPP_NEROSHOP
#define WALLET_HPP_NEROSHOP
@ -11,6 +12,8 @@
#define EXPLORER_XMRCHAIN_STAGENET_TX "https://stagenet.xmrchain.net/tx/"
#define EXPLORER_XMRCHAIN_TESTNET_TX "https://testnet.xmrchain.net/tx/"
#define NEROSHOP_DEFAULT_WALLET_PATH "/home/" + neroshop::device::get_user() + "/neroshop"//"/home/" + neroshop::device::get_user() + "/Monero/wallets"
#include <daemon/monero_daemon.h>
#include <daemon/monero_daemon_model.h>
#include <utils/gen_utils.h>
@ -19,33 +22,37 @@
#include <wallet/monero_wallet_full.h>
#include <wallet/monero_wallet_keys.h>
#include <wallet/monero_wallet_model.h>
#include <file.hpp>
#include <process.hpp> // to open daemon process //#include "script.hpp"
#include <message.hpp>
#include <progressbar.hpp>
#include <iostream>
#include <string>
#include <vector>
#include <utility> // std::pair
#include <cmath>
#include "process.hpp" // for monerod daemon process
#include "message.hpp"
namespace neroshop {
// this wallet class is only meant for creating and loading wallets, generating subaddresses, and listening to transactions. sending transactions? not so much - more focused on receiving
class Wallet : public monero_wallet_listener {
public:
Wallet();
Wallet(const std::string& file); // include .keys
~Wallet();
// wallet-related functions
void connect(); // connect to a hw
void create(std::string password = ""/*, const std::string& confirm_pw*/); // creates a new wallet
void create_from_mnemonic(const std::string& mnemonic, std::string password = ""/*, const std::string &confirm_pw*/); // create wallet from mnemonic phrase
void create_from_keys(const std::string& address, const std::string& view_key, const std::string& spend_key, std::string password = ""/*, const std::string &confirm_pw*/); // create wallet from address, view_key, and spend_key
std::string upload(bool open = true, std::string password = ""); // change to mainnet later
void open(const std::string& path, std::string password = "");
void restore(const std::string& mnemonic, std::string password = ""); // restore from mnemonic //void restore(const std::string& keyfile); // restore from keyfile
void restore(const std::string& address, const std::string& view_key, const std::string& spend_key, std::string password = ""); // restore from keys (address, view_key, spend_key)
void close(bool save=false);
void create_random(const std::string& password, const std::string& confirm_pwd, const std::string& path);
void create_from_mnemonic(const std::string& mnemonic, const std::string& password, const std::string& confirm_pwd, const std::string& path);
void create_from_keys(const std::string& address, const std::string& view_key, const std::string& spend_key, const std::string& password, const std::string &confirm_pwd, const std::string& path);
void restore_from_mnemonic(const std::string& mnemonic); // In-memory wallet
void restore_from_keys(const std::string& primary_address, const std::string& view_key, const std::string& spend_key); // In-memory wallet
void open(const std::string& path, const std::string& password); // Password-protected wallet file
void close(bool save = false);
std::string upload(bool open = true, std::string password = ""); // change to mainnet later
// todo: create a function that connects a hardware wallet
void transfer(const std::string& address, double amount); // "transfer" will be used for sending refunds
void sweep_all(const std::string& address); // sends entire balance, including dust to an address // "sweep_all <address>"
std::string address_new() const; // generates a new subaddress from main account // "address new" // monero addresses start with 4 or 8
@ -54,9 +61,7 @@ public:
std::vector<std::string> address_all(); // show all addresses
std::vector<std::string> address_used(); // show all used addresses
std::vector<std::string> address_unused(); // show all unused addresses
// override monero_wallet_listener functions (when inheriting from the class)
// now I can finally remove the darn singleton :D
// https://moneroecosystem.org/monero-cpp/classmonero_1_1monero__wallet__listener.html
void on_sync_progress(uint64_t height, uint64_t start_height, uint64_t end_height, double percent_done, const std::string& message);
////void on_new_block (uint64_t height);
void on_balances_changed(uint64_t new_balance, uint64_t new_unlocked_balance);
@ -84,7 +89,7 @@ public:
// subaddress
std::string get_last_subaddress() const; // returns the last subaddress to be created
// proof (proving the transaction was submitted) - https://web.getmonero.org/resources/user-guides/prove-payment.html
std::string get_tx_note(const std::string& txid) const; // "get_tx_note <txid>" - useful for retrieving address information
////std::string get_tx_note(const std::string& txid) const; // "get_tx_note <txid>" - useful for retrieving address information
// get_spend_proof <txid> [<message>]
// get_tx_proof <txid> <address> [<message>]
// get_reserve_proof (all|<amount>) [<message>]
@ -92,9 +97,13 @@ public:
// check_spend_proof <txid> <signature_file> [<message>]
// check_tx_proof <txid> <address> <signature_file> [<message>]
// NOTE: use address_new to automatically generate a unique subaddress for each customer to make it easier to track who and where the payments are coming from
std::pair<std::string, std::string> get_viewkey(const std::string& password) const; // secret, public // "viewkey"
std::pair<std::string, std::string> get_spendkey(const std::string& password) const; // secret, public // "spendkey"
std::string get_mnemonic(const std::string& password) const; // "seed"
std::string get_private_view_key() const; // secret view key
std::string get_public_view_key() const;
std::pair<std::string, std::string> get_view_keys() const; // secret, public // "viewkey"
std::string get_private_spend_key() const; // secret spend key
std::string get_public_spend_key() const;
std::pair<std::string, std::string> get_spend_keys() const; // secret, public // "spendkey"
std::string get_mnemonic() const; // "seed"
//-Image * get_qr_code() const; // returns address qrcode // "show_qr_code"
//-Image * get_qr_code(unsigned int address_index) const; // returns the qrcode of the address at "index"
std::string get_path() const; // "wallet_info"
@ -122,9 +131,10 @@ private:
// monero-related
std::unique_ptr<monero::monero_wallet_full> monero_wallet_obj; // monero wallet
monero::monero_network_type network_type; // default will be mainnet when this application is released
// process-related (dokun-ui)
// dokun-ui
std::unique_ptr<Process> process; // monerod process // every wallet will have its own process
std::unique_ptr<Progressbar> sync_bar;
//std::unique_ptr<Progressbar> sync_bar;
};
}
#endif // WALLET_HPP

@ -7,7 +7,7 @@ workspace("NeroshopWorkspace")
project("neroshop")
kind("ConsoleApp")--("WindowedApp")
language("C++")
files({ "src/buyer.cpp", --[["src/carrier.cpp",]] "src/cart.cpp", "src/catalog.cpp", "src/client.cpp", "src/converter.cpp", "src/database.cpp", "src/encryptor.cpp", "src/icon.cpp", "src/item.cpp", "src/main.cpp", "src/message.cpp", "src/order.cpp", "src/qr.cpp", "src/seller.cpp", "src/server.cpp", "src/user.cpp", "src/validator.cpp", "src/wallet.cpp", })
files({ "src/buyer.cpp", --[["src/carrier.cpp",]] "src/cart.cpp", "src/catalog.cpp", "src/client.cpp", "src/converter.cpp", "src/database.cpp", "src/encryptor.cpp", "src/icon.cpp", "src/item.cpp", "src/main.cpp", "src/message.cpp", "src/order.cpp", "src/process.cpp", "src/qr.cpp", "src/seller.cpp", "src/server.cpp", "src/user.cpp", "src/validator.cpp", "src/wallet.cpp", })
includedirs ({
"include/", "external/monero-cpp/src/", --[["external/libbcrypt/",]] "external/sqlite/", "external/QR-Code-generator/cpp/", "external/json/single_include/", --[["external/curl/include/", "external/curl/lib/",]] --[["/usr/include/postgresql/", "/usr/include/postgresql/server/",]] "external/raft/include/", --[["external/libuv/include/", "external/libuv/src/",]] "external/monero-cpp/external/monero-project/external/db_drivers/liblmdb/",
-- dokun-ui
@ -30,7 +30,7 @@ project("neroshop")
libdirs({ "src/", "build/bin/Debug/", "build/bin/Release/", "external/dokun-ui/src/", })
links({ "monero-cpp", --[["bcrypt",]] "sqlite3", "qrcodegen", "curl", --[["crypto", "ssl",]] --[["pq",]] "raft", "uv",
-- dokun-ui
"dokun-ui",
"dokun-ui", "glfw",
-- monero
"external/monero-cpp/external/monero-project/build/release/lib/wallet_merged",
"external/monero-cpp/external/monero-project/build/release/lib/wallet",

@ -93,6 +93,7 @@ git clone --recurse-submodules https://github.com/nlohmann/json.git
#git clone --recurse-submodules https://github.com/curl/curl.git
#git clone --recurse-submodules https://github.com/libuv/libuv.git
git clone --recurse-submodules https://github.com/willemt/raft.git
#git clone --recurse-submodules https://github.com/mariusbancila/stduuid.git
cd ../
```

@ -0,0 +1,77 @@
#include <iostream>
#include <string>
// neroshop
#include "../include/neroshop.hpp"
using namespace neroshop;
// dokun-ui
#include <dokun_ui.hpp>
using namespace dokun;
lua_State * neroshop::lua_state = luaL_newstate(); // lua_state should be initialized by default
int main() {
if(!neroshop::create_config()) {
neroshop::load_config();
}
std::vector<std::string> networks = {"mainnet", "stagenet", "testnet"};
std::string network_type = Script::get_string(lua_state, "neroshop.daemon.network_type");
if (std::find(networks.begin(), networks.end(), network_type) == networks.end()) {
neroshop::print("\033[1;91mnetwork_type \"" + network_type + "\" is not valid");
return 1;
}
std::vector<std::string> nodes_list = Script::get_table_string(neroshop::get_lua_state(), "neroshop.nodes."+network_type);
if(nodes_list.empty()) {
std::cout << "failed to get nodes in the config file\nCheck your config file in ~/.config/neroshop" << std::endl;
}
while (true) {
std::string shellinput;
std::cout << "neroshop> ";
std::getline(std::cin, shellinput);//std::cin >> shellinput;
if (shellinput == "help") {std::cout << "Available commands:\n\n help Display list of available commands\n\n exit Exit CLI\n\n";}
else if (shellinput == "monero_nodes") {
for (std::string n : nodes_list) {
std::cout << n << std::endl;
}
}
else if (shellinput == "version") {break;}
std::cout << "neroshop " << APP_VERSION << std::endl;
}
else if (shellinput == "exit") {break;}
}
//-------------------------------------
/*else if(shellinput == "register") { // create a new wallet
}
*/
/*else if(shellinput == "auth") { // auth or access = synonym for login
std::cout << "1. seed (mnemonic)\n2. keys\n3. open wallet file";
unsigned int auth_options;
std::cin >> auth_options;
if(auth_options == 1) {
}
if(auth_options == 2) {
}
}*/
/*else if(shellinput == "auth_with_seed") { // restore wallet from seed
}
else if(shellinput == "auth_with_keys") { // restore wallet from keys
}
else if(shellinput == "auth_with_hw") { // restore/create wallet from hw
}
*/
/*else if(shellinput == "") {
}*/
return 0;
}

@ -54,12 +54,15 @@ unsigned int neroshop::Cart::get_id() const {
////////////////////
////////////////////
bool neroshop::Cart::is_empty() const {
return true;
}
////////////////////
bool neroshop::Cart::is_full() const {
return false;
}
////////////////////
bool neroshop::Cart::in_cart(unsigned int item_id) const {
return false;
}
////////////////////
bool neroshop::Cart::in_cart(const neroshop::Item& item) const {

@ -1,23 +1,23 @@
#include "../include/database.hpp"
neroshop::DB::SQLite3::SQLite3() : handle(nullptr), opened(false) {}
neroshop::db::Sqlite3::Sqlite3() : handle(nullptr), opened(false) {}
////////////////////
neroshop::DB::SQLite3::SQLite3(const std::string& filename) : SQLite3()
neroshop::db::Sqlite3::Sqlite3(const std::string& filename) : Sqlite3()
{
if(!open(filename)) {
throw std::runtime_error(std::string("sqlite3_open: ") + std::string(sqlite3_errmsg(handle)));
}
}
////////////////////
neroshop::DB::SQLite3::~SQLite3() {
neroshop::db::Sqlite3::~Sqlite3() {
close();
}
////////////////////
std::unique_ptr<neroshop::DB::SQLite3> neroshop::DB::SQLite3::singleton (nullptr);//(std::make_unique<neroshop::DB::SQLite3>());
std::unique_ptr<neroshop::db::Sqlite3> neroshop::db::Sqlite3::singleton (nullptr);//(std::make_unique<neroshop::db::Sqlite3>());
////////////////////
// SQLite database should only need to be opened once per application session and closed once when the application is terminated
bool neroshop::DB::SQLite3::open(const std::string& filename)
bool neroshop::db::Sqlite3::open(const std::string& filename)
{
if(opened) {
neroshop::print("database is already opened", 2);
@ -41,7 +41,7 @@ bool neroshop::DB::SQLite3::open(const std::string& filename)
return true;
}
////////////////////
void neroshop::DB::SQLite3::close() {
void neroshop::db::Sqlite3::close() {
if(!handle) {
return;
}
@ -51,18 +51,18 @@ void neroshop::DB::SQLite3::close() {
neroshop::print("database is now closed");
}
////////////////////
void neroshop::DB::SQLite3::execute(const std::string& command)
void neroshop::db::Sqlite3::execute(const std::string& command)
{
if(!handle) throw std::runtime_error("database is not connected");
char * error_message = 0;
int result = sqlite3_exec(handle, command.c_str(), neroshop::DB::SQLite3::callback, 0, &error_message);
int result = sqlite3_exec(handle, command.c_str(), neroshop::db::Sqlite3::callback, 0, &error_message);
if (result != SQLITE_OK) {
neroshop::print("sqlite3_exec: " + std::string(error_message), 1);
sqlite3_free(error_message);
}
}
////////////////////
void neroshop::DB::SQLite3::execute_params(const std::string& command, const std::vector<std::string>& args) {
void neroshop::db::Sqlite3::execute_params(const std::string& command, const std::vector<std::string>& args) {
if(!handle) throw std::runtime_error("database is not connected");
// Prepare statement
sqlite3_stmt * statement = nullptr;
@ -100,22 +100,22 @@ void neroshop::DB::SQLite3::execute_params(const std::string& command, const std
////////////////////
////////////////////
////////////////////
std::string neroshop::DB::SQLite3::get_sqlite_version() {
std::string neroshop::db::Sqlite3::get_sqlite_version() {
return sqlite3_libversion();
}
////////////////////
sqlite3 * neroshop::DB::SQLite3::get_handle() const {
sqlite3 * neroshop::db::Sqlite3::get_handle() const {
return handle;
}
////////////////////
neroshop::DB::SQLite3 * neroshop::DB::SQLite3::get_singleton() {
neroshop::db::Sqlite3 * neroshop::db::Sqlite3::get_singleton() {
if(!singleton.get()) {
singleton = std::make_unique<neroshop::DB::SQLite3>();
singleton = std::make_unique<neroshop::db::Sqlite3>();
}
return singleton.get();
}
////////////////////
void * neroshop::DB::SQLite3::get_blob(const std::string& command) {
void * neroshop::db::Sqlite3::get_blob(const std::string& command) {
if(!handle) throw std::runtime_error("database is not connected");
sqlite3_stmt * statement = nullptr;
int result = sqlite3_prepare_v2(handle, command.c_str(), -1, &statement, nullptr);
@ -140,7 +140,7 @@ void * neroshop::DB::SQLite3::get_blob(const std::string& command) {
return blob;
}
////////////////////
void * neroshop::DB::SQLite3::get_blob_params(const std::string& command, const std::vector<std::string>& args) {
void * neroshop::db::Sqlite3::get_blob_params(const std::string& command, const std::vector<std::string>& args) {
if(!handle) throw std::runtime_error("database is not connected");
sqlite3_stmt * statement = nullptr;
int result = sqlite3_prepare_v2(handle, command.c_str(), -1, &statement, nullptr);
@ -169,7 +169,7 @@ void * neroshop::DB::SQLite3::get_blob_params(const std::string& command, const
return blob;
}
////////////////////
std::string neroshop::DB::SQLite3::get_text(const std::string& command) {//const {
std::string neroshop::db::Sqlite3::get_text(const std::string& command) {//const {
if(!handle) throw std::runtime_error("database is not connected");
sqlite3_stmt * stmt = nullptr;
int result = sqlite3_prepare_v2(handle, command.c_str(), -1, &stmt, nullptr);
@ -194,7 +194,7 @@ std::string neroshop::DB::SQLite3::get_text(const std::string& command) {//const
return text;
}
////////////////////
std::string neroshop::DB::SQLite3::get_text_params(const std::string& command, const std::vector<std::string>& args) {//const {
std::string neroshop::db::Sqlite3::get_text_params(const std::string& command, const std::vector<std::string>& args) {//const {
if(!handle) throw std::runtime_error("database is not connected");
// Prepare statement
sqlite3_stmt * statement = nullptr;
@ -227,7 +227,7 @@ std::string neroshop::DB::SQLite3::get_text_params(const std::string& command, c
return text;
}
////////////////////
int neroshop::DB::SQLite3::get_integer(const std::string& command) {
int neroshop::db::Sqlite3::get_integer(const std::string& command) {
if(!handle) throw std::runtime_error("database is not connected");
sqlite3_stmt * statement = nullptr;
int result = sqlite3_prepare_v2(handle, command.c_str(), -1, &statement, nullptr);
@ -252,7 +252,7 @@ int neroshop::DB::SQLite3::get_integer(const std::string& command) {
return number;
}
////////////////////
int neroshop::DB::SQLite3::get_integer_params(const std::string& command, const std::vector<std::string>& args) {
int neroshop::db::Sqlite3::get_integer_params(const std::string& command, const std::vector<std::string>& args) {
if(!handle) throw std::runtime_error("database is not connected");
// Prepare statement
sqlite3_stmt * statement = nullptr;
@ -285,7 +285,7 @@ int neroshop::DB::SQLite3::get_integer_params(const std::string& command, const
return number;
}
////////////////////
double neroshop::DB::SQLite3::get_real(const std::string& command) {
double neroshop::db::Sqlite3::get_real(const std::string& command) {
if(!handle) throw std::runtime_error("database is not connected");
sqlite3_stmt * stmt = nullptr;
int result = sqlite3_prepare_v2(handle, command.c_str(), -1, &stmt, nullptr);
@ -310,7 +310,7 @@ double neroshop::DB::SQLite3::get_real(const std::string& command) {
return number;
}
////////////////////
double neroshop::DB::SQLite3::get_real_params(const std::string& command, const std::vector<std::string>& args) {
double neroshop::db::Sqlite3::get_real_params(const std::string& command, const std::vector<std::string>& args) {
if(!handle) throw std::runtime_error("database is not connected");
// Prepare statement
sqlite3_stmt * statement = nullptr;
@ -346,23 +346,23 @@ double neroshop::DB::SQLite3::get_real_params(const std::string& command, const
////////////////////
////////////////////
////////////////////
bool neroshop::DB::SQLite3::is_open() const {
bool neroshop::db::Sqlite3::is_open() const {
return (opened == true);
}
////////////////////
bool neroshop::DB::SQLite3::table_exists(const std::string& table_name) {
bool neroshop::db::Sqlite3::table_exists(const std::string& table_name) {
std::string command = "SELECT count(*) FROM sqlite_master WHERE type = 'table' AND name = $1;";
return get_integer_params(command, { table_name });
}
////////////////////
/*bool neroshop::DB::SQLite3::rowid_exists(const std::string& table_name, int rowid) {
/*bool neroshop::db::Sqlite3::rowid_exists(const std::string& table_name, int rowid) {
int rowid = database->get_integer_params("SELECT id FROM $1 WHERE id = $2", { table_name, rowid });
return (rowid != 0);
}*/
////////////////////
////////////////////
////////////////////
int neroshop::DB::SQLite3::callback(void *not_used, int argc, char **argv, char **az_col_name)
int neroshop::db::Sqlite3::callback(void *not_used, int argc, char **argv, char **az_col_name)
{
int i;
for(i = 0; i < argc; i++) {

@ -61,7 +61,7 @@ bool neroshop::Encryptor::generate_key_pair_ex() {
}
////////////////////
EVP_PKEY * neroshop::Encryptor::generate_key_pair_return() {
// generate public/private key pairs
// Generate public/private key pairs
EVP_PKEY_CTX * ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, nullptr);
EVP_PKEY * pkey = nullptr;
if(!ctx) { neroshop::print("EVP_PKEY_CTX_new_id failed", 1); return nullptr; }
@ -80,29 +80,16 @@ EVP_PKEY * neroshop::Encryptor::generate_key_pair_return() {
neroshop::print(std::string("EVP_PKEY_keygen ") + std::string(ERR_error_string(ERR_get_error(), nullptr)), 1);
return nullptr;
}
// we need the pkey alive so that we can return it. Do not free it
// free the context instead
// We need the pkey alive so that we can return it. Do not free it
// Free the context instead
EVP_PKEY_CTX_free(ctx);
return pkey;
}
////////////////////
bool neroshop::Encryptor::save_public_key(const EVP_PKEY * pkey) {
BIO * bio_public = BIO_new_file("public.pem", "w+"); // or .pub
if(PEM_write_bio_PUBKEY(bio_public, const_cast<EVP_PKEY *>(pkey)) != 1) {
//if(PEM_write_bio_RSAPublicKey(bp_public, const_cast<RSA *>(rsa)) != 1) { // deprecated in OpenSSL 3.0
neroshop::print("PEM_write_bio_RSAPublicKey failed", 1);
BIO_free_all(bio_public);
return false;
}
// free the bio now that we are done writing to it
BIO_free_all(bio_public);
neroshop::print("public.pem created", 3);
return true;
}
////////////////////
bool neroshop::Encryptor::save_public_key(const EVP_PKEY * pkey, const std::string& filename) {
bool neroshop::Encryptor::save_public_key(const EVP_PKEY * pkey, std::string filename) {
BIO * bio_public = BIO_new_file(filename.c_str(), "w+"); // or .pub
if(PEM_write_bio_PUBKEY(bio_public, const_cast<EVP_PKEY *>(pkey)) != 1) {
//if(PEM_write_bio_RSAPublicKey(bp_public, const_cast<RSA *>(rsa)) != 1) { // deprecated in OpenSSL 3.0
neroshop::print("PEM_write_bio_RSAPublicKey failed", 1);
BIO_free_all(bio_public);
return false;
@ -110,26 +97,13 @@ bool neroshop::Encryptor::save_public_key(const EVP_PKEY * pkey, const std::stri
// free the bio now that we are done writing to it
BIO_free_all(bio_public);
neroshop::print(filename + " created", 3);
return true;
}
////////////////////
bool neroshop::Encryptor::save_private_key(const EVP_PKEY * pkey) {
BIO * bio_private = BIO_new_file("private.pem", "w+"); // or .key
if(PEM_write_bio_PKCS8PrivateKey(bio_private, const_cast<EVP_PKEY *>(pkey), nullptr, nullptr, 0, nullptr, nullptr) != 1) { // same as PEM_write_bio_PrivateKey - both use PKCS#8 format which supports all algorithms including RSA // to-do: add encryption e.g: EVP_aes_256_cbc() (in arg 3) using a passphrase/password (in arg 4) and passphrase_len (in arg 5)
//if(PEM_write_bio_RSAPrivateKey(bp_private, const_cast<RSA *>(rsa), nullptr, nullptr, 0, nullptr, nullptr) != 1) { // deprecated in OpenSSL 3.0
neroshop::print("PEM_write_bio_PKCS8PrivateKey failed", 1);
BIO_free_all(bio_private);
return false;
}
// free the bio now that we are done writing to it
BIO_free_all(bio_private);
neroshop::print("private.pem created", 3);
return true;
}
////////////////////
bool neroshop::Encryptor::save_private_key(const EVP_PKEY * pkey, const std::string& filename) {
bool neroshop::Encryptor::save_private_key(const EVP_PKEY * pkey, std::string filename) {
BIO * bio_private = BIO_new_file(filename.c_str(), "w+"); // or .key
if(PEM_write_bio_PKCS8PrivateKey(bio_private, const_cast<EVP_PKEY *>(pkey), nullptr, nullptr, 0, nullptr, nullptr) != 1) { // same as PEM_write_bio_PrivateKey - both use PKCS#8 format which supports all algorithms including RSA // to-do: add encryption e.g: EVP_aes_256_cbc() (in arg 3) using a passphrase/password (in arg 4) and passphrase_len (in arg 5)
//if(PEM_write_bio_RSAPrivateKey(bp_private, const_cast<RSA *>(rsa), nullptr, nullptr, 0, nullptr, nullptr) != 1) { // deprecated in OpenSSL 3.0
neroshop::print("PEM_write_bio_PKCS8PrivateKey failed", 1);
BIO_free_all(bio_private);
return false;
@ -140,15 +114,9 @@ bool neroshop::Encryptor::save_private_key(const EVP_PKEY * pkey, const std::str
return true;
}
////////////////////
bool neroshop::Encryptor::save_key_pair(const EVP_PKEY * pkey) {
if(!save_public_key(pkey)) return false;
if(!save_private_key(pkey)) return false;
return true;
}
////////////////////
bool neroshop::Encryptor::save_key_pair(const EVP_PKEY * pkey, const std::string& filename) {
if(!save_public_key(pkey, filename)) return false;
if(!save_private_key(pkey, filename)) return false;
bool neroshop::Encryptor::save_key_pair(const EVP_PKEY * pkey, std::string public_key_file, std::string private_key_file) {
if(!save_public_key(pkey, public_key_file)) return false;
if(!save_private_key(pkey, private_key_file)) return false;
return true;
}
////////////////////

File diff suppressed because it is too large Load Diff

@ -4,42 +4,603 @@
#include "../include/neroshop.hpp"
using namespace neroshop;
// dokun-ui
#include <dokun_ui.hpp>
using namespace dokun;
//#include <dokun_ui.hpp>
//using namespace dokun;
/*#define CATCH_CONFIG_MAIN
#include <catch.hpp>*/
//using namespace uuids;
lua_State * neroshop::lua_state = luaL_newstate(); // lua_state should be initialized by default
int main() {
if(!neroshop::create_config()) {
neroshop::load_config();
}
std::vector<std::string> networks = {"mainnet", "stagenet", "testnet"};
////////////////////
static void some_func() {
std::string network_type = Script::get_string(lua_state, "neroshop.daemon.network_type");
if (std::find(networks.begin(), networks.end(), network_type) == networks.end()) {
neroshop::print("\033[1;91mnetwork_type \"" + network_type + "\" is not valid");
return 1;
}
////////////////////
////////////////////
////////////////////
////////////////////
static void start_and_initialize_database() {
std::cout << "sqlite3 v" << db::Sqlite3::get_sqlite_version() << std::endl;
db::Sqlite3 * database = db::Sqlite3::get_singleton();//std::unique_ptr<db::Sqlite3> database = std::make_unique<db::Sqlite3>();
if(!database->open("data.sqlite3")) {//(":memory:")) { // In-memory databases are temporary and written in RAM. They do not support WAL mode either
neroshop::print(SQLITE3_TAG "\033[91mSQLite::open failed");
}
std::vector<std::string> nodes_list = Script::get_table_string(neroshop::get_lua_state(), "neroshop.nodes."+network_type);
if(nodes_list.empty()) {
std::cout << "failed to get nodes in the config file\nCheck your config file in ~/.config/neroshop" << std::endl;
//-------------------------
// Create a table and add columns
/*if(!database->table_exists("users")) {
std::cout << "CREATE TABLE users\n";
database->execute("CREATE TABLE IF NOT EXISTS users(id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT);");
database->execute("ALTER TABLE users ADD name text;");
//database->execute("ALTER TABLE users ADD pw_hash text;");
database->execute("ALTER TABLE users ADD age integer;");
}*/
//database->execute();
// Insert a new row
////database->execute_params("INSERT INTO users (name, age) VALUES ($1, $2);", { "sid", "25" });
////std::cout << database->get_text_params("SELECT name FROM users WHERE id = $1", { "1" }) << std::endl;
// Modify new row
//database->execute_params("SELECT * FROM users WHERE id = $1 AND name = $2", { "1", "dude" });
//-------------------------
// todo: store this code in a initialize_database function
database->execute("BEGIN;");
//-------------------------
// table: account_type
/*if(!database->table_exists("account_type")) {
database->execute("CREATE TABLE account_type(id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT);");
database->execute("ALTER TABLE account_type ADD COLUMN name TEXT");
database->execute("INSERT INTO account_type(name) VALUES('Buyer');");
database->execute("INSERT INTO account_type(name) VALUES('Seller');");
}*/
//-------------------------
// users
// if 2 users share the same id or name then the raft consensus protocol must decide whether t
if(!database->table_exists("users")) { // todo: rename "users" to "peers" or create a separate peers table
database->execute("CREATE TABLE users(id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT);");
////database->execute("ALTER TABLE users ADD COLUMN name TEXT;"); // mostly suitable for centralized or federated apps
database->execute("ALTER TABLE users ADD COLUMN key TEXT;"); // verify_key - public_key used for verification of signatures
////database->execute("ALTER TABLE users ADD COLUMN verify_key TEXT;"); // verify_key - public_key used for verification of signatures
////database->execute("ALTER TABLE users ADD COLUMN encrypt_key TEXT;"); // encrypt_key - public_key used for encryption of messages
////database->execute("CREATE UNIQUE INDEX index_user_names ON users (name);");
database->execute("CREATE UNIQUE INDEX index_user_auth_keys ON users (key);");//database->execute("CREATE UNIQUE INDEX index_users ON users (name, verify_key, encrypt_key);");// enforce that the user names are unique, in case there is an attempt to insert a new "name" of the same value
////database->execute("CREATE UNIQUE INDEX index_verify_keys ON users (verify_key);");//database->execute("CREATE UNIQUE INDEX index_users ON users (name, verify_key, encrypt_key);");// enforce that the user names are unique, in case there is an attempt to insert a new "name" of the same value
////database->execute("CREATE UNIQUE INDEX index_encrypt_keys ON users (encrypt_key);");//database->execute("CREATE UNIQUE INDEX index_users ON users (name, verify_key, encrypt_key);");// enforce that the user names are unique, in case there is an attempt to insert a new "name" of the same value
// sellers require a username and buyers do not
// passwords will no longer be stored as salted bcrpyt hashes, only public keys will be stored
}
while (true) {
std::string shellinput;
std::cout << "neroshop> ";
std::cin >> shellinput;
if (shellinput == "help") {std::cout << "Available commands:\n\n help Display list of available commands\n\n exit Exit CLI\n\n";}
else if (shellinput == "monero_nodes") {
for (std::string n : nodes_list) {
std::cout << n << std::endl;
}
//-------------------------
// products (items)
if(!database->table_exists("products")) {
database->execute("CREATE TABLE products(id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT);");
database->execute("ALTER TABLE products ADD COLUMN name TEXT;");
database->execute("ALTER TABLE products ADD COLUMN description TEXT;"); // desc or description
database->execute("ALTER TABLE products ADD COLUMN price REAL");//INTEGER;");//numeric(20, 12);"); // unit_price or price_per_unit // 64-bit integer (uint64_t) that will be multipled by a piconero to get the actual monero price
database->execute("ALTER TABLE products ADD COLUMN weight REAL;"); // kg
//database->execute("ALTER TABLE products ADD COLUMN size ?datatype;"); // l x w x h
database->execute("ALTER TABLE products ADD COLUMN code TEXT;"); // product_code can be either upc (universal product code) or a custom sku
//database->execute("ALTER TABLE products ADD COLUMN category_id INTEGER REFERENCES categories(id);");
//database->execute("ALTER TABLE products ADD COLUMN subcategory_id INTEGER REFERENCES categories(id);");
//database->execute("ALTER TABLE products ADD COLUMN ?col ?datatype;");
database->execute("CREATE UNIQUE INDEX index_product_codes ON products (code);"); // product codes must be unique
// the seller determines the final product price, the product condition and whether the product will have a discount or not
}
//-------------------------
// inventory
if(!database->table_exists("inventory")) {
database->execute("CREATE TABLE inventory(id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT);");
database->execute("ALTER TABLE inventory ADD COLUMN item_id INTEGER REFERENCES products(id);");
database->execute("ALTER TABLE inventory ADD COLUMN seller_id INTEGER REFERENCES users(id);"); // alternative names: "store_id"
database->execute("ALTER TABLE inventory ADD COLUMN stock_qty INTEGER;"); // alternative names: "stock" or "stock_available"
database->execute("ALTER TABLE inventory ADD COLUMN sales_price REAL;");//numeric(20,12);"); // alternative names: "seller_price" or "list_price" // this is the final price of a product
database->execute("ALTER TABLE inventory ADD COLUMN currency TEXT;"); // the fiat currency the seller is selling the item in
//database->execute("ALTER TABLE inventory ADD COLUMN discount numeric(20,12);"); // alternative names: "seller_discount", or "discount_price"
//database->execute("ALTER TABLE inventory ADD COLUMN ?col ?datatype;"); // discount_times_can_use - number of times the discount can be used
//database->execute("ALTER TABLE inventory ADD COLUMN ?col ?datatype;"); // discounted_items_qty - number of items that the discount will apply to
//database->execute("ALTER TABLE inventory ADD COLUMN ?col ?datatype;"); // discount_expiry - date and time that the discount expires (will be in UTC format)
//database->execute("ALTER TABLE inventory ADD COLUMN ?col ?datatype;");
database->execute("ALTER TABLE inventory ADD COLUMN condition TEXT;"); // item condition
//database->execute("ALTER TABLE inventory ADD COLUMN last_updated ?datatype;");
//database->execute("");
}
//-------------------------
// cart
if(!database->table_exists("cart")) {
// local cart - for a single cart containing a list of item_ids
//database->execute("CREATE TABLE cart(id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, item_id INTEGER REFERENCES products(id));");
// public cart - copied to all peers' databases
database->execute("CREATE TABLE cart(id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT);");
database->execute("ALTER TABLE cart ADD COLUMN user_id INTEGER REFERENCES users(id);");//database->execute("CREATE TABLE cart(id INTEGER NOT NULL PRIMARY KEY, user_id INTEGER REFERENCES users(id));");
// cart_items (public cart)
database->execute("CREATE TABLE cart_item(id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT);");
database->execute("ALTER TABLE cart_item ADD COLUMN cart_id INTEGER REFERENCES cart(id);");
database->execute("ALTER TABLE cart_item ADD COLUMN item_id INTEGER REFERENCES products(id);");
database->execute("ALTER TABLE cart_item ADD COLUMN item_qty INTEGER;");
//database->execute("ALTER TABLE cart_item ADD COLUMN item_price numeric;"); // sales_price will be used for the final pricing rather than the unit_price
//database->execute("ALTER TABLE cart_item ADD COLUMN item_weight REAL;");//database->execute("CREATE TABLE cart_item(id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, cart_id INTEGER REFERENCES cart(id), item_id INTEGER REFERENCES products(id), item_qty INTEGER, item_price NUMERIC, item_weight REAL);");
}
//-------------------------
// orders (purchase_orders)
if(!database->table_exists("orders")) {
database->execute("CREATE TABLE orders(id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT);");//database->execute("ALTER TABLE orders ADD COLUMN ?col ?datatype;");
database->execute("ALTER TABLE orders ADD COLUMN timestamp TEXT DEFAULT CURRENT_TIMESTAMP;"); // creation_date // to get UTC time: set to datetime('now');
database->execute("ALTER TABLE orders ADD COLUMN number TEXT;"); // uuid
database->execute("ALTER TABLE orders ADD COLUMN status TEXT;");
database->execute("ALTER TABLE orders ADD COLUMN user_id INTEGER REFERENCES users(id);"); // the user that placed the order
//database->execute("ALTER TABLE orders ADD COLUMN weight REAL;"); // weight of all order items combined - not essential
database->execute("ALTER TABLE orders ADD COLUMN subtotal numeric(20, 12);");
database->execute("ALTER TABLE orders ADD COLUMN discount numeric(20, 12);");
//database->execute("ALTER TABLE orders ADD COLUMN shipping_method TEXT;"); // comment this out
database->execute("ALTER TABLE orders ADD COLUMN shipping_cost numeric(20, 12);");
database->execute("ALTER TABLE orders ADD COLUMN total numeric(20, 12);");
//database->execute("ALTER TABLE orders ADD COLUMN notes TEXT;"); // will contain sensative such as shipping address and tracking numbers that will be encrypted and can only be decrypted by the seller - this may not be necessary since buyer can contact seller privately
// order_item
database->execute("CREATE TABLE order_item(id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT);");
database->execute("ALTER TABLE order_item ADD COLUMN order_id INTEGER REFERENCES orders(id);");
database->execute("ALTER TABLE order_item ADD COLUMN item_id INTEGER REFERENCES products(id);");
database->execute("ALTER TABLE order_item ADD COLUMN seller_id INTEGER REFERENCES users(id);");
database->execute("ALTER TABLE order_item ADD COLUMN item_qty INTEGER;");
//database->execute("ALTER TABLE order_item ADD COLUMN item_price ?datatype;");
//database->execute("ALTER TABLE order_item ADD COLUMN ?col ?datatype;");
}
else if (shellinput == "exit") {break;}
//-------------------------
// ratings - product_ratings, seller_ratings
// maybe merge both item ratings and seller ratings together or nah?
if(!database->table_exists("seller_ratings")) {//if(!database->table_exists("user_ratings")) {
// seller
database->execute("CREATE TABLE seller_ratings(id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT);");
database->execute("ALTER TABLE seller_ratings ADD COLUMN seller_id INTEGER REFERENCES users(id);"); // seller_pkey or seller_pubkey//database->execute("ALTER TABLE user_ratings ADD COLUMN user_id INTEGER REFERENCES users(id);"); // seller_pkey or seller_pubkey
database->execute("ALTER TABLE seller_ratings ADD COLUMN score INTEGER;");
database->execute("ALTER TABLE seller_ratings ADD COLUMN user_id INTEGER REFERENCES users(id);"); // or rater_id // user_pkey or user_pubkey//database->execute("ALTER TABLE user_ratings ADD COLUMN rater_id INTEGER REFERENCES users(id);"); // user_pkey or user_pubkey
database->execute("ALTER TABLE seller_ratings ADD COLUMN comments TEXT;"); // plain text
}
if(!database->table_exists("product_ratings")) {
// product - put in a separate table reviews (but revies only mean comments)
database->execute("CREATE TABLE product_ratings(id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT);");
database->execute("ALTER TABLE product_ratings ADD COLUMN item_id INTEGER REFERENCES products(id);");
database->execute("ALTER TABLE product_ratings ADD COLUMN stars INTEGER;");
database->execute("ALTER TABLE product_ratings ADD COLUMN user_id INTEGER REFERENCES users(id);");
database->execute("ALTER TABLE product_ratings ADD COLUMN comments TEXT;"); // plain text
}
//-------------------------
// images
if(!database->table_exists("images")) {
//database->execute("CREATE TABLE images(id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT);");
//database->execute("ALTER TABLE images ADD COLUMN item_id INTEGER REFERENCES products(id);");
//database->execute("ALTER TABLE images ADD COLUMN name TEXT[];");
//database->execute("ALTER TABLE images ADD COLUMN data BLOB[];");
//database->execute("ALTER TABLE images ADD COLUMN ?col ?datatype;");
//database->execute("ALTER TABLE images ADD COLUMN ?col ?datatype;");
}
//-------------------------
// avatars - each user will have a single avatar
if(!database->table_exists("avatars")) {
//database->execute("CREATE TABLE avatars(id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT);");
//database->execute("ALTER TABLE avatars ADD COLUMN user_id INTEGER REFERENCES users(id);");
//database->execute("ALTER TABLE avatars ADD COLUMN data BLOB;");
}
//-------------------------
// product_categories, product_subcategories
if(!database->table_exists("categories")) {
database->execute("CREATE TABLE categories(id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT);");
database->execute("ALTER TABLE categories ADD COLUMN name TEXT;");
database->execute("ALTER TABLE categories ADD COLUMN alt_names TEXT;");
//database->execute("ALTER TABLE categories ADD COLUMN desc ?datatype;");
}
if(!database->table_exists("subcategories")) {
database->execute("CREATE TABLE subcategories(id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT);");
//database->execute("ALTER TABLE subcategories ADD COLUMN ?col ?datatype;");
database->execute("ALTER TABLE subcategories ADD COLUMN name TEXT;");
database->execute("ALTER TABLE subcategories ADD COLUMN category_id INTEGER REFERENCES categories(id);");
database->execute("ALTER TABLE subcategories ADD COLUMN description TEXT;");
}
// insert all categories and subcategories
// category here
int category_id = database->get_integer("INSERT INTO categories (name, alt_names) VALUES ('Food', 'Grocery & Gourmet Foods; Produce') RETURNING id;"); // Almost done :) // Food & Beverage in one category? nah
// subcategories here
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Canned Foods', $1)", { std::to_string(category_id) }); // sub subcategory
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Condiments', $1)", { std::to_string(category_id) }); // sweet and savory sauces // includes ketchup, mustard, mayonnaise, sour cream, barbecue sauce, compound butter, etc. // A condiment is a preparation that is added to food, typically after cooking, to impart a specific flavor, to enhance the flavor, or to complement the dish
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Confections', $1)", { std::to_string(category_id) }); // confections or confectionery are sweets like cake, deserts, candies, marshmellows, and other food items that are sweet // sugar confections (aka sweets) = candy, baker/flour confection = cake, chocolate confection = hershey
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Dairy', $1)", { std::to_string(category_id) }); // includes food items like cheese, milk, and yogurt
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Fish & Seafood', $1)", { std::to_string(category_id) }); // includes fish, crab, and all other seafoods
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Food Additives - Sweeteners', $1)", { std::to_string(category_id) }); // includes honey, maple syrup, raw sugar, etc.
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Frozen Foods', $1)", { std::to_string(category_id) }); // sub subcategory
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Fruits', $1)", { std::to_string(category_id) }); // includes berries, melons, etc.
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Grains, Breads & Cereals', $1)", { std::to_string(category_id) }); // includes cereal, rice, oatmeal, pasta and traditional bakery like biscuits and bread (whole grains)
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Herbs & Spices', $1)", { std::to_string(category_id) }); //include ginger, turmeric, cinnamon, cocoa powder, parsley, and basil, etc. // herbs are leafy things, like basil, tarragon, thyme, and cilantro; and spices are seeds, either whole or ground, like coriander, cumin, and anise. Leaves vs. seeds is indeed a simple version of the separation. But simple isn't always accurate.
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Meat & Poutry', $1)", { std::to_string(category_id) }); //Protein -// All poutry is meat, well since a bird and chicken are meat // fish should have its own subcategory // pescatarians - vegetarians who eat fish and no other flesh or meat
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Nuts, Seeds & Legumes', $1)", { std::to_string(category_id) }); // a nut is a hard-shell containing a seed and a seed is without a shell // legumes are beans
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Fats, Oils, Sugar & Salt', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Organic Foods', $1)", { std::to_string(category_id) }); // sub subcategory
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Processed Foods', $1)", { std::to_string(category_id) }); // sub subcategory
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Proteins - Eggs', $1)", { std::to_string(category_id) }); // eggs are neither dairy (since they don't come from milk, but laid by chickens) nor meat (eggs contain no animal flesh since they are unfertilized)
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Snack Foods', $1)", { std::to_string(category_id) }); // pretzels, slated peanuts, potato chips, popcorn, trail mix, candy, chocolate, baked sweets, etc.
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Vegetables', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Vitamins & Dietary Supplements', $1)", { std::to_string(category_id) }); //Nutritional and herbal supplements // includes bee pollen, matcha powder, protein powder, and powdered vitamin or mineral supplements, etc. // Dietary supplements can include a variety of components such as vitamins, minerals, herbs, amino acids, enzymes and other ingredients taken in various forms such as a pill, gel, capsule, gummy, powder, drink or food
////database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('?', $1)", { std::to_string(category_id) });
//---------------------------
// category here
category_id = database->get_integer("INSERT INTO categories (name, alt_names) VALUES ('Beverages', '') RETURNING id;"); // DONE! :D
// subcategories here
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Alchoholic Beverages - Hard Liquors & Spirits', $1)", { std::to_string(category_id) }); // spirits is another name for liquor (almost), both are distilled beverages and are usually put into these two categories: liquors and spirits // distilled rather than fermented alcoholic beverage
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Alchoholic Beverages - Beer', $1)", { std::to_string(category_id) }); // beer is made from fermented grain
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Alchoholic Beverages - Wine', $1)", { std::to_string(category_id) }); // most wine is produced by fermenting grape juice. However, you cant just use any type of grape. You need wine grapes
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Coffee', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Juices', $1)", { std::to_string(category_id) }); // lemonade included :} // lemonade could also be a carbonated drink :O // is smoothie a juice? :O
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Milk or milk-based', $1)", { std::to_string(category_id) }); // milkshake, most hot chocolate and some protein shake included :}
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Mixed drinks', $1)", { std::to_string(category_id) }); // cocktail is a mixed drink with a mix of alcohol, fruit juice, soda, etc. :O // what about smoothies? :O
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Soft drinks', $1)", { std::to_string(category_id) }); // soda
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Sports & Energy drinks', $1)", { std::to_string(category_id) }); // sports drinks like gatorade and energy drinks like red bull
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Tea', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Water - Carbonated', $1)", { std::to_string(category_id) }); // same thing as sparkling water
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Water - Non-carbonated', $1)", { std::to_string(category_id) }); // regular drinking water
//---------------------------
// category here
category_id = database->get_integer("INSERT INTO categories (name, alt_names) VALUES ('Electronics', '') RETURNING id;"); // aka Consumer Electronics or Hardware
// subcategories here
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Appliances', $1)", { std::to_string(category_id) }); // Home Appliances
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Appliances - Dishwashers', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Appliances - Garbage Disposals & Compactors', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Appliances - Heating, Cooling & Air Quality Appliances', $1)", { std::to_string(category_id) }); // air conditioners, heaters
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Appliances - Home Appliance Warranties', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Appliances - Kitchen Small Appliances', $1)", { std::to_string(category_id) }); // blenders, toasters, etc.
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Appliances - Laundry Appliances', $1)", { std::to_string(category_id) }); // washing machines, dryers, etc.
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Appliances - Microwave Ovens', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Appliances - Parts & Accessories', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Appliances - Ranges, Ovens & Cooktops', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Appliances - Refrigerators, Freezers & Ice Makers', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Appliances - Outdoor Appliances', $1)", { std::to_string(category_id) }); // grills, smokers
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Appliances - Vacuums & Floor Care Appliances', $1)", { std::to_string(category_id) });
//database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Automotive Electronics - ', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Automotive Electronics', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Automotive Electronics - GPS Navigators', $1)", { std::to_string(category_id) });
//database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Automotive Electronics - ', $1)", { std::to_string(category_id) });
//database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Automotive Electronics - Radio and Vehicle audio', $1)", { std::to_string(category_id) });
//database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Automotive Electronics - ', $1)", { std::to_string(category_id) });
//////database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('?', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Accessories', $1)", { std::to_string(category_id) }); // accessories for electronics
//database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('?', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('AC Adapters, Chargers, Power strips, & Converters', $1)", { std::to_string(category_id) }); // includes chargers, power outlet (wall) chargers, universal power adapters / Travel Adapters & Converters, power strips, voltage converters, power banks, etc.
//database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('?', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Cables, Cords, Plugs, and Wires', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Cables and Wires - Monitor Cables', $1)", { std::to_string(category_id) }); // usb-c, hdmi, vga, dvi, displayport, rca or component/composite video, thunderbolt 1/2, etc.
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Cables -', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Calculators', $1)", { std::to_string(category_id) }); // including scientific ones
//database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('?', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Camera & Photo - Camcorders and Digital Cameras', $1)", { std::to_string(category_id) }); // includes digital cameras(DSLR, Mirrorless, Compact Cameras / Point & Shoot Cameras, Bridge Cameras, Instant Cameras, Film Cameras, Action Cameras, 360 Degree Cameras, Underwater Cameras / Waterproof Cameras, Medium Format Cameras, SmartPhone Cameras, Rangefinder Cameras, Security Camera, Smartphone Camera, Drone Camera, etc.)
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Camera & Photo - Display Stands', $1)", { std::to_string(category_id) }); // includes digital cameras(DSLR, Mirrorless, Compact Cameras / Point & Shoot Cameras, Bridge Cameras, Instant Cameras, Film Cameras, Action Cameras, 360 Degree Cameras, Underwater Cameras / Waterproof Cameras, Medium Format Cameras, SmartPhone Cameras, Rangefinder Cameras, Security Camera, Smartphone Camera, Drone Camera, etc.) database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Camera & Photo - Film Cameras', $1)", { std::to_string(category_id) }); // traditional cameras with film - still digital
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Camera & Photo - Security cameras', $1)", { std::to_string(category_id) }); // includes doorbell cameras, security cameras such as bullet, dome, hidden/covert, infrared, box, outdoor, PTZ, and wireless
//database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('?', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Cell Phones - Mobile Phones & Smartphones', $1)", { std::to_string(category_id) }); // aka Mobile phones//database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Phones - Telephones', $1)", { std::to_string(category_id) });
//database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('?', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Clocks - Digital clocks & Alarm clocks', $1)", { std::to_string(category_id) }); // includes alarm clocks
//database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('?', $1)", { std::to_string(category_id) });
//database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('?', $1)", { std::to_string(category_id) });
//database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('?', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Computers - Desktops', $1)", { std::to_string(category_id) }); // aka PC
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Computers - Laptops', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Computers - Laptop Tablet Hybrids', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Computer Parts & Hardware', $1)", { std::to_string(category_id) }); // or Computer Hardware
//database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('?', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Electronic Repair Tools', $1)", { std::to_string(category_id) }); // drills, etc.
//database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('?', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Electric Shavers, Razors & Curling Irons', $1)", { std::to_string(category_id) });
//database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('?', $1)", { std::to_string(category_id) });
//database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('?', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Entertainment - 3D Glasses', $1)", { std::to_string(category_id) }); // Entertainment or TV & Theater
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Entertainment - CD, DVD and Blu-ray players', $1)", { std::to_string(category_id) }); // Blu-ray, is a digital optical disc storage format. It is designed to supersede the DVD format
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Entertainment - ', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Entertainment - ', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Entertainment - Portable audio players & Boomboxes', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Entertainment - Radios', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Entertainment - ', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Entertainment - ', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Entertainment - Remote Controllers', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Entertainment - Stereo systems', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Entertainment - TVs', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Entertainment - TV Receivers', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Entertainment - ', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Entertainment - Video Cassette Recorders (VCR)', $1)", { std::to_string(category_id) });
//database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('?', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Electronic Musical Instruments', $1)", { std::to_string(category_id) }); // includes Audio Interfaces, Electronic Drums, Digital Synthesizers and Midi Controllers, Microphones, Studio Monitors, etc.
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Hardware - ', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Headphones, Earphones & Earbuds', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Industrial & Scientific - Electronic Measurement Devices', $1)", { std::to_string(category_id) }); // scales, calipers, etc. // Industrial & Scientific will have its own main category
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('', $1)", { std::to_string(category_id) });
////database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Lighting - Lamps, Lightbulbs', $1)", { std::to_string(category_id) }); // reading lamps, etc. // put this in Home Tools & Improvements category
//database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Lawn Mowers', $1)", { std::to_string(category_id) }); // reading lamps, etc.
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Peripherals', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Peripherals - Headsets', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Peripherals - Microphone', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Peripherals - Mouse', $1)", { std::to_string(category_id) }); // dont forget touchpad and pen input, etc.
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Peripherals - Keyboards', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Peripherals - Monitors', $1)", { std::to_string(category_id) }); // screen - led, lcd, ctr, etc.
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Peripherals - Power Adapters', $1)", { std::to_string(category_id) }); // laptop power adaptors
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Peripherals - Projectors', $1)", { std::to_string(category_id) }); // screen
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Peripherals - Speakers', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Peripherals - USB Hubs', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Peripherals - Webcams', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Peripherals - ', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('', $1)", { std::to_string(category_id) });
//database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('?', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Hardware - Ports, Jacks, Slots, Sockets & Connectors', $1)", { std::to_string(category_id) }); // includes audio jacks, usb ports, microSD card reader, etc. // all plugs and ports are connectors
//database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('?', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Portable Media Devices', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Portable Media Devices - ', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Portable Media Devices - CB & Two-way Radio', $1)", { std::to_string(category_id) }); // walkie-talkies
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Portable Media Devices - ', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Portable Media Devices - Media Players', $1)", { std::to_string(category_id) }); // portable mp3 players, etc.
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Portable Media Devices - ', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Printers - 3D Printers', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Printers - Inkjet Printers', $1)", { std::to_string(category_id) }); // single function printers only print while multi-function printers can print, scan, copy, and fax
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Printers - Laser Printers', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Printers, Scanners, Copiers, & Fax machines', $1)", { std::to_string(category_id) }); // single function printers only print while multi-function printers can print, scan, copy, and fax
//database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('?', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Ink and toner cartridges', $1)", { std::to_string(category_id) });
//database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('?', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Safe box', $1)", { std::to_string(category_id) });
//database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('?', $1)", { std::to_string(category_id) });
//database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('?', $1)", { std::to_string(category_id) });
//database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('?', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Storage Media', $1)", { std::to_string(category_id) }); // includes hard disk drives (hdd), solid state drives (ssd), m.2 ssd, network attached storage (nas), etc.
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Storage Media - Cassette Tapes', $1)", { std::to_string(category_id) }); // small ones for audio, big ones for video
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Storage Media - CDs/DVDs/Blu-rays', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Storage Media - Floppy Disks', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Storage Media - Game Discs & ROM Catridges', $1)", { std::to_string(category_id) }); // aka game cartridge, cart, or card
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Storage Media - Hard disk drives (HDD), Solid state drives (SSD)', $1)", { std::to_string(category_id) }); // includes hdd, sdd, etc.
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Storage Media - Memory Cards', $1)", { std::to_string(category_id) }); // includes sd cards, card readers
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Storage Media - USB Flash Drives', $1)", { std::to_string(category_id) }); // flash memory
//database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('?', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Tablets', $1)", { std::to_string(category_id) }); // includes ipad, android tablets, etc.
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Tablets - Graphics and Drawing Tablets', $1)", { std::to_string(category_id) }); // includes pen tablets (without a screen) and graphics tablets like wacom, etc. // https://www.autopano.net/types-of-drawing-tablets/
//database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('?', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Toys & Games', $1)", { std::to_string(category_id) }); // toys and games should have a category of its own
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Toys & Games - Electronic Toys', $1)", { std::to_string(category_id) });// includes electric car toys, remote control cars, drones, robots, etc. // toys and games should have a category of its own
//database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('?', $1)", { std::to_string(category_id) });
//database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('?', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Video Game Consoles, Games & Accessories', $1)", { std::to_string(category_id) }); // includes video game controllers, remote controllers, headsets, virtual reality headsets (PSVR), covers, etc.
//database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('?', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Wearable Technology', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Wearable Technology - Body Mounted Cameras', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Wearable Technology - Clips, Arm & Wristbands', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Wearable Technology - Glasses', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Wearable Technology - Rings', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Wearable Technology - Smartwatches', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Wearable Technology - Virtual Reality Gear & Headsets', $1)", { std::to_string(category_id) });
//database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('?', $1)", { std::to_string(category_id) });
//database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('?', $1)", { std::to_string(category_id) });
//---------------------------
// category here
category_id = database->get_integer("INSERT INTO categories (name, alt_names) VALUES ('Digital Goods', '') RETURNING id;"); // DONE :D! // SELECT * FROM subcategories WHERE category_id = $1;--ORDER BY name;
// subcategories here
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Codes - Cheat codes and hacks', $1)", { std::to_string(category_id) }); // replace "Codes" with "Information" anaa? :O // includes hacked information and leaks
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Codes - Discount and coupons', $1)", { std::to_string(category_id) }); // discounts, coupons/vouchers, promo codes etc.
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Codes - Gift cards', $1)", { std::to_string(category_id) }); // gift certificates included
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Codes - Membership and subscription cards', $1)", { std::to_string(category_id) }); // PSN Membership card, PS+ subscription card, Xbox Live cards, etc.
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Codes - Prepaid cards', $1)", { std::to_string(category_id) }); // A prepaid card is not linked to a bank checking account or to a credit union share draft account. Instead, you are spending money you placed in the prepaid card account in advance. This is sometimes called “loading money onto the card”.// For hacked credit cards, this subcategory can be used >:D JK!
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Digital Art', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Digital Currencies - Cryptocurrencies', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Digital Currencies - Fiat', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('eBooks', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Freelancing', $1)", { std::to_string(category_id) }); // sell your personal services online in a gig-economy and work from home // freelancing is different and better than remote work cuz you are your own boss // Gigs are also known as “freelancing” and “independent contracting” jobs
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Information - Online accounts', $1)", { std::to_string(category_id) }); // includes online accounts such as video game accounts, netflix accounts, etc.
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Media - Audio', $1)", { std::to_string(category_id) }); // sound, video, text, etc. // Multimedia is the combined use of sound, video, and text to present an idea
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Media - Documents', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Media - Photos', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Media - Videos', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Software', $1)", { std::to_string(category_id) }); // general software
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Video Games', $1)", { std::to_string(category_id) }); // video games are softwares with their own category :O
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Virtual Goods - In-Game content', $1)", { std::to_string(category_id) }); // video game/virtual avatars, items, etc.
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Virtual Goods - NFTs', $1)", { std::to_string(category_id) }); // NFTs can be more than just art ranging from Fashion and wearables, DeFi, Events and ticketing, etc.
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Websites and Domain names', $1)", { std::to_string(category_id) });
////database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('?', $1)", { std::to_string(category_id) });
//---------------------------
// category here
category_id = database->get_integer("INSERT INTO categories (name, alt_names) VALUES ('Books', '') RETURNING id;");
// subcategories here
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Children''s Books', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Comics & Manga', $1)", { std::to_string(category_id) }); // include Manga?
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Cookbooks', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Journals', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Magazines', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Newspapers', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Poetry', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Textbooks', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Novels', $1)", { std::to_string(category_id) });
////database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('?', $1)", { std::to_string(category_id) });
//---------------------------
// category here
category_id = database->get_integer("INSERT INTO categories (name, alt_names) VALUES ('Apparel', 'Clothing, Shoes and Accessories; Fashion') RETURNING id;"); // Wearables // Almost DONE :)!
// subcategories here
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Armwear', $1)", { std::to_string(category_id) }); // gloves, bracelets, sleeves, armband, etc.
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Baby & Toddler', $1)", { std::to_string(category_id) }); // diapers, bibs, etc.
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Bags, Handbags, Backpacks, Wallets, Purses & Pouches', $1)", { std::to_string(category_id) }); // backpacks, handbags, purses, totes, laptop bags, duffel bags, fanny packs/belt bags, briefcases, etc. // https://shilpaahuja.com/types-of-bags/ // Carry Goods or Carry Access.
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Bottomwear', $1)", { std::to_string(category_id) }); // pants/trousers/jeans, shorts, skirts, miniskirts, leggings, breeches, etc.
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Cookwear - Aprons & Bibs', $1)", { std::to_string(category_id) }); // kappōgis, pinafores, etc.
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Costumes & Cosplay', $1)", { std::to_string(category_id) }); // costumes, reanactment and theater, and masks too
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Dresses & Gowns', $1)", { std::to_string(category_id) }); // dresses, blouses, gowns
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Eyewear', $1)", { std::to_string(category_id) }); // eyeglasses, googles, sunglasses / shades, monocles, eyepatches, contact lenses, etc.
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Footwear', $1)", { std::to_string(category_id) }); // socks, boots, shoes / sneakers, slippers, sandals, heels, flats, crocs
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Handwear - Gloves, Mittens', $1)", { std::to_string(category_id) }); // gloves, mittens, boxing gloves, rubber gloves, knuckle dusters, etc.
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Headwear', $1)", { std::to_string(category_id) }); // hats, caps, bandanas, headbands, crowns, wigs, kerchiefs, helmets, hijabs, hoods, headscarfs, turbans, hair nets, face masks, theatre masks, gas masks, sports mask for hockey, masquerade ball masks, ritual masks, etc.
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Hosiery - Socks & stockings, Pantyhose, Tights, etc.', $1)", { std::to_string(category_id) }); // socks & stockings, knee-highs, pantyhose, tights, fishnets + garters, leg warmers, yoga pants, etc.
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Kids'' Wear', $1)", { std::to_string(category_id) }); // or Children''s
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Knee clothing', $1)", { std::to_string(category_id) }); // knee-pads, etc.
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Men''s Wear', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Neckwear', $1)", { std::to_string(category_id) }); // necklaces, chokers / collars, scarfs, neckties
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Outerwear', $1)", { std::to_string(category_id) }); // coats, sweaters / hoodies, and jackets
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Pets - Pets'' clothing', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Robes and cloaks', $1)", { std::to_string(category_id) }); // sleeping gowns, bath robes, ponchos, academic dress, etc.
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Scarfs, Shawls, Wraps & Pashimas', $1)", { std::to_string(category_id) }); // scarfs, shawls and wraps, pashimas
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Sleepwear & Pajamas', $1)", { std::to_string(category_id) }); // pyjamas, pyjama pants, night gowns, sleep shirts, etc. // Nightwear
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Sportswear', $1)", { std::to_string(category_id) }); // jerseys, swimsuits, tracksuits, bathing suits, wet suits, ski wear, motorcycle gear, etc.
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Suits & One-piece suits', $1)", { std::to_string(category_id) }); // one-piece suits include: Sling swimsuit, jumpsuits, flight/space suits, ski suits, chemturion, etc.
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Textiles', $1)", { std::to_string(category_id) }); // cloth pieces, fabrics:knitted, woven, and non-woven, silk, cotton, leather, etc. // https://www.masterclass.com/articles/28-types-of-fabrics-and-their-uses#28-different-types-of-fabric //
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Topwear - Shirts & Tops', $1)", { std::to_string(category_id) }); // tees, tank-tops/singlets, vests, coats, sweaters, and jackets, cardigans
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Topwear', $1)", { std::to_string(category_id) }); // tees, tank-tops/singlets, vests, coats, sweaters, and jackets, cardigans
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Traditional Wear', $1)", { std::to_string(category_id) }); // kimonos, kilts, sari(s), hwarots, etc.
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Underwear', $1)", { std::to_string(category_id) }); // slips, panties and boxers, bras, other undergarments
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Uniforms & Work Clothing', $1)", { std::to_string(category_id) }); // school uniforms, police uniforms, etc.
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Unisex', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Waistwear - Belts & Suspenders', $1)", { std::to_string(category_id) }); // belts, sashes like obi, karate belts, etc.
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Watches, Rings & Jewelry', $1)", { std::to_string(category_id) }); // accessory: rings, earrings, watches, bracelets, chains, necklaces, pendants, charms, jewelry clasps / hooks,
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Wedding & Formal', $1)", { std::to_string(category_id) }); // wedding gowns, dress shirts/men's suits/sweater vest/waistcoat/lounge jackets(suit coats) // formal attire
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Women''s Wear', $1)", { std::to_string(category_id) });
////database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('?', $1)", { std::to_string(category_id) });
//---------------------------
// category here
category_id = database->get_integer("INSERT INTO categories (name, alt_names) VALUES ('Pets', 'Domesticated Animals') RETURNING id;");
// subcategories here
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Dogs', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Cats', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Birds', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Fishes', $1)", { std::to_string(category_id) });
database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Reptiles', $1)", { std::to_string(category_id) });
//database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('Pet Supplies', $1)", { std::to_string(category_id) });
////database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('?', $1)", { std::to_string(category_id) });
//---------------------------
// category here
category_id = database->get_integer("INSERT INTO categories (name, alt_names) VALUES ('Cosmetics', 'Beauty & Personal Care') RETURNING id;"); // skin and hair care
// subcategories here
//////database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('?', $1)", { std::to_string(category_id) });
/*//---------------------------
// category here
category_id = database->get_integer("INSERT INTO categories (name, alt_names) VALUES ('?', 'Musical Instruments') RETURNING id;");
// subcategories here
//database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('?', $1)", { std::to_string(category_id) });
//---------------------------
// category here
category_id = database->get_integer("INSERT INTO categories (name, alt_names) VALUES ('?', '') RETURNING id;"); // Sports & Outdoor Goods => Camping & Hiking, Garden (pots, plants, gardening tools), Cookouts & Outdoor Furniture (patios, etc.), Recreation (basketball hoop, etc.), Fishing & Hunting
// subcategories here
//database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('?', $1)", { std::to_string(category_id) });
//database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('?', $1)", { std::to_string(category_id) });
//database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('?', $1)", { std::to_string(category_id) });
//database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('?', $1)", { std::to_string(category_id) });
//---------------------------
// category here
category_id = database->get_integer("INSERT INTO categories (name, alt_names) VALUES ('Everything Else', 'Miscellaneous') RETURNING id;");
// subcategories here
//database->execute_params("INSERT INTO subcategories (name, category_id) VALUES ('?', $1)", { std::to_string(category_id) });
//--------------------------- */
//-------------------------
// favorites (wishlists)
if(!database->table_exists("favorites")) {
//database->execute("CREATE TABLE ?tbl(id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT);");
//database->execute("ALTER TABLE ?tbl ADD COLUMN user_id INTEGER REFERENCES users(id);");
//database->execute("ALTER TABLE ?tbl ADD COLUMN item_ids integer[];");
//database->execute("ALTER TABLE ?tbl ADD COLUMN ?col ?datatype;");
}
//-------------------------
database->execute("COMMIT;");
//database->execute_params("UPDATE users SET verify_key = $1 WHERE id = 2;", { "myverifykey1" });
//std::string verify_key = database->get_text_params("SELECT verify_key FROM users WHERE id = $1;", { "1" });
//std::cout << "verify_key: " << verify_key << std::endl;
//database->execute("INSERT INTO users(verify_key, encrypt_key) VALUES(\"myverifykey1\", \"myencryptkey1\");");
}
int main() {
// Do some testing here ...
start_and_initialize_database();
// Fetch the database singleton object
db::Sqlite3 * database = db::Sqlite3::get_singleton();
// register an item
Item ball("Ball", "A round and bouncy play-thing", 10, 0.5, std::make_tuple(0, 0, 0), "new", "0000-0000-0001");
Item candy("Candy", "O' so sweet and dee-lish!", 2, 0.01, std::make_tuple(0, 0, 0), "", "0000-0000-0002");
Item ring("Ring", "One ring to rule them all", 99, 0.5, std::make_tuple(0, 0, 0), "new", "0000-0000-0003");
// register user
/*if(!Validator::register_peer()) {
neroshop::print("register_peer: failed", 1);
}*/
// create a user
//User * user = Seller::on_login();//new Seller();
//static_cast<Seller *>(user)->list_item(ball, 50, 8.50, "usd", 0.00, 0, 0, "", "new");
// list an item
// temporary testing code
////Encryptor::generate_key_pair();
/*Wallet * create_wallet = new Wallet();
std::string wallet_name = "auth";
std::string wallet_pwd;
//std::cout << "Please enter your desired wallet path and name:\n";
//std::getline(std::cin, wallet_name);
std::cout << "Please enter your desired wallet password:\n";
std::getline(std::cin, wallet_pwd);
// Create a directory in home folder for wallets
std::cout << "trying to creating wallet at: " << NEROSHOP_DEFAULT_WALLET_PATH << std::endl;
// todo: make wallet path customizable by user
if(!std::filesystem::is_directory(NEROSHOP_DEFAULT_WALLET_PATH)) {
if(!neroshop::filesystem::make_directory(NEROSHOP_DEFAULT_WALLET_PATH)) {
neroshop::print("FAILED TO MAKE WALLET DIRECTORY", 1);
return 1;
}
std::cout << "created directory " << NEROSHOP_DEFAULT_WALLET_PATH << std::endl;
}
create_wallet->create_random(wallet_pwd, wallet_pwd, NEROSHOP_DEFAULT_WALLET_PATH + "/" + wallet_name);
// Provide user with their mnemonic
std::cout << "Store these words safely. There words are the key to your account. If you lose them Your account goes bye-bye:\n";
std::cout << create_wallet->get_mnemonic(wallet_pwd) << std::endl;
return 0;*/
// User can upload a wallet file or type their mnemonic or view/spend keys or connect a hardware wallet
//-------------------------
// Get private_key contents from file
/*std::ifstream rfile (std::string(NEROSHOP_CONFIG_PATH + "/secret.key").c_str(), std::ios::binary);
std::stringstream private_key;
private_key << rfile.rdbuf(); // dump file contents
rfile.close();
std::cout << "secret.key contents: \n" << private_key.str() << std::endl;
// Get SHA256sum of private_key contents
std::string sha256sum;
Validator::generate_sha256_hash(private_key.str(), sha256sum); // 1.7 kilobytes
std::cout << "sha256sum of secret.key content: " << sha256sum << std::endl;*/
//-------------------------
//neroshop::Server server;
//server.bind("exit", [](void) { ::system("exit"); });
//-------------------------
// Authentication Test
// bool authenticate_user(mnemonic, password)
//-------------------------
std::cout << neroshop::string::precision("1.123456789", 9) << std::endl;
std::cout << neroshop::string::lower("LOWER") << std::endl;
std::cout << neroshop::string::upper("upper") << std::endl;
#if defined(__cplusplus) && (__cplusplus >= 201402L) // 14
std::cout << "This compiler supports C++ 14\n";
#endif
#if defined(__cplusplus) && (__cplusplus >= 201703L) // 17
std::cout << "This compiler supports C++ 17\n";
#endif
std::cout << "current dir: " << neroshop::filesystem::current_directory() << std::endl;
std::cout << "mkdir result: " << neroshop::filesystem::make_directory("dude") << std::endl;
std::cout << "get_user result: " << neroshop::device::get_user() << std::endl;
//std::cout << "filename result: " << neroshop::filesystem::get_file_extension("player.png") << std::endl;
//-------------------------
// QR Test
/*QrCode::Ecc ecc = QrCode::Ecc::LOW;
std::string text = "888tNkZrPN6JsEgekjMnABU4TBzc2Dt29EPAvkRxbANsAnjyPbb3iQ1YBRk1UXcdRsiKc9dhwMVgN5S9cQUiyoogDavup3H";
int image_size = 400;
auto qr_code = qrcodegen::QrCode::encodeText(text.c_str(), ecc);
neroshop::QR qr("qr.png", 400, text, true, ecc);
std::cout << "qr image size: " << qr.get_size() << std::endl;//(qr_code) << std::endl;
std::cout << "qr text: " << qr.get_text() << std::endl;
std::cout << "qr file: " << qr.get_file() << std::endl;
// Do the conversion
qr.to_png();*/
//QR::export_png("qr_export.png", 400, "Turtles are cool!", true, QrCode::Ecc::LOW);
//-------------------------
// UUID test
/*uuids::uuid const id = uuids::uuid_system_generator{}();
assert(!id.is_nil());
assert(id.version() == uuids::uuid_version::random_number_based);
assert(id.variant() == uuids::uuid_variant::rfc);*/
//-------------------------
// Close database when app is terminated
database->close();
return 0;
}

@ -0,0 +1,246 @@
#include "../include/process.hpp"
neroshop::Process::Process()
{
#ifdef __gnu_linux__
handle = -1; // default
#endif
}
////////////////////
neroshop::Process::Process(const std::string& program, const std::string& arg) : Process()
{
if(!create(program, arg)) {
neroshop::print("Process creation failed", 1);
}
}
////////////////////
neroshop::Process::~Process()
{
#ifdef __gnu_linux__
#ifdef DOKUN_DEBUG0
std::cout << DOKUN_UI_TAG "process (" << name << ") has been deallocated" << std::endl;
#endif
#endif
terminate(); // kill pid
}
////////////////////
std::vector<std::tuple<std::string, int, bool>> neroshop::Process::process_list({});
////////////////////
void * neroshop::Process::open()
{
#ifdef _WIN32
this->handle = static_cast<void *>(OpenProcess(PROCESS_ALL_ACCESS, FALSE, GetCurrentProcessId()));
return this->handle;
#endif
#ifdef __gnu_linux__
#endif
return nullptr;
}
////////////////////
bool neroshop::Process::create(const std::string& program, const std::string& argument)
{
#ifdef _WIN32
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory (&si, sizeof(si));
si.cb = sizeof (si);
ZeroMemory (&pi, sizeof(pi));
// static_cast<LPSTR>(const_cast<char *>(program.c_str()))
std::string cmd = program + argument;
// Start the child process.
if(CreateProcess(
NULL,//static_cast<LPCTSTR>("glue.exe"), // No module name (use command line)
static_cast<LPSTR>(const_cast<char *>(cmd.c_str())),//static_cast<LPCTSTR>("glue.exe srlua.exe main.lua main.exe"), // Command line
NULL, // Process handle not inheritable
NULL, // Thread handle not inheritable
FALSE, // Set handle inheritance to FALSE
CREATE_NEW_CONSOLE, // No creation flags
NULL, // Use parent's environment block
NULL, // Use parent's starting directory
&si, // Pointer to STARTUPINFO structure
&pi ) // Pointer to PROCESS_INFORMATION structure
== 0)
{
return false;
}
// Wait until child process exits.
WaitForSingleObject (pi.hProcess, INFINITE);
// Close process and thread handles.
CloseHandle (pi.hProcess);
CloseHandle (pi.hThread );
#endif
#ifdef __gnu_linux__
pid_t child_pid = fork (); // holds the process id (pid)
if (child_pid != 0) {
// the handle is basically the process id (pid)
this->handle = static_cast<pid_t>(child_pid);
this->name = program.substr(program.find_last_of("\\/") + 1);//program;
// store process information in "process_list"
process_list.push_back(std::make_tuple(program, child_pid, (child_pid != -1)));
}
else {
std::vector<std::string> arg_split = neroshop::string::split(argument, " ");
char * arg_list[arg_split.size()];
for(int i = 0; i < arg_split.size(); i++)
{
arg_list[i] = static_cast<char *>(const_cast<char *>(arg_split[i].c_str()));
//std::cout << arg_list[i] << std::endl;
}
arg_list[arg_split.size()] = nullptr; // arg_list must end with a nullptr
/* Now execute PROGRAM, searching for it in the path. */
execvp (static_cast<char *>(const_cast<char *>(program.c_str())), arg_list);
/* The execvp function returns only if an error occurs. */
fprintf (stderr, "an error occurred in execvp\n");
abort ();
}
#endif
return true;
}
////////////////////
bool neroshop::Process::terminate()
{
#ifdef _WIN32
return (TerminateProcess(static_cast<HANDLE>(this->handle), 0) != 0);
#endif
#ifdef __gnu_linux__
if(handle == -1) return true; // if pid has already been killed then no need to kill it again, so exit function
// kill function doesn't even work -.-
if(kill(static_cast<pid_t>(handle), SIGKILL) != 0) {// 0=success, -1=failure // #include <signal.h>
std::cout << "FAILED to kill process: " << handle << std::endl;
return false;
}
// just to be sure process has been killed
// this doesn't work either LOL
//std::system(std::string("kill " + std::to_string(handle)).c_str());
handle = -1;// set handle to default value so we know its been properly deleted
////std::cout << DOKUN_UI_TAG "process (" << name << ") terminated\n";
return true;
#endif
return false;
}
////////////////////
bool neroshop::Process::terminate(const Process& process)
{
#ifdef _WIN32
return (TerminateProcess(static_cast<HANDLE>(process.get_handle()), 0) != 0);
#endif
#ifdef __gnu_linux__
// kill function doesn't even work -.-
return const_cast<Process&>(process).terminate();//return (kill(static_cast<pid_t>(process.get_handle()), SIGTERM) != -1); //0=success, -1=failure// #include <signal.h>
#endif
return false;
}
////////////////////
void neroshop::Process::terminate_by_process_id(int process_id) {
#ifdef __gnu_linux__
while(process_id != -1) {
if(kill(static_cast<pid_t>(process_id), SIGTERM) < 0) // kill all instances of this process
std::cout << "FAILED to kill process " << process_id << std::endl;
}
#endif
}
////////////////////
void neroshop::Process::terminate_by_process_name(const std::string& process_name) {
#ifdef __gnu_linux__
while(neroshop::Process::get_process_by_name(process_name) != -1) {// while this process is still running
if(kill(static_cast<pid_t>(neroshop::Process::get_process_by_name(process_name)), SIGTERM) < 0) // kill all instances of this process
std::cout << "FAILED to kill process " << process_name << std::endl;
}
#endif
}
////////////////////
void neroshop::Process::exit(int code)
{
#ifdef _WIN32
ExitProcess(code);
#endif
#ifdef __gnu_linux__
#endif
}
////////////////////
////////////////////
////////////////////
////////////////////
void neroshop::Process::show_processes(void) { // displays all processes from current session
for(int i = 0; i < process_list.size(); i++) {
std::cout
<< "\033[1;35;49mprocess[" << i << "] ("
<< "name: " << std::get<0>(process_list[i]) << ", "
<< "id: " << std::get<1>(process_list[i]) << ", "
<< "status: " << std::get<2>(process_list[i])
<< ")\033[0m"
<< std::endl;
}
}
////////////////////
////////////////////
////////////////////
////////////////////
#ifdef _WIN32
void * neroshop::Process::get_handle() const
{
return this->handle;
}
#endif
////////////////////
#ifdef __gnu_linux__
int neroshop::Process::get_handle() const
{
return handle;
}
////////////////////
std::string neroshop::Process::get_name() const {
return name;
}
////////////////////
int neroshop::Process::get_process_by_name(const std::string& process_name) { // UPDATE(2022-02-05): this doesn't work as well as I expected it to :/
int pid = -1;
// Open the /proc directory
DIR *dp = opendir("/proc");
if (dp != NULL)
{
// Enumerate all entries in directory until process found
struct dirent *dirp;
while (pid < 0 && (dirp = readdir(dp)))
{
// Skip non-numeric entries
int id = atoi(dirp->d_name);
if (id > 0)
{
// Read contents of virtual /proc/{pid}/cmdline file
std::string cmdPath = std::string("/proc/") + dirp->d_name + "/cmdline";
std::ifstream cmdFile(cmdPath.c_str());
std::string cmdLine;
std::getline(cmdFile, cmdLine);
if (!cmdLine.empty())
{
// Keep first cmdline item which contains the program path
size_t pos = cmdLine.find('\0');
if (pos != std::string::npos)
cmdLine = cmdLine.substr(0, pos);
// Keep program name only, removing the path
pos = cmdLine.rfind('/');
if (pos != std::string::npos)
cmdLine = cmdLine.substr(pos + 1);
// Compare against requested process name
if (process_name == cmdLine)
pid = id;
}
}
}
}
closedir(dp);
return pid;
}
#endif
////////////////////
void * neroshop::Process::get_active()
{
#ifdef _WIN32
return static_cast<void *>(GetCurrentProcess());
#endif
#ifdef __gnu_linux__
#endif
return nullptr;
}

@ -2,12 +2,12 @@
neroshop::QR::QR() {}
////////////////////
neroshop::QR::QR(std::string filename, int image_size, std::string text,
neroshop::QR::QR(const std::string& filename, int image_size, const std::string& text,
bool overwrite, qrcodegen::QrCode::Ecc ecc) : QR() {
this->filename = filename;
this->size = image_size;
this->text = text;
this->overwrite_existing_file = overwrite;
this->overwrite = overwrite;
this->ecc = ecc;
}
////////////////////
@ -19,7 +19,7 @@ bool neroshop::QR::to_png() const {
std::ifstream file(filename.c_str());
bool exists = file.good();
file.close();
if(!overwrite_existing_file && exists) return false;
if(!overwrite && exists) return false;
auto qr_code = qrcodegen::QrCode::encodeText(text.c_str(), ecc);
@ -118,14 +118,110 @@ bool neroshop::QR::write_to_png(const QrCode& qr, const int& multiplicator) cons
return true;
}
////////////////////
bool neroshop::QR::export_png(const std::string& filename, int size, const std::string& text, bool overwrite, QrCode::Ecc ecc) {
auto qr = qrcodegen::QrCode::encodeText(text.c_str(), ecc);
int multiplicator = size / qr.getSize();
FILE *fp = NULL;
png_structp png_ptr = NULL;
png_infop info_ptr = NULL;
png_bytep row = NULL;
// Open file for writing (binary mode)
fp = fopen(filename.c_str(), "wb");
if (fp == NULL) {
neroshop::print("Could not open file " + filename + " for writing", 1);
return false;
}
// Initialize write structure
png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (png_ptr == NULL) {
neroshop::print("Could not allocate write struct", 1);
fclose(fp);
return false;
}
// Initialize info structure
info_ptr = png_create_info_struct(png_ptr);
if (info_ptr == NULL) {
neroshop::print("Could not allocate info struct", 1);
fclose(fp);
png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1);
return false;
}
// Setup Exception handling
if (setjmp(png_jmpbuf(png_ptr))) {
neroshop::print("Error during png creation", 1);
fclose(fp);
png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1);
png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
return false;
}
png_init_io(png_ptr, fp);
// Write header (8 bit colour depth)
png_set_IHDR(png_ptr, info_ptr, qr.getSize()*multiplicator, qr.getSize()*multiplicator,
8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE,
PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
png_write_info(png_ptr, info_ptr);
// Allocate memory for one row (3 bytes per pixel)
row = (png_bytep) malloc(3 * multiplicator * qr.getSize() * sizeof(png_byte));
// Write image data
int offset_y = 0;
int offset_x = 0;
for (int y=0 ; y < qr.getSize() * multiplicator ; y++) {
for (int x=0 ; x < qr.getSize() * multiplicator; x++) {
if(qr.getModule(offset_x, offset_y)) {
row[x*3] = row[x*3+1] = row[x*3+2] = 0;
} else {
row[x*3] = row[x*3+1] = row[x*3+2] = 255;
}
if (x && x % multiplicator == 0) {
offset_x++;
}
}
offset_x = 0;
if (y && y % multiplicator == 0) {
offset_y++;
}
png_write_row(png_ptr, row);
}
// End write
png_write_end(png_ptr, NULL);
if (fp != NULL) fclose(fp);
if (info_ptr != NULL) png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1);
if (png_ptr != NULL) png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
if (row != NULL) free(row);
return true;
}
////////////////////
std::string neroshop::QR::get_text() const {
return text;
}
////////////////////
unsigned int neroshop::QR::image_size(const qrcodegen::QrCode& qr_data) const {
unsigned int neroshop::QR::get_size() const {
auto qr_data = qrcodegen::QrCode::encodeText(text.c_str(), ecc);
return (size / qr_data.getSize()) * qr_data.getSize();
}
////////////////////
unsigned int neroshop::QR::image_size_with_border(const qrcodegen::QrCode& qr_data) const {
return (size / (qr_data.getSize() + 2));
std::string neroshop::QR::get_file() const {
return filename;
}
////////////////////
////////////////////

@ -36,7 +36,7 @@ void neroshop::Seller::list_item(unsigned int item_id, unsigned int stock_qty, d
// make sure currency is supported
if(!neroshop::Converter::is_supported_currency(currency)) {neroshop::print(currency + " is not a supported currency", 2); return;}
////////////////////////////////
DB::SQLite3 */*std::unique_ptr<DB::SQLite3>*/ database = DB::SQLite3::get_singleton();//std::make_unique<DB::SQLite3>(NEROSHOP_DATABASE_FILE);
db::Sqlite3 */*std::unique_ptr<db::Sqlite3>*/ database = db::Sqlite3::get_singleton();//std::make_unique<db::Sqlite3>(NEROSHOP_DATABASE_FILE);
// to prevent duplicating item_id that is being sold by the same seller_id (a seller cannot list the same item twice, except change the stock amount)
int listed_item = database->get_integer_params("SELECT item_id FROM inventory WHERE item_id = $1 AND seller_id = $2", { std::to_string(item_id), std::to_string(get_id()) });
if(listed_item == item_id) {
@ -45,11 +45,11 @@ void neroshop::Seller::list_item(unsigned int item_id, unsigned int stock_qty, d
return;
}
// begin transaction - this is not necessary since it is just a single operation
////DB::Postgres::get_singleton()->execute("BEGIN;");
////db::Postgres::get_singleton()->execute("BEGIN;");
// create a restore point - no need for this
////DB::Postgres::get_singleton()->execute("SAVEPOINT before_seller_item_listing_savepoint;");
////db::Postgres::get_singleton()->execute("SAVEPOINT before_seller_item_listing_savepoint;");
// convert localtime to universal time
//std::cout << "discount_exp_date to UTC: " << DB::Postgres::get_singleton()->localtimestamp_to_utc(discount_expiry) << std::endl;
//std::cout << "discount_exp_date to UTC: " << db::Postgres::get_singleton()->localtimestamp_to_utc(discount_expiry) << std::endl;
// SELECT TO_TIMESTAMP('2021 12 10', 'YYYY-MM-DD HH24:MI:SS');
// SELECT TO_TIMESTAMP('2021-12-10', 'YYYY-MM-DD HH24:MI:SS');
// SELECT TO_CHAR(now(), 'YYYY-MM-DD HH24:MI:SS') ;
@ -69,7 +69,7 @@ void neroshop::Seller::list_item(const neroshop::Item& item, unsigned int stock_
////////////////////
void neroshop::Seller::delist_item(unsigned int item_id) {
#if defined(NEROSHOP_USE_POSTGRESQL)
DB::Postgres::get_singleton()->execute_params("DELETE FROM inventory WHERE item_id = $1 AND seller_id = $2", { std::to_string(item_id), std::to_string(get_id()) }); // update item stock to 0 beforehand or nah?
db::Postgres::get_singleton()->execute_params("DELETE FROM inventory WHERE item_id = $1 AND seller_id = $2", { std::to_string(item_id), std::to_string(get_id()) }); // update item stock to 0 beforehand or nah?
#endif
}
////////////////////
@ -84,7 +84,7 @@ void neroshop::Seller::delist_item(const neroshop::Item& item) {
// if seller accepts the order, then an address will be generated from seller's wallet and sent to the customer
// if seller rejects the order, their stock_qty is increased by the failed order's qty
void neroshop::Seller::load_customer_orders() {
/*DB::Sqlite3 db("neroshop.db");
/*db::Sqlite3 db("neroshop.db");
///////////
if(!db.table_exists("order_item")) return; // seller has probably never received an order from a customer before
// check for orders made by customers
@ -120,15 +120,15 @@ void neroshop::Seller::load_customer_orders() {
// postgresql
////////////////////////////////
#if defined(NEROSHOP_USE_POSTGRESQL)
//DB::Postgres::get_singleton()->connect("host=127.0.0.1 port=5432 user=postgres password=postgres dbname=neroshoptest");
//db::Postgres::get_singleton()->connect("host=127.0.0.1 port=5432 user=postgres password=postgres dbname=neroshoptest");
////////////////////////////////
// get number of order_items to be purchased by customers from this particular seller
int seller_customer_order_item_count = DB::Postgres::get_singleton()->get_integer_params("SELECT COUNT(*) FROM order_item WHERE seller_id = $1", { std::to_string(get_id()) });
int seller_customer_order_item_count = db::Postgres::get_singleton()->get_integer_params("SELECT COUNT(*) FROM order_item WHERE seller_id = $1", { std::to_string(get_id()) });
if(seller_customer_order_item_count < 1) {neroshop::print("No buyer has ordered an item from you yet"); return;}
// load customer orders
std::string command = "SELECT order_id FROM order_item WHERE seller_id = $1 ORDER BY order_id";
std::vector<const char *> param_values = { std::to_string(get_id()).c_str() };
PGresult * result = PQexecParams(DB::Postgres::get_singleton()->get_handle(), command.c_str(), 1, nullptr, param_values.data(), nullptr, nullptr, 0);
PGresult * result = PQexecParams(db::Postgres::get_singleton()->get_handle(), command.c_str(), 1, nullptr, param_values.data(), nullptr, nullptr, 0);
if (PQresultStatus(result) != PGRES_TUPLES_OK) {
neroshop::print("Seller::load_customer_orders(): No customer orders found", 2);
PQclear(result);
@ -145,13 +145,13 @@ void neroshop::Seller::load_customer_orders() {
}
/*#ifdef NEROSHOP_DEBUG0
// get items in the order_item table
unsigned int item_id = DB::Postgres::get_singleton()->get_integer_params("SELECT item_id FROM order_item WHERE id = $1 AND seller_id = $2", { std::to_string(i), std::to_string(get_id()) });
unsigned int item_qty = DB::Postgres::get_singleton()->get_integer_params("SELECT item_qty FROM order_item WHERE id = $1 AND seller_id = $2", { std::to_string(i), std::to_string(get_id()) });
unsigned int item_id = db::Postgres::get_singleton()->get_integer_params("SELECT item_id FROM order_item WHERE id = $1 AND seller_id = $2", { std::to_string(i), std::to_string(get_id()) });
unsigned int item_qty = db::Postgres::get_singleton()->get_integer_params("SELECT item_qty FROM order_item WHERE id = $1 AND seller_id = $2", { std::to_string(i), std::to_string(get_id()) });
Item item(item_id); // item obj will die at the end of this scope
std::cout << "You've received an order (id: " << order_id << ") from a customer "
<< "containing items: " << item.get_name() << " (id: " << item_id << ", qty: " << item_qty << ")" << std::endl;
#endif */
} //DB::Postgres::get_singleton()->get_integer_params("SELECT item_id FROM order_item WHERE id = $1 AND seller_id = $2", { std::to_string(i), std::to_string(get_id()) });
} //db::Postgres::get_singleton()->get_integer_params("SELECT item_id FROM order_item WHERE id = $1 AND seller_id = $2", { std::to_string(i), std::to_string(get_id()) });
////////////////////////////////
////////////////////////////////
@ -161,12 +161,12 @@ void neroshop::Seller::load_customer_orders() {
// THIS FUNCTION WILL BE LISTENING FOR ANY NEW (PENDING) ORDERS AT ALL TIMES
void neroshop::Seller::update_customer_orders() { // this function is faster (I think) than load_customer_orders()
#if defined(NEROSHOP_USE_POSTGRESQL)
//DB::Postgres::get_singleton()->connect("host=127.0.0.1 port=5432 user=postgres password=postgres dbname=neroshoptest");
//db::Postgres::get_singleton()->connect("host=127.0.0.1 port=5432 user=postgres password=postgres dbname=neroshoptest");
////////////////////////////////
//customer_order_list.clear(); // No need to clear customer_orders since it only inserts unique order_ids, so it will not take any duplicates
std::string command = "SELECT order_id FROM order_item WHERE seller_id = $1";
std::vector<const char *> param_values = { std::to_string(get_id()).c_str() };
PGresult * result = PQexecParams(DB::Postgres::get_singleton()->get_handle(), command.c_str(), 1, nullptr, param_values.data(), nullptr, nullptr, 0);
PGresult * result = PQexecParams(db::Postgres::get_singleton()->get_handle(), command.c_str(), 1, nullptr, param_values.data(), nullptr, nullptr, 0);
if (PQresultStatus(result) != PGRES_TUPLES_OK) {
neroshop::print("Seller::update_customer_orders(): No customer orders found", 2);
PQclear(result);
@ -179,7 +179,7 @@ void neroshop::Seller::update_customer_orders() { // this function is faster (I
// store order_ids if not already stored (does NOT store duplicates)
if(std::find(customer_order_list.begin(), customer_order_list.end(), customer_order_id) == customer_order_list.end()) {
// check if order is a pending order
bool is_pending = DB::Postgres::get_singleton()->get_integer_params("SELECT id FROM orders WHERE id = $1 AND status = $2", { std::to_string(customer_order_id), "Pending" });
bool is_pending = db::Postgres::get_singleton()->get_integer_params("SELECT id FROM orders WHERE id = $1 AND status = $2", { std::to_string(customer_order_id), "Pending" });
if(is_pending) {
std::cout << "You have received a new customer order (status: PENDING)" << std::endl; // for terminal
neroshop::Message::get_first()->set_text("You have received a new customer order (status: PENDING)");//\n Do you wish to proceed with this order?");
@ -249,7 +249,7 @@ void neroshop::Seller::set_stock_quantity(unsigned int item_id, unsigned int sto
// a seller can create an item and then register it to the database
if(item_id <= 0) {NEROSHOP_TAG_OUT std::cout << "\033[0;91m" << "Could not set stock_qty (invalid Item id)" << "\033[0m" << std::endl; return;}
/*// update stock_qty in database
DB::Sqlite3 db("neroshop.db");
db::Sqlite3 db("neroshop.db");
//db.execute("PRAGMA journal_mode = WAL;"); // this may reduce the incidence of SQLITE_BUSY errors (such as database being locked)
if(db.table_exists("inventory"))
db.update("inventory", "stock_qty", std::to_string(stock_qty), "item_id = " + std::to_string(item_id) + " AND seller_id = " + std::to_string(get_id()));
@ -258,9 +258,9 @@ void neroshop::Seller::set_stock_quantity(unsigned int item_id, unsigned int sto
// postgresql
////////////////////////////////
#if defined(NEROSHOP_USE_POSTGRESQL)
//DB::Postgres::get_singleton()->connect("host=127.0.0.1 port=5432 user=postgres password=postgres dbname=neroshoptest");
DB::Postgres::get_singleton()->execute_params("UPDATE inventory SET stock_qty = $1 WHERE item_id = $2 AND seller_id = $3", { std::to_string(stock_qty), std::to_string(item_id), std::to_string(get_id()) });
std::string item_name = DB::Postgres::get_singleton()->get_text_params("SELECT name FROM item WHERE id = $1", { std::to_string(item_id) });
//db::Postgres::get_singleton()->connect("host=127.0.0.1 port=5432 user=postgres password=postgres dbname=neroshoptest");
db::Postgres::get_singleton()->execute_params("UPDATE inventory SET stock_qty = $1 WHERE item_id = $2 AND seller_id = $3", { std::to_string(stock_qty), std::to_string(item_id), std::to_string(get_id()) });
std::string item_name = db::Postgres::get_singleton()->get_text_params("SELECT name FROM item WHERE id = $1", { std::to_string(item_id) });
neroshop::print("\"" + item_name + "\"'s stock has been updated", 3);
////////////////////////////////
@ -293,7 +293,7 @@ void neroshop::Seller::set_wallet(const neroshop::Wallet& wallet) {
// getters - seller rating system
////////////////////
unsigned int neroshop::Seller::get_good_ratings() const {
/*DB::Sqlite3 db("neroshop.db");
/*db::Sqlite3 db("neroshop.db");
if(db.table_exists("seller_ratings")) {
unsigned int good_ratings_count = db.get_column_integer("seller_ratings", "COUNT(score)", "seller_id = " + std::to_string(get_id()) + " AND score = " + std::to_string(1));
return good_ratings_count;
@ -303,9 +303,9 @@ unsigned int neroshop::Seller::get_good_ratings() const {
// postgresql
////////////////////////////////
#if defined(NEROSHOP_USE_POSTGRESQL)
//DB::Postgres::get_singleton()->connect("host=127.0.0.1 port=5432 user=postgres password=postgres dbname=neroshoptest");
if(!DB::Postgres::get_singleton()->table_exists("seller_ratings")) { return 0;}
unsigned int good_ratings_count = DB::Postgres::get_singleton()->get_integer_params("SELECT COUNT(score) FROM seller_ratings WHERE seller_id = $1 AND score = $2", { std::to_string(get_id()), std::to_string(1) });
//db::Postgres::get_singleton()->connect("host=127.0.0.1 port=5432 user=postgres password=postgres dbname=neroshoptest");
if(!db::Postgres::get_singleton()->table_exists("seller_ratings")) { return 0;}
unsigned int good_ratings_count = db::Postgres::get_singleton()->get_integer_params("SELECT COUNT(score) FROM seller_ratings WHERE seller_id = $1 AND score = $2", { std::to_string(get_id()), std::to_string(1) });
return good_ratings_count;
////////////////////////////////
@ -313,7 +313,7 @@ unsigned int neroshop::Seller::get_good_ratings() const {
return 0;
}
unsigned int neroshop::Seller::get_bad_ratings() const {
/*DB::Sqlite3 db("neroshop.db");
/*db::Sqlite3 db("neroshop.db");
if(db.table_exists("seller_ratings")) {
unsigned int bad_ratings_count = db.get_column_integer("seller_ratings", "COUNT(score)", "seller_id = " + std::to_string(get_id()) + " AND score = " + std::to_string(0));
return bad_ratings_count;
@ -323,9 +323,9 @@ unsigned int neroshop::Seller::get_bad_ratings() const {
// postgresql
////////////////////////////////
#if defined(NEROSHOP_USE_POSTGRESQL)
//DB::Postgres::get_singleton()->connect("host=127.0.0.1 port=5432 user=postgres password=postgres dbname=neroshoptest");
if(!DB::Postgres::get_singleton()->table_exists("seller_ratings")) { return 0;}
unsigned int bad_ratings_count = DB::Postgres::get_singleton()->get_integer_params("SELECT COUNT(score) FROM seller_ratings WHERE seller_id = $1 AND score = $2", { std::to_string(get_id()), std::to_string(0) });
//db::Postgres::get_singleton()->connect("host=127.0.0.1 port=5432 user=postgres password=postgres dbname=neroshoptest");
if(!db::Postgres::get_singleton()->table_exists("seller_ratings")) { return 0;}
unsigned int bad_ratings_count = db::Postgres::get_singleton()->get_integer_params("SELECT COUNT(score) FROM seller_ratings WHERE seller_id = $1 AND score = $2", { std::to_string(get_id()), std::to_string(0) });
return bad_ratings_count;
////////////////////////////////
@ -334,7 +334,7 @@ unsigned int neroshop::Seller::get_bad_ratings() const {
}
////////////////////
unsigned int neroshop::Seller::get_ratings_count() const {
/*DB::Sqlite3 db("neroshop.db");
/*db::Sqlite3 db("neroshop.db");
if(db.table_exists("seller_ratings")) {
unsigned int ratings_count = db.get_column_integer("seller_ratings", "COUNT(*)", "seller_id = " + std::to_string(get_id()));
return ratings_count;
@ -344,9 +344,9 @@ unsigned int neroshop::Seller::get_ratings_count() const {
// postgresql
////////////////////////////////
#if defined(NEROSHOP_USE_POSTGRESQL)
//DB::Postgres::get_singleton()->connect("host=127.0.0.1 port=5432 user=postgres password=postgres dbname=neroshoptest");
if(!DB::Postgres::get_singleton()->table_exists("seller_ratings")) { return 0;}
unsigned int ratings_count = DB::Postgres::get_singleton()->get_integer_params("SELECT COUNT(*) FROM seller_ratings WHERE seller_id = $1", { std::to_string(get_id()) });
//db::Postgres::get_singleton()->connect("host=127.0.0.1 port=5432 user=postgres password=postgres dbname=neroshoptest");
if(!db::Postgres::get_singleton()->table_exists("seller_ratings")) { return 0;}
unsigned int ratings_count = db::Postgres::get_singleton()->get_integer_params("SELECT COUNT(*) FROM seller_ratings WHERE seller_id = $1", { std::to_string(get_id()) });
return ratings_count;
////////////////////////////////
@ -359,7 +359,7 @@ unsigned int neroshop::Seller::get_total_ratings() const {
}
////////////////////
unsigned int neroshop::Seller::get_reputation() const {
/*DB::Sqlite3 db("neroshop.db");
/*db::Sqlite3 db("neroshop.db");
if(db.table_exists("seller_ratings")) {
unsigned int ratings_count = db.get_column_integer("seller_ratings", "COUNT(*)", "seller_id = " + std::to_string(get_id()));
if(ratings_count == 0) return 0; // seller has not yet been rated so his/her reputation will be 0%
@ -375,12 +375,12 @@ unsigned int neroshop::Seller::get_reputation() const {
// postgresql
////////////////////////////////
#if defined(NEROSHOP_USE_POSTGRESQL)
//DB::Postgres::get_singleton()->connect("host=127.0.0.1 port=5432 user=postgres password=postgres dbname=neroshoptest");
if(!DB::Postgres::get_singleton()->table_exists("seller_ratings")) { return 0;}
unsigned int ratings_count = DB::Postgres::get_singleton()->get_integer_params("SELECT COUNT(*) FROM seller_ratings WHERE seller_id = $1", { std::to_string(get_id()) });
//db::Postgres::get_singleton()->connect("host=127.0.0.1 port=5432 user=postgres password=postgres dbname=neroshoptest");
if(!db::Postgres::get_singleton()->table_exists("seller_ratings")) { return 0;}
unsigned int ratings_count = db::Postgres::get_singleton()->get_integer_params("SELECT COUNT(*) FROM seller_ratings WHERE seller_id = $1", { std::to_string(get_id()) });
if(ratings_count == 0) { return 0;} // seller has not yet been rated so his or her reputation will be 0%
// get seller's good ratings
unsigned int good_ratings = DB::Postgres::get_singleton()->get_integer_params("SELECT COUNT(score) FROM seller_ratings WHERE seller_id = $1 AND score = $2", { std::to_string(get_id()), std::to_string(1) });
unsigned int good_ratings = db::Postgres::get_singleton()->get_integer_params("SELECT COUNT(score) FROM seller_ratings WHERE seller_id = $1 AND score = $2", { std::to_string(get_id()), std::to_string(1) });
// calculate seller reputation
double reputation = (good_ratings / static_cast<double>(ratings_count)) * 100;
@ -396,7 +396,7 @@ std::vector<unsigned int> neroshop::Seller::get_top_rated_sellers(unsigned int l
// ISSUE: both seller_4 and seller_1 have the same number of 1_score_values but seller_1 has the highest reputation and it places seller_4 first [solved - by using reputation in addition]
std::string command = "SELECT users.id FROM users JOIN seller_ratings ON users.id = seller_ratings.seller_id WHERE score = 1 GROUP BY users.id ORDER BY COUNT(score) DESC LIMIT $1;";
std::vector<const char *> param_values = { std::to_string(limit).c_str() };
PGresult * result = PQexecParams(DB::Postgres::get_singleton()->get_handle(), command.c_str(), 1, nullptr, param_values.data(), nullptr, nullptr, 0);
PGresult * result = PQexecParams(db::Postgres::get_singleton()->get_handle(), command.c_str(), 1, nullptr, param_values.data(), nullptr, nullptr, 0);
if (PQresultStatus(result) != PGRES_TUPLES_OK) {
neroshop::print("Seller::get_top_rated_sellers(): No sellers found", 2);
PQclear(result);
@ -407,9 +407,9 @@ std::vector<unsigned int> neroshop::Seller::get_top_rated_sellers(unsigned int l
for(int i = 0; i < rows; i++) {
int seller_id = std::stoi(PQgetvalue(result, i, 0));
// calculate the reputation of each seller_id
unsigned int ratings_count = DB::Postgres::get_singleton()->get_integer_params("SELECT COUNT(*) FROM seller_ratings WHERE seller_id = $1", { std::to_string(seller_id) });
unsigned int ratings_count = db::Postgres::get_singleton()->get_integer_params("SELECT COUNT(*) FROM seller_ratings WHERE seller_id = $1", { std::to_string(seller_id) });
if(ratings_count == 0) continue; // seller has not yet been rated so his or her reputation will be 0%. Skip this seller
int good_ratings = DB::Postgres::get_singleton()->get_integer_params("SELECT COUNT(score) FROM seller_ratings WHERE seller_id = $1 AND score = $2", { std::to_string(seller_id), std::to_string(1) });
int good_ratings = db::Postgres::get_singleton()->get_integer_params("SELECT COUNT(score) FROM seller_ratings WHERE seller_id = $1 AND score = $2", { std::to_string(seller_id), std::to_string(1) });
double reputation = (good_ratings / static_cast<double>(ratings_count)) * 100;
// store the top rated seller_ids (only if they have a certain high reputation)
if(reputation >= 90) { // a reputation of 90 and above makes you a top rated seller (maybe I will reduce it to 85 just to be more fair or nah)
@ -455,7 +455,7 @@ std::vector<int> neroshop::Seller::get_pending_customer_orders() {
#if defined(NEROSHOP_USE_POSTGRESQL)
std::vector<int> pending_order_list;
////////////////////////////////
//DB::Postgres::get_singleton()->connect("host=127.0.0.1 port=5432 user=postgres password=postgres dbname=neroshoptest");
//db::Postgres::get_singleton()->connect("host=127.0.0.1 port=5432 user=postgres password=postgres dbname=neroshoptest");
////////////////////////////////
// update customer_order_list (by adding any new orders or orders that have not yet been added)
update_customer_orders();
@ -463,7 +463,7 @@ std::vector<int> neroshop::Seller::get_pending_customer_orders() {
// now lets get all the pending orders from the UPDATED customer_order_list
std::string pending_order_msg = "Pending orders awaiting seller approval: (ids: ";
for(int i = 0; i < customer_order_list.size(); i++) {
int pending_orders = DB::Postgres::get_singleton()->get_integer_params("SELECT id FROM orders WHERE id = $1 AND status = $2", { std::to_string(customer_order_list[i]), "Pending" });
int pending_orders = db::Postgres::get_singleton()->get_integer_params("SELECT id FROM orders WHERE id = $1 AND status = $2", { std::to_string(customer_order_list[i]), "Pending" });
if(pending_orders != 0) {
pending_order_list.push_back(customer_order_list[i]);
// gather ids of pending_orders
@ -505,7 +505,7 @@ std::vector<int> neroshop::Seller::get_pending_customer_orders() {
unsigned int neroshop::Seller::get_sales_count() const {
#if defined(NEROSHOP_USE_POSTGRESQL)
// should item not be considered sold until the order is done processing or nah ?
int items_sold = DB::Postgres::get_singleton()->get_integer_params("SELECT SUM(item_qty) FROM order_item WHERE seller_id = $1;", { std::to_string(get_id()) });
int items_sold = db::Postgres::get_singleton()->get_integer_params("SELECT SUM(item_qty) FROM order_item WHERE seller_id = $1;", { std::to_string(get_id()) });
return items_sold;
#endif
return 0;
@ -513,7 +513,7 @@ unsigned int neroshop::Seller::get_sales_count() const {
////////////////////
unsigned int neroshop::Seller::get_units_sold(unsigned int item_id) const {
#if defined(NEROSHOP_USE_POSTGRESQL)
int units_sold = DB::Postgres::get_singleton()->get_integer_params("SELECT SUM(item_qty) FROM order_item WHERE item_id = $1 AND seller_id = $2", { std::to_string(item_id), std::to_string(get_id()) });
int units_sold = db::Postgres::get_singleton()->get_integer_params("SELECT SUM(item_qty) FROM order_item WHERE item_id = $1 AND seller_id = $2", { std::to_string(item_id), std::to_string(get_id()) });
return units_sold;
#endif
return 0;
@ -525,7 +525,7 @@ unsigned int neroshop::Seller::get_units_sold(const neroshop::Item& item) const
////////////////////
double neroshop::Seller::get_sales_profit() const {
#if defined(NEROSHOP_USE_POSTGRESQL)
double profit_from_sales = DB::Postgres::get_singleton()->get_real_params("SELECT SUM(item_price * item_qty) FROM order_item WHERE seller_id = $1;", { std::to_string(get_id()) });//neroshop::print("The overall profit made from all sales combined is: $" + std::to_string(profit_from_sales), 3);
double profit_from_sales = db::Postgres::get_singleton()->get_real_params("SELECT SUM(item_price * item_qty) FROM order_item WHERE seller_id = $1;", { std::to_string(get_id()) });//neroshop::print("The overall profit made from all sales combined is: $" + std::to_string(profit_from_sales), 3);
return profit_from_sales;
#endif
return 0.0;
@ -533,7 +533,7 @@ double neroshop::Seller::get_sales_profit() const {
////////////////////
double neroshop::Seller::get_profits_made(unsigned int item_id) const {
#if defined(NEROSHOP_USE_POSTGRESQL)
double item_profits = DB::Postgres::get_singleton()->get_real_params("SELECT SUM(item_price * item_qty) FROM order_item WHERE item_id = $1 AND seller_id = $2;", { std::to_string(item_id), std::to_string(get_id()) });//std::string item_name = DB::Postgres::get_singleton()->get_text_params("SELECT name FROM item WHERE id = $1", { std::to_string(item_id) });neroshop::print("The overall profit made from \"" + item_name + "\" is: $" + std::to_string(item_profits), 3);
double item_profits = db::Postgres::get_singleton()->get_real_params("SELECT SUM(item_price * item_qty) FROM order_item WHERE item_id = $1 AND seller_id = $2;", { std::to_string(item_id), std::to_string(get_id()) });//std::string item_name = db::Postgres::get_singleton()->get_text_params("SELECT name FROM item WHERE id = $1", { std::to_string(item_id) });neroshop::print("The overall profit made from \"" + item_name + "\" is: $" + std::to_string(item_profits), 3);
return item_profits;
#endif
return 0.0;
@ -546,9 +546,9 @@ double neroshop::Seller::get_profits_made(const neroshop::Item& item) const {
unsigned int neroshop::Seller::get_item_id_with_most_sales() const { // this function is preferred over the "_by_mode" version as it provides the most accurate best-selling item_id result
#if defined(NEROSHOP_USE_POSTGRESQL)
// get the item with the biggest quantity sold (returns multiple results but I've limited it to 1)
int item_with_biggest_qty = DB::Postgres::get_singleton()->get_integer_params("SELECT item_id FROM order_item WHERE seller_id = $1 GROUP BY item_id ORDER BY SUM(item_qty) DESC LIMIT 1;", { std::to_string(get_id()) }); // from the biggest to smallest sum of item_qty
int item_with_biggest_qty = db::Postgres::get_singleton()->get_integer_params("SELECT item_id FROM order_item WHERE seller_id = $1 GROUP BY item_id ORDER BY SUM(item_qty) DESC LIMIT 1;", { std::to_string(get_id()) }); // from the biggest to smallest sum of item_qty
#ifdef NEROSHOP_DEBUG
std::string item_name = DB::Postgres::get_singleton()->get_text_params("SELECT name FROM item WHERE id = $1", { std::to_string(item_with_biggest_qty) });
std::string item_name = db::Postgres::get_singleton()->get_text_params("SELECT name FROM item WHERE id = $1", { std::to_string(item_with_biggest_qty) });
neroshop::print("\"" + item_name + "\" is your best-selling item with a sale of " + std::to_string(get_units_sold(item_with_biggest_qty)) + " units", 3);
#endif
return item_with_biggest_qty;
@ -559,10 +559,10 @@ unsigned int neroshop::Seller::get_item_id_with_most_sales() const { // this fun
unsigned int neroshop::Seller::get_item_id_with_most_orders() const {
#if defined(NEROSHOP_USE_POSTGRESQL)
// get the item with the most occurences in all orders - if two items are the most occuring then it will select the lowest item_id of the two (unless I add DESC)
int item_with_most_occurrences = DB::Postgres::get_singleton()->get_integer_params("SELECT MODE() WITHIN GROUP (ORDER BY item_id) FROM order_item WHERE seller_id = $1;", { std::to_string(get_id()) });
int item_with_most_occurrences = db::Postgres::get_singleton()->get_integer_params("SELECT MODE() WITHIN GROUP (ORDER BY item_id) FROM order_item WHERE seller_id = $1;", { std::to_string(get_id()) });
#ifdef NEROSHOP_DEBUG
std::string item_name = DB::Postgres::get_singleton()->get_text_params("SELECT name FROM item WHERE id = $1", { std::to_string(item_with_most_occurrences) });
int times_occured = DB::Postgres::get_singleton()->get_integer_params("SELECT COUNT(*) FROM order_item WHERE item_id = $1 AND seller_id = $2;", { std::to_string(item_with_most_occurrences), std::to_string(get_id()) });
std::string item_name = db::Postgres::get_singleton()->get_text_params("SELECT name FROM item WHERE id = $1", { std::to_string(item_with_most_occurrences) });
int times_occured = db::Postgres::get_singleton()->get_integer_params("SELECT COUNT(*) FROM order_item WHERE item_id = $1 AND seller_id = $2;", { std::to_string(item_with_most_occurrences), std::to_string(get_id()) });
neroshop::print("\"" + item_name + "\" is your most ordered item occuring a total of " + std::to_string(times_occured) + " times in all orders", 2);
#endif
return item_with_most_occurrences;
@ -579,7 +579,7 @@ unsigned int neroshop::Seller::get_item_id_with_most_orders() const {
////////////////////
bool neroshop::Seller::has_listed(unsigned int item_id) const {
#if defined(NEROSHOP_USE_POSTGRESQL)
bool listed = (DB::Postgres::get_singleton()->get_text_params("SELECT EXISTS(SELECT item_id FROM inventory WHERE item_id = $1 AND seller_id = $2);", { std::to_string(item_id), std::to_string(get_id()) }) == "t") ? true : false;
bool listed = (db::Postgres::get_singleton()->get_text_params("SELECT EXISTS(SELECT item_id FROM inventory WHERE item_id = $1 AND seller_id = $2);", { std::to_string(item_id), std::to_string(get_id()) }) == "t") ? true : false;
return listed;
#endif
return false;
@ -591,7 +591,7 @@ bool neroshop::Seller::has_listed(const neroshop::Item& item) const {
////////////////////
bool neroshop::Seller::has_stock(unsigned int item_id) const {
#if defined(NEROSHOP_USE_POSTGRESQL)
bool in_stock = (DB::Postgres::get_singleton()->get_text_params("SELECT EXISTS(SELECT item_id FROM inventory WHERE item_id = $1 AND seller_id = $2 AND stock_qty > 0);", { std::to_string(item_id), std::to_string(get_id()) }) == "t") ? true : false;
bool in_stock = (db::Postgres::get_singleton()->get_text_params("SELECT EXISTS(SELECT item_id FROM inventory WHERE item_id = $1 AND seller_id = $2 AND stock_qty > 0);", { std::to_string(item_id), std::to_string(get_id()) }) == "t") ? true : false;
return in_stock;
#endif
return false;
@ -619,13 +619,13 @@ bool neroshop::Seller::has_wallet_synced() const {
// callbacks
////////////////////
neroshop::User * neroshop::Seller::on_login(const std::string& username) { // assumes user data already exists in database
//DB::Postgres::get_singleton()->connect("host=127.0.0.1 port=5432 user=postgres password=postgres dbname=neroshoptest");//DB::Postgres::get_singleton()->connect;//DB::Postgres::get_singleton()->connect("host=127.0.0.1 port=5432 user=postgres password=postgres dbname=neroshoptest");
//db::Postgres::get_singleton()->connect("host=127.0.0.1 port=5432 user=postgres password=postgres dbname=neroshoptest");//db::Postgres::get_singleton()->connect;//db::Postgres::get_singleton()->connect("host=127.0.0.1 port=5432 user=postgres password=postgres dbname=neroshoptest");
// create a new user (seller)
neroshop::User * user = new Seller(username);
// set user properties retrieved from database
dynamic_cast<Seller *>(user)->set_logged(true); // protected, so can only be accessed by child class obj // if validator::login(user, pw) returns true, then set neroshop::User::logged to true
#if defined(NEROSHOP_USE_POSTGRESQL)
int user_id = DB::Postgres::get_singleton()->get_integer_params("SELECT id FROM users WHERE name = $1", { username });
int user_id = db::Postgres::get_singleton()->get_integer_params("SELECT id FROM users WHERE name = $1", { username });
dynamic_cast<Seller *>(user)->set_id(user_id);
#endif
dynamic_cast<Seller *>(user)->set_account_type(user_account_type::seller);

@ -255,36 +255,6 @@ void neroshop::Validator::change_pw(const std::string& old_pw, const std::string
////////////////////
////////////////////
////////////////////
bool neroshop::Validator::register_peer() {
DB::SQLite3 * database = DB::SQLite3::get_singleton();
// Generate public/private key pairs
EVP_PKEY * pkey = Encryptor::generate_key_pair_return();
if(!pkey) { neroshop::print("generate_key_pair_return failed", 1); return false; }
// Save public_key on the database (by default user names will be a SHA256 hash of the public key)
std::string public_key = Encryptor::get_public_key(pkey);//std::cout << "generated public_key: \n" << public_key << std::endl;//Encryptor::save_public_key(pkey, NEROSHOP_CONFIG_PATH + "/public.pem");
database->execute_params("INSERT INTO users(verify_key) VALUES($1);", { public_key });//database->execute_params("INSERT INTO users(name, verify_key) VALUES($1, $2);", { user_id, public_key });//database->execute_params("INSERT INTO users(name, verify_key, encrypt_key) VALUES($1, $2, $3);", { user_id, public_key });
// Save private_key locally on the user's device
Encryptor::save_private_key(pkey, NEROSHOP_CONFIG_PATH + "/secret.key");//"/keys/private.key"); // alternative names: secret.key, verify.key or private.key
// Display notification message
std::string sha256sum;
generate_sha256_hash(public_key, sha256sum);
std::string user_id = sha256sum;
neroshop::print((!user_id.empty()) ? std::string("Welcome to neroshop, user " + user_id) : "Welcome to neroshop", 4);
// free up the pkey
EVP_PKEY_free(pkey);
////EVP_PKEY_CTX_free(ctx);
return true;
}
////////////////////
bool neroshop::Validator::login_peer() {
// user will supply their id or name or public key (verify_key)
// message will be signed using user's public_key (verify_key)
// verify that public_key matches private_key (verify_key)
return true;
}
////////////////////
////////////////////
////////////////////
bool neroshop::Validator::validate_username(const std::string& username)
{
// username (will appear only in lower-case letters within the app)

@ -3,22 +3,9 @@
////////////////////
// constructors and destructors
////////////////////
neroshop::Wallet::Wallet() : process(nullptr), sync_bar(nullptr), monero_wallet_obj(nullptr), network_type(monero_network_type::STAGENET)
neroshop::Wallet::Wallet() : process(nullptr), monero_wallet_obj(nullptr), network_type(monero_network_type::STAGENET)
{}
////////////////////
neroshop::Wallet::Wallet(const std::string& file) { // must include .keys extension
// if wallet.keys file is found, open it
if(monero::monero_wallet_full::wallet_exists(file)) { // if file exists
open(file.substr(0, file.find(".")));
return; // exit function
}
// if wallet.keys is not found then create it
if(!monero::monero_wallet_full::wallet_exists(file)) { // in case the file does not exist
create(file.substr(0, file.find("."))); // create the wallet file
return; // exit function
}
}
////////////////////
neroshop::Wallet::~Wallet()
{
if(monero_wallet_obj.get()) {
@ -35,10 +22,6 @@ neroshop::Wallet::~Wallet()
process.reset(); // this will call the process destructor which should auto kill the process
if(!process.get()) std::cout << "wallet process deleted\n";
}
// destroy sync_bar
if(sync_bar.get()) {
sync_bar.reset(); // will also delete the label along with the label's font//if(!sync_bar.get()) std::cout << "wallet sync progress_bar deleted\n";
}
#ifdef NEROSHOP_DEBUG
std::cout << "wallet deleted\n";
#endif
@ -46,31 +29,62 @@ neroshop::Wallet::~Wallet()
////////////////////
////////////////////
////////////////////
// normal
////////////////////
void neroshop::Wallet::connect() { // connect a hardware wallet
}
////////////////////
void neroshop::Wallet::create(std::string password/*, const std::string& confirm_pw*/) {
std::string path = "wallet"; // will create a wallet.keys file in the current path
// Reminder: path is the path and name of the wallet without the .keys extension
void neroshop::Wallet::create_random(const std::string& password, const std::string& confirm_pwd, const std::string& path) {
if(confirm_pwd != password) {
neroshop::print("Wallet passwords do not match", 1);
return;
}
monero_wallet_obj = std::unique_ptr<monero_wallet_full>(monero_wallet_full::create_wallet_random (path, password, network_type/*, const monero_rpc_connection &daemon_connection=monero_rpc_connection(), const std::string &language="English", std::unique_ptr< epee::net_utils::http::http_client_factory > http_client_factory=nullptr*/));
if(monero_wallet_obj.get()) std::cout << "\033[1;35;49m" << "created wallet \"" << path << ".keys\"" << "\033[0m" << std::endl;
}
////////////////////
void neroshop::Wallet::create_from_mnemonic(const std::string& mnemonic, std::string password/*, const std::string &confirm_pw*/) {
// retrieve keys from text edit
std::string path = "wallet"; // will create a wallet.keys file in the current path
monero_wallet_obj = std::unique_ptr<monero_wallet_full>(monero_wallet_full::create_wallet_from_mnemonic (path, password, network_type, mnemonic/*, const monero_rpc_connection &daemon_connection=monero_rpc_connection(), uint64_t restore_height=0, const std::string &seed_offset="", std::unique_ptr< epee::net_utils::http::http_client_factory > http_client_factory=nullptr*/));
void neroshop::Wallet::create_from_mnemonic(const std::string& mnemonic, const std::string& password, const std::string& confirm_pwd, const std::string& path) {
if(confirm_pwd != password) {
neroshop::print("Wallet passwords do not match", 1);
return;
}
monero_wallet_obj = std::unique_ptr<monero_wallet_full>(monero_wallet_full::create_wallet_from_mnemonic (path, password, network_type, mnemonic));
if(monero_wallet_obj.get()) std::cout << "\033[1;35;49m" << "created wallet \"" << path << ".keys\" (from mnemonic)" << "\033[0m" << std::endl;
}
////////////////////
void neroshop::Wallet::create_from_keys(const std::string& address, const std::string& view_key, const std::string& spend_key, std::string password/*, const std::string &confirm_pw*/) {
// retrieve keys from text edit
std::string path = "wallet"; // will create a wallet.keys file in the current path
monero_wallet_obj = std::unique_ptr<monero_wallet_full>(monero_wallet_full::create_wallet_from_keys (path, password, network_type, address, view_key, spend_key/*, const monero_rpc_connection &daemon_connection=monero_rpc_connection(), uint64_t restore_height=0, const std::string &language="English", std::unique_ptr< epee::net_utils::http::http_client_factory > http_client_factory=nullptr*/));
// To restore a view-only wallet, leave the spend key blank
void neroshop::Wallet::create_from_keys(const std::string& address, const std::string& view_key, const std::string& spend_key, const std::string& password, const std::string &confirm_pwd, const std::string& path) {
if(confirm_pwd != password) {
neroshop::print("Wallet passwords do not match", 1);
return;
}
monero_wallet_obj = std::unique_ptr<monero_wallet_full>(monero_wallet_full::create_wallet_from_keys(path, password, network_type, address, view_key, spend_key));
if(monero_wallet_obj.get()) std::cout << "\033[1;35;49m" << "created wallet \"" << path << ".keys\" (from keys)" << "\033[0m" << std::endl;
}
////////////////////
void neroshop::Wallet::restore_from_mnemonic(const std::string& mnemonic)
{
monero_wallet_obj = std::unique_ptr<monero_wallet_full>(monero_wallet_full::create_wallet_from_mnemonic("", "", network_type, mnemonic)); // set path to "" for an in-memory wallet
if(monero_wallet_obj.get()) std::cout << "\033[1;35;49m" << "restored in-memory wallet (from mnemonic)" << "\033[0m" << std::endl;
}
////////////////////
void neroshop::Wallet::restore_from_keys(const std::string& primary_address, const std::string& view_key, const std::string& spend_key)
{
// Check validity of primary address
if(!monero_utils::is_valid_address(primary_address, network_type)) {
neroshop::print("Invalid Monero address", 1);
}
monero_wallet_obj = std::unique_ptr<monero_wallet_full>(monero_wallet_full::create_wallet_from_keys ("", "", network_type, primary_address, view_key, spend_key)); // set path to "" for an in-memory wallet
if(monero_wallet_obj.get()) std::cout << "\033[1;35;49m" << "restored in-memory wallet (from keys)" << "\033[0m" << std::endl;
}
////////////////////
void neroshop::Wallet::open(const std::string& path, const std::string& password) {
monero_wallet_obj = std::unique_ptr<monero_wallet_full>(monero::monero_wallet_full::open_wallet(path, password, network_type)); // will apply ".keys" ext to the wallet file
if(monero_wallet_obj.get()) std::cout << "\033[1;35;49m" << "opened wallet \"" << path << ".keys\"" << "\033[0m" << std::endl;
}
////////////////////
void neroshop::Wallet::close(bool save)
{
if(!monero_wallet_obj.get()) throw std::runtime_error("monero_wallet_full is not opened");
monero_wallet_obj->close(save);
}
////////////////////
std::string neroshop::Wallet::upload(bool open, std::string password) { // opens the wallet file
// open file dialog to retrieve walletfile path
// reminder: use this function for an upload button instead
@ -84,26 +98,10 @@ std::string neroshop::Wallet::upload(bool open, std::string password) { // opens
std::string filename(file); // "wallet.keys" file
filename = filename.substr(0, filename.find(".")); // remove ".keys" extension
if(!monero::monero_wallet_full::wallet_exists(filename + ".keys")) { neroshop::print("wallet not found", 1); return ""; } // check if wallet file is valid (or exists)
if(open == true) neroshop::Wallet::open(filename, password);// will re-apply ".keys" ext to the wallet file
if(open == true) neroshop::Wallet::open(filename, password);// will apply ".keys" ext to the wallet file
return std::string(filename + ".keys");
}
////////////////////
void neroshop::Wallet::open(const std::string& path, std::string password) { // opens the wallet file's name without the ".key" extension
monero_wallet_obj = std::unique_ptr<monero_wallet_full>(monero::monero_wallet_full::open_wallet(path, password, network_type)); // will re-apply ".keys" ext to the wallet file
if(monero_wallet_obj.get()) std::cout << "\033[1;35;49m" << "opened wallet \"" << path << ".keys\"" << "\033[0m" << std::endl;
}
////////////////////
void neroshop::Wallet::restore(const std::string& mnemonic, std::string password)
{}
////////////////////
void neroshop::Wallet::restore(const std::string& address, const std::string& view_key, const std::string& spend_key, std::string password)
{}
////////////////////
void neroshop::Wallet::close(bool save)
{
if(!monero_wallet_obj.get()) throw std::runtime_error("monero_wallet_full is not opened");
monero_wallet_obj->close(save);
}
////////////////////
void neroshop::Wallet::transfer(const std::string& address, double amount) {
if(!monero_wallet_obj.get()) throw std::runtime_error("monero_wallet_full is not opened");
@ -231,7 +229,7 @@ void neroshop::Wallet::on_sync_progress(uint64_t height, uint64_t start_height,
if((percent_done * 100) == 100) std::cout << "\033[0;35;49m" << date << " \033[1;32;49m" << "SYNCHRONIZATION DONE" << std::endl;
std::cout << "\033[0;35;49m" << date << std::endl;
std::cout << "\033[0;35;49m" << date << " \033[1;33;49m" << "**********************************************************************" << "\033[0m" << std::endl;*/
///////////////////////////////////
#ifdef NEROSHOP_USE_DOKUN_UI
if(!sync_bar.get()) {
sync_bar = std::unique_ptr<Progressbar>(new Progressbar());//sync_bar->set_range(0.0, 100.0); // 0-100%//sync_bar->set_outline(true);
sync_bar->set_size(300, 30);
@ -278,6 +276,7 @@ void neroshop::Wallet::on_sync_progress(uint64_t height, uint64_t start_height,
sync_bar->draw();
////////////////
window->update();
#endif
}
////////////////////
void neroshop::Wallet::on_output_received(const monero_output_wallet& output) {
@ -439,7 +438,7 @@ void neroshop::Wallet::wallet_info() {
double unlocked_balance = (double)unlocked_balance_raw * piconero;
std::cout << std::fixed << std::setprecision(12) << "unlocked_balance: " << unlocked_balance << std::fixed << std::setprecision(2) << std::endl; // uint64_t
// view and spend keys ----------------------------------------------------
std::cout << "view_key: " << get_viewkey("supersecretpassword123").first << std::endl;
std::cout << "view_key: " << get_view_keys().first << std::endl;
std::cout << "spend_key: " << "(secret)" << std::endl; // since this is intended to be a view-only wallet
// subaddress -------------------------------------------------------------
// generate new subaddresses on the default account 0
@ -554,22 +553,42 @@ std::string neroshop::Wallet::get_last_subaddress() const
////////////////////
////////////////////
// proof (proving the transaction was submitted) - https://web.getmonero.org/resources/user-guides/prove-payment.html
std::string neroshop::Wallet::get_tx_note(const std::string& txid) const {return "";} // "get_tx_note <txid>" - useful for retrieving address information
//std::string neroshop::Wallet::get_tx_note(const std::string& txid) const {return "";} // "get_tx_note <txid>" - useful for retrieving address information
////////////////////
std::string neroshop::Wallet::get_private_view_key() const {
if(!monero_wallet_obj.get()) throw std::runtime_error("monero_wallet_full is not opened");
return monero_wallet_obj->get_private_view_key();
}
////////////////////
std::string neroshop::Wallet::get_public_view_key() const {
if(!monero_wallet_obj.get()) throw std::runtime_error("monero_wallet_full is not opened");
return monero_wallet_obj->get_public_view_key();
}
////////////////////
std::pair<std::string, std::string> neroshop::Wallet::get_viewkey(const std::string& password) const {
std::pair<std::string, std::string> neroshop::Wallet::get_view_keys() const {
if(!monero_wallet_obj.get()) throw std::runtime_error("monero_wallet_full is not opened");
return std::make_pair(monero_wallet_obj->get_private_view_key(), monero_wallet_obj->get_public_view_key());
} // secret, public // "viewkey"
}
////////////////////
std::pair<std::string, std::string> neroshop::Wallet::get_spendkey(const std::string& password) const {
std::string neroshop::Wallet::get_private_spend_key() const {
if(!monero_wallet_obj.get()) throw std::runtime_error("monero_wallet_full is not opened");
return monero_wallet_obj->get_private_spend_key();
}
////////////////////
std::string neroshop::Wallet::get_public_spend_key() const {
if(!monero_wallet_obj.get()) throw std::runtime_error("monero_wallet_full is not opened");
return monero_wallet_obj->get_public_spend_key();
}
////////////////////
std::pair<std::string, std::string> neroshop::Wallet::get_spend_keys() const {
if(!monero_wallet_obj.get()) throw std::runtime_error("monero_wallet_full is not opened");
return std::make_pair(monero_wallet_obj->get_private_spend_key(), monero_wallet_obj->get_public_spend_key());
} // secret, public // "spendkey"
}
////////////////////
std::string neroshop::Wallet::get_mnemonic(const std::string& password) const {
std::string neroshop::Wallet::get_mnemonic() const {
if(!monero_wallet_obj.get()) throw std::runtime_error("monero_wallet_full is not opened");
return monero_wallet_obj->get_mnemonic();
} // "seed"
}
//-Image * neroshop::Wallet::get_qr_code() const {} // returns address qrcode // "show_qr_code"
//-Image * neroshop::Wallet::get_qr_code(unsigned int address_index) const {} // returns the qrcode of the address at "index"
////////////////////

@ -0,0 +1,419 @@
cmake_minimum_required(VERSION 3.1.0 FATAL_ERROR)
project(test)
set(neroshop_root ..)
set(neroshop_srcs ${neroshop_root}/src/buyer.cpp #[[${neroshop_root}/src/carrier.cpp]] ${neroshop_root}/src/cart.cpp ${neroshop_root}/src/catalog.cpp ${neroshop_root}/src/client.cpp ${neroshop_root}/src/converter.cpp ${neroshop_root}/src/database.cpp ${neroshop_root}/src/encryptor.cpp ${neroshop_root}/src/icon.cpp ${neroshop_root}/src/item.cpp ${neroshop_root}/src/message.cpp ${neroshop_root}/src/order.cpp ${neroshop_root}/src/process.cpp ${neroshop_root}/src/qr.cpp ${neroshop_root}/src/seller.cpp ${neroshop_root}/src/server.cpp ${neroshop_root}/src/user.cpp ${neroshop_root}/src/validator.cpp ${neroshop_root}/src/wallet.cpp)
#set(neroshop_headers ) # not needed
set(neroshop_include_dir ${neroshop_root}/include)# ${neroshop_root}/external
include_directories(${neroshop_include_dir})
link_directories(${neroshop_root}/src ${neroshop_root}/build)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ..) # will output to build/ instead of build/test/
######################################
#[[
if(WIN32)
endif()
if(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
# Set compiler-specific flags
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -w") #-w=ignores all warnings
message(STATUS "Building with clang")
else()
message(STATUS "Building with gcc/g++")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -no-pie") # detach
endif()
endif()
if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
endif()
]]
######################################
set(MONERO_PROJECT "${neroshop_root}/external/monero-cpp/external/monero-project")
set(MONERO_PROJECT_SRC "${MONERO_PROJECT}/src")
# header includes
include_directories("${MONERO_PROJECT}/contrib/epee/include")
include_directories("${MONERO_PROJECT}/external/")
include_directories("${MONERO_PROJECT}/external/easylogging++")
include_directories("${MONERO_PROJECT}/external/rapidjson/include")
include_directories("${MONERO_PROJECT_SRC}/")
include_directories("${MONERO_PROJECT_SRC}/wallet")
include_directories("${MONERO_PROJECT_SRC}/wallet/api")
include_directories("${MONERO_PROJECT_SRC}/crypto/crypto_ops_builder/include/")
set(EXTERNAL_LIBS_DIR ${neroshop_root}/monero-cpp/external-libs)
message(STATUS EXTERNAL_LIBS_DIR : ${EXTERNAL_LIBS_DIR})
######################################
# Extra libraries
if (APPLE)
if (DEPENDS)
list(APPEND EXTRA_LIBRARIES "-framework Foundation -framework IOKit -framework AppKit")
else()
find_library(COREFOUNDATION CoreFoundation)
find_library(IOKIT IOKit)
find_library(APPKIT AppKit)
list(APPEND EXTRA_LIBRARIES ${IOKIT})
list(APPEND EXTRA_LIBRARIES ${COREFOUNDATION})
list(APPEND EXTRA_LIBRARIES ${APPKIT})
endif()
endif()
if (WIN32)
list(APPEND EXTRA_LIBRARIES setupapi)
endif()
message(STATUS EXTRA_LIBRARIES: ${EXTRA_LIBRARIES})
######################################
# Protobuf
include(FindProtobuf)
find_package(Protobuf)
message(STATUS "Protobuf lib: ${Protobuf_LIBRARY}, inc: ${Protobuf_INCLUDE_DIR}, protoc: ${Protobuf_PROTOC_EXECUTABLE}")
include_directories(${Protobuf_INCLUDE_DIR})
######################################
# LibUSB
find_library(usb_LIBRARY NAMES usb-1.0 libusb usb)
set(LibUSB_LIBRARIES ${usb_LIBRARY})
######################################
# Boost - sudo apt install libboost-dev, sudo apt-get install libboost-all-dev
set(Boost_NO_BOOST_CMAKE 1)
set(Boost_USE_MULTITHREADED ON)
find_package(Boost 1.58 QUIET REQUIRED COMPONENTS chrono date_time filesystem program_options regex serialization wserialization system thread)
message(STATUS "Using Boost include dir at ${Boost_INCLUDE_DIR}")
include_directories(${Boost_INCLUDE_DIR})
add_definitions(-DBOOST_BIND_GLOBAL_PLACEHOLDERS) # to ignore warnings
######################################
# OpenSSL - sudo apt-get install libssl-dev
if (APPLE AND NOT IOS)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=x86-64 -fvisibility=default -std=c++11")
if (NOT OPENSSL_ROOT_DIR)
EXECUTE_PROCESS(COMMAND brew --prefix openssl
OUTPUT_VARIABLE OPENSSL_ROOT_DIR
OUTPUT_STRIP_TRAILING_WHITESPACE)
message(STATUS "Using OpenSSL found at ${OPENSSL_ROOT_DIR}")
endif()
endif()
find_package(OpenSSL REQUIRED)
message(STATUS "Using OpenSSL include dir at ${OPENSSL_INCLUDE_DIR}")
include_directories(${OPENSSL_INCLUDE_DIR})
if(STATIC AND NOT IOS)
if(UNIX)
set(OPENSSL_LIBRARIES "${OPENSSL_LIBRARIES};${CMAKE_DL_LIBS};${CMAKE_THREAD_LIBS_INIT}")
endif()
endif()
######################################
# libsodium
include_directories(external/monero-cpp/external/libsodium/include)
include_directories(external/monero-cpp/external/libsodium/include/sodium)
find_library(SODIUM_LIBRARY sodium REQUIRED)
message(STATUS "Using libsodium library at ${SODIUM_LIBRARY}")
#[[include_directories(monero-cpp/external/libsodium/include/sodium) # export.h
set(SODIUM_LIBRARIES monero-cpp/external/libsodium/src/crypto_verify/verify.c)]]
#set(sodium_src /usr/lib/x86_64-linux-gnu/libsodium.so)
######################################
# HIDAPI - https://github.com/libusb/hidapi/releases / sudo apt-get install libhidapi-dev / sudo apt-get install libusb-1.0-0-dev, sudo apt-get install libudev-dev (libudev.h)
if(APPLE)
include_directories(SYSTEM /usr/include/malloc)
if(POLICY CMP0042)
cmake_policy(SET CMP0042 NEW)
endif()
endif()
if (APPLE AND NOT IOS)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=x86-64 -fvisibility=default -std=c++11")
if (NOT OPENSSL_ROOT_DIR)
EXECUTE_PROCESS(COMMAND brew --prefix openssl
OUTPUT_VARIABLE OPENSSL_ROOT_DIR
OUTPUT_STRIP_TRAILING_WHITESPACE)
message(STATUS "Using OpenSSL found at ${OPENSSL_ROOT_DIR}")
endif()
endif()
find_package(HIDAPI)
if(HIDAPI_FOUND)
message(STATUS "Using HIDAPI include dir at ${HIDAPI_INCLUDE_DIR}")
add_definitions(-DHAVE_HIDAPI)
include_directories(${HIDAPI_INCLUDE_DIR})
link_directories(${LIBHIDAPI_LIBRARY_DIRS})
endif()
if(NOT HIDAPI_FOUND)
message("HIDAPI libraries not found. Will manually set libraries.")
if(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
set(UDEV_LIBRARY libudev.so)
set(HIDAPI_LIBRARY ${UDEV_LIBRARY} libhidapi-libusb.so) # or libhidapi-hidraw.so # has to be dynamically linked or you'll get "undefined reference to `libusb_get_device_address'" error
endif()
endif()
######################################
# Monero (monero-0.17.2.3 contents pasted in "monero-cpp/external/monero-project")
set(MONERO_PROJECT_BUILD "${MONERO_PROJECT}/build/release")
message(STATUS "Using monero-project build" : ${MONERO_PROJECT_BUILD})
#[[
add_library(wallet_merged STATIC IMPORTED)
set_target_properties(wallet_merged PROPERTIES IMPORTED_LOCATION
${MONERO_PROJECT_BUILD}/lib/libwallet_merged.a)
add_library(wallet STATIC IMPORTED)
set_target_properties(wallet PROPERTIES IMPORTED_LOCATION
${MONERO_PROJECT_BUILD}/lib/libwallet.a)
add_library(wallet_crypto STATIC IMPORTED)
set_target_properties(wallet_crypto PROPERTIES IMPORTED_LOCATION
${MONERO_PROJECT_BUILD}/src/crypto/wallet/libwallet-crypto.a)
add_library(lmdb STATIC IMPORTED)
set_target_properties(lmdb PROPERTIES IMPORTED_LOCATION
${MONERO_PROJECT_BUILD}/external/db_drivers/liblmdb/liblmdb.a)
add_library(epee STATIC IMPORTED)
set_target_properties(epee PROPERTIES IMPORTED_LOCATION
${MONERO_PROJECT_BUILD}/contrib/epee/src/libepee.a)
add_library(unbound STATIC IMPORTED)
set_target_properties(unbound PROPERTIES IMPORTED_LOCATION
${MONERO_PROJECT_BUILD}/external/unbound/libunbound.a)
add_library(easylogging STATIC IMPORTED)
set_target_properties(easylogging PROPERTIES IMPORTED_LOCATION
${MONERO_PROJECT_BUILD}/external/easylogging++/libeasylogging.a)
add_library(cryptonote_core STATIC IMPORTED)
set_target_properties(cryptonote_core PROPERTIES IMPORTED_LOCATION
${MONERO_PROJECT_BUILD}/src/cryptonote_core/libcryptonote_core.a)
add_library(cryptonote_basic STATIC IMPORTED)
set_target_properties(cryptonote_basic PROPERTIES IMPORTED_LOCATION
${MONERO_PROJECT_BUILD}/src/cryptonote_basic/libcryptonote_basic.a)
# new addition [2021-10-02]
add_library(cryptonote_format_utils_basic STATIC IMPORTED)
set_target_properties(cryptonote_format_utils_basic PROPERTIES IMPORTED_LOCATION
${MONERO_PROJECT_BUILD}/src/cryptonote_basic/libcryptonote_format_utils_basic.a)
add_library(mnemonics STATIC IMPORTED)
set_target_properties(mnemonics PROPERTIES IMPORTED_LOCATION
${MONERO_PROJECT_BUILD}/src/mnemonics/libmnemonics.a)
add_library(common STATIC IMPORTED)
set_target_properties(common PROPERTIES IMPORTED_LOCATION
${MONERO_PROJECT_BUILD}/src/common/libcommon.a)
add_library(cncrypto STATIC IMPORTED)
set_target_properties(cncrypto PROPERTIES IMPORTED_LOCATION
${MONERO_PROJECT_BUILD}/src/crypto/libcncrypto.a)
add_library(ringct STATIC IMPORTED)
set_target_properties(ringct PROPERTIES IMPORTED_LOCATION
${MONERO_PROJECT_BUILD}/src/ringct/libringct.a)
add_library(ringct_basic STATIC IMPORTED)
set_target_properties(ringct_basic PROPERTIES IMPORTED_LOCATION
${MONERO_PROJECT_BUILD}/src/ringct/libringct_basic.a)
add_library(blockchain_db STATIC IMPORTED)
set_target_properties(blockchain_db PROPERTIES IMPORTED_LOCATION
${MONERO_PROJECT_BUILD}/src/blockchain_db/libblockchain_db.a)
add_library(blocks STATIC IMPORTED)
set_target_properties(blocks PROPERTIES IMPORTED_LOCATION
${MONERO_PROJECT_BUILD}/src/blocks/libblocks.a)
add_library(checkpoints STATIC IMPORTED)
set_target_properties(checkpoints PROPERTIES IMPORTED_LOCATION
${MONERO_PROJECT_BUILD}/src/checkpoints/libcheckpoints.a)
add_library(device STATIC IMPORTED)
set_target_properties(device PROPERTIES IMPORTED_LOCATION
${MONERO_PROJECT_BUILD}/src/device/libdevice.a)
add_library(device_trezor STATIC IMPORTED)
set_target_properties(device_trezor PROPERTIES IMPORTED_LOCATION
${MONERO_PROJECT_BUILD}/src/device_trezor/libdevice_trezor.a)
add_library(multisig STATIC IMPORTED)
set_target_properties(multisig PROPERTIES IMPORTED_LOCATION
${MONERO_PROJECT_BUILD}/src/multisig/libmultisig.a)
add_library(version STATIC IMPORTED)
set_target_properties(version PROPERTIES IMPORTED_LOCATION
${MONERO_PROJECT_BUILD}/src/libversion.a)
add_library(randomx STATIC IMPORTED)
set_target_properties(randomx PROPERTIES IMPORTED_LOCATION
${MONERO_PROJECT_BUILD}/external/randomx/librandomx.a)
]]
######################################
set(monero_src wallet_merged wallet_crypto #[[wallet_api]] wallet lmdb epee unbound easylogging cryptonote_core cryptonote_basic cryptonote_format_utils_basic mnemonics ringct ringct_basic common cncrypto blockchain_db blocks checkpoints device device_trezor multisig version randomx
${Boost_LIBRARIES} ${Protobuf_LIBRARY} ${LibUSB_LIBRARIES} ${OPENSSL_LIBRARIES} ${SODIUM_LIBRARY} ${HIDAPI_LIBRARY} ${EXTRA_LIBRARIES})
######################################
# monero-cpp (wrapper) v0.5.1 => v0.5.5 => v0.5.10 => v0.6.4 => v0.7.0
include_directories(${neroshop_root}/external/monero-cpp/src/)
set(monero_cpp_src libmonero-cpp.a)#set(monero_cpp_src external/monero-cpp/src/utils/gen_utils.cpp external/monero-cpp/src/utils/monero_utils.cpp external/monero-cpp/src/daemon/monero_daemon_model.cpp external/monero-cpp/src/daemon/monero_daemon.cpp external/monero-cpp/src/wallet/monero_wallet_model.cpp external/monero-cpp/src/wallet/monero_wallet_keys.cpp external/monero-cpp/src/wallet/monero_wallet_full.cpp)
######################################
# libbcrypt (optional)
include_directories(${neroshop_root}/external/libbcrypt)
set(bcrypt_src libbcrypt.a)#set(bcrypt_src external/libbcrypt/crypt_blowfish/crypt_blowfish.c external/libbcrypt/crypt_blowfish/crypt_gensalt.c external/libbcrypt/crypt_blowfish/wrapper.c external/libbcrypt/bcrypt.c)
######################################
# sqlite3 (will be built-in/bundled with neroshop)
#[[find_package(SQLite3)
if(SQLite3_FOUND)
message(STATUS "Using SQLite3: ${SQLite3_LIBRARY} (v${SQLite3_VERSION})")
include_directories(${SQLite3_INCLUDE_DIRS})
set(sqlite_src ${SQLite3_LIBRARY}) # or ${SQLite3_LIBRARIES}
endif()
if(NOT SQLite3_FOUND)
include_directories(${neroshop_root}/external/sqlite)
set(sqlite_src ${neroshop_root}/external/sqlite/sqlite3.c) # amalgamation - runs a bit faster
endif()]]
include_directories(${neroshop_root}/external/sqlite)
set(sqlite_src libsqlite3.a)#set(sqlite_src ${neroshop_root}/external/sqlite/sqlite3.c)
######################################
# QR-Code-generator
include_directories(${neroshop_root}/external/QR-Code-generator/cpp)
set(qr_code_generator_src libqrcodegen.a)#set(qr_code_generator_src ${neroshop_root}/external/QR-Code-generator/cpp/qrcodegen.cpp) # or ${neroshop_root}/external/QR-Code-generator/c/qrcodegen.c
######################################
# json
include_directories(${neroshop_root}/external/json/single_include)
######################################
# curl
find_package(CURL) # if curl is found on the system, use the system default shared library, otherwise use the curl that we've built from source
if(CURL_FOUND)
message(STATUS "Using CURL: ${CURL_LIBRARIES} (v${CURL_VERSION_STRING})")
include_directories(${CURL_INCLUDE_DIRS})
set(curl_src ${CURL_LIBRARIES})
endif()
if(NOT CURL_FOUND)
include_directories(${neroshop_root}/external/curl/include ${neroshop_root}/external/curl/lib)
set(curl_src ${neroshop_root}/external/curl/lib/.libs/libcurl.a)
add_definitions(-DCURL_STATICLIB)
set(CMAKE_CXX_LINK_EXECUTABLE "${CMAKE_CXX_LINK_EXECUTABLE} -lldap -llber -lnghttp2 -lpsl -lidn2 -lbrotlidec -lzstd -lrtmp") # for Arch (Manjaro) # https://stackoverflow.com/questions/68368557/linking-nghttp2-static-library#comment120830125_68368557
endif()
######################################
# libuv (supports Android :D)
find_package(LIBUV)
if(LIBUV_FOUND)
message(STATUS "Using LIBUV: ${LIBUV_LIBRARIES}")
include_directories(${LIBUV_INCLUDE_DIRS})
set(libuv_src ${LIBUV_LIBRARIES})
endif()
if(NOT LIBUV_FOUND)
include_directories(${neroshop_root}/external/libuv/include ${neroshop_root}/external/libuv/src)
set(libuv_src ${neroshop_root}/external/libuv/.libs/libuv.a) # In case user chooses to build libuv themselves instead of installing it on the system
endif()
######################################
# willemt/raft (BSD and has zero dependencies :D)
include_directories(${neroshop_root}/external/raft/include)
set(raft_src libraft.a)#set(raft_src ${neroshop_root}/external/raft/src/raft_log.c ${neroshop_root}/external/raft/src/raft_node.c ${neroshop_root}/external/raft/src/raft_server.c ${neroshop_root}/external/raft/src/raft_server_properties.c)
######################################
# stduuid (header-only MIT library for generating uuids)
include_directories(${neroshop_root}/external/stduuid ${neroshop_root}/external/stduuid/catch ${neroshop_root}/external/stduuid/include)
######################################
# dokun-ui_dependencies
include_directories(${neroshop_root}/external/dokun-ui/external/lua/lua-5.4.1/src) # lua
include_directories(${neroshop_root}/external/dokun-ui/external/glew/include)
include_directories(${neroshop_root}/external/dokun-ui/external/png ${neroshop_root}/external/dokun-ui/external/zlib)
include_directories(${neroshop_root}/external/dokun-ui/external/freetype/include # public headers - ft2build.h
${neroshop_root}/external/dokun-ui/external/freetype/include/freetype # public headers
${neroshop_root}/external/dokun-ui/external/freetype/include/freetype/config # public config headers
${neroshop_root}/external/dokun-ui/external/freetype/include/freetype/internal) # private headers - added 2019-07-29
include_directories(${neroshop_root}/external/dokun-ui/external/ogg/include)
include_directories(${neroshop_root}/external/dokun-ui/external/vorbis/include
${neroshop_root}/external/dokun-ui/external/vorbis/lib)
include_directories(${neroshop_root}/external/dokun-ui/external/theora/include)
#include_directories(${neroshop_root}/external/dokun-ui/external/utf8/source)
include_directories(${neroshop_root}/external/dokun-ui/external/openal/include
${neroshop_root}/external/dokun-ui/external/openal-soft/include)
include_directories(${neroshop_root}/external/dokun-ui/external/jpeg
${neroshop_root}/external/dokun-ui/external/jpeg/jpeg-6b)
include_directories(${neroshop_root}/external/dokun-ui/external/tiff/libtiff)
include_directories(${neroshop_root}/external/dokun-ui/external/gif/lib)
include_directories(#[[${neroshop_root}/external/flac]] # config.h
${neroshop_root}/external/dokun-ui/external/flac/include
${neroshop_root}/external/dokun-ui/external/flac/src/libFLAC/include) # for "private/cpu.h"
include_directories(${neroshop_root}/external/dokun-ui/external/glm)
######################################
# dokun-ui
include_directories(${neroshop_root}/external/dokun-ui/include)
link_directories(${neroshop_root}/external/dokun-ui/src)
set(dokun_ui_src libdokun-ui.a) # definitions added: DOKUN_OPENGL, DOKUN_BUILD_LIBRARY#add_subdirectory(${neroshop_root}/external/dokun-ui)
######################################
# network_uv test
set(test_network_uv "network_uv_test")
add_executable(${test_network_uv} network_test_uv.cpp ${neroshop_srcs})
target_link_libraries(${test_network_uv} ${monero_cpp_src} ${sqlite_src} ${qr_code_generator_src} ${dokun_ui_src} ${raft_src} ${libuv_src} ${curl_src} ${monero_src})
# utility test
set(test_utility "utility_test")
add_executable(${test_utility} utility_test.cpp ${neroshop_srcs})
target_link_libraries(${test_utility} ${monero_cpp_src} ${sqlite_src} ${qr_code_generator_src} ${dokun_ui_src} ${raft_src} ${libuv_src} ${curl_src} ${monero_src})
# auth_test
set(test_auth "auth_test")
add_executable(${test_auth} auth_test.cpp ${neroshop_srcs})
target_link_libraries(${test_auth} ${monero_cpp_src} ${sqlite_src} ${qr_code_generator_src} ${dokun_ui_src} ${raft_src} ${libuv_src} ${curl_src} ${monero_src})
#[[
set(test_ "")
add_executable(${test_} .cpp ${neroshop_srcs})
target_link_libraries(${test_} ${monero_cpp_src} ${sqlite_src} ${qr_code_generator_src} ${dokun_ui_src} ${raft_src} ${libuv_src} ${curl_src} ${monero_src})
]]
######################################
# todo: Remove CLI dependency on dokun-ui (only tests that use GUI features should link to X11, OpenGL and GLFW)
if(DEFINED NEROSHOP_USE_LIBBCRYPT) # -DNEROSHOP_USE_LIBBCRYPT=1
message(STATUS "Using libbcrypt: ${bcrypt_src}")
#[[target_compile_definitions(${test_} PUBLIC -DNEROSHOP_USE_LIBBCRYPT)
target_link_libraries(${test_} ${bcrypt_src})]]
endif()
if(WIN32)
set(winsock2_src ws2_32.lib) # -lglfw3 -lgdi32 -lopengl32 -limm32
target_link_libraries(${test_network_uv} ${winsock2_src})
#target_link_libraries(${test_} ${winsock2_src})
endif()
if(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
set(posix_src libpthread.so libdl.so libm.so)
target_link_libraries(${test_network_uv} ${posix_src})
target_link_libraries(${test_utility} ${posix_src})
target_link_libraries(${test_auth} ${posix_src})
#target_link_libraries(${test_} ${posix_src})
find_package(X11 REQUIRED)
if(X11_FOUND)
target_link_libraries(${test_network_uv} ${X11_LIBRARIES})
target_link_libraries(${test_utility} ${X11_LIBRARIES})
target_link_libraries(${test_auth} ${X11_LIBRARIES})
#target_link_libraries(${test_} ${X11_LIBRARIES})
endif()
endif()
set(OpenGL_GL_PREFERENCE "LEGACY") # LEGACY (libGL.so) or GLVND (libOpenGL.so and libGLX.so)
find_package(OpenGL REQUIRED)
if(OPENGL_FOUND)
target_link_libraries(${test_network_uv} ${OPENGL_LIBRARIES})
target_link_libraries(${test_utility} ${OPENGL_LIBRARIES})
target_link_libraries(${test_auth} ${OPENGL_LIBRARIES})
#[[target_compile_definitions(${test_} PRIVATE DOKUN_USE_OPENGL)
target_link_libraries(${test_} ${OPENGL_LIBRARIES})]]
endif()
find_package(GLFW3 REQUIRED)
if(GLFW3_FOUND)
message(STATUS "Using GLFW3: ${GLFW3_LIBRARY}")
target_link_libraries(${test_network_uv} ${GLFW3_LIBRARY})
target_link_libraries(${test_utility} ${GLFW3_LIBRARY})
target_link_libraries(${test_auth} ${GLFW3_LIBRARY})
#[[target_compile_definitions(${test_} PRIVATE DOKUN_USE_GLFW) # already defined in libdokun-ui.a
#target_link_libraries(${test_} ${GLFW3_LIBRARY})]]
endif()

@ -0,0 +1,184 @@
// neroshop
#include "../include/neroshop.hpp"
using namespace neroshop;
lua_State * neroshop::lua_state = luaL_newstate();
static void register_user() {
db::Sqlite3 * database = db::Sqlite3::get_singleton();//std::unique_ptr<db::Sqlite3> database = std::make_unique<db::Sqlite3>();
if(!database->open("data.sqlite3")) {//(":memory:")) { // In-memory databases are temporary and written in RAM. They do not support WAL mode either
neroshop::print(SQLITE3_TAG "\033[91mSQLite::open failed");
}
//----------------------------
Wallet * wallet = new Wallet();
std::string wallet_name;
std::string wallet_pwd;
std::string wallet_confirm_pwd;
std::cout << "Please enter your desired wallet name:\n";
std::getline(std::cin, wallet_name);
if(wallet_name.empty()) wallet_name = "auth"; // default wallet name
std::cout << "Please enter your desired wallet password:\n";
std::getline(std::cin, wallet_pwd);
std::cout << "Please confirm your wallet password:\n";
std::getline(std::cin, wallet_confirm_pwd);
// Create a directory in home folder for wallets
// todo: make wallet path customizable by user
if(!std::filesystem::is_directory(NEROSHOP_DEFAULT_WALLET_PATH)) {
if(!std::filesystem::create_directories(NEROSHOP_DEFAULT_WALLET_PATH)) {
neroshop::print("FAILED TO MAKE WALLET DIRECTORY", 1);
return;
}
neroshop::print(std::string("\033[1;97mcreated directory \"") + NEROSHOP_DEFAULT_WALLET_PATH + "\"");
}
// Create a random wallet
wallet->create_random(wallet_pwd, wallet_confirm_pwd, NEROSHOP_DEFAULT_WALLET_PATH + "/" + wallet_name);
// Provide user with their mnemonic
std::cout << "Store these words safely. These 25 words are the key to your account. If you lose them, your account goes bye-bye:\n\033[1;36m";
std::cout << wallet->get_mnemonic() << "\033[0m" << std::endl;
// And their secret view and spend key pairs too ...
std::cout << "Secret view key: " << wallet->get_monero_wallet()->get_private_view_key() << std::endl;
std::cout << "Secret spend key: " << wallet->get_monero_wallet()->get_private_spend_key() << std::endl;
// Get SHA256 hash of the primary address
std::string primary_address = wallet->get_monero_wallet()->get_primary_address();
std::string user_auth_key;// = neroshop::algo::sha256(primary_address);
Validator::generate_sha256_hash(primary_address, user_auth_key); // temp
neroshop::print("Primary address: \033[1;33m" + primary_address + "\033[1;37m\nSHA256 hash: \033[1;32m" + user_auth_key);
// Store auth credentials in database
// todo: make this command (DB entry) a client request that the server must respond to and the consensus must agree with
database->execute_params("INSERT INTO users(key) VALUES($1)", { user_auth_key });
}
static bool auth_with_wallet_file() {
db::Sqlite3 * database = db::Sqlite3::get_singleton();//std::unique_ptr<db::Sqlite3> database = std::make_unique<db::Sqlite3>();
if(!database->open("data.sqlite3")) {//(":memory:")) { // In-memory databases are temporary and written in RAM. They do not support WAL mode either
neroshop::print(SQLITE3_TAG "\033[91mSQLite::open failed");
}
//----------------------------
Wallet * wallet = new Wallet();
// Initialize monero wallet with existing wallet file
std::string wallet_password;// = "supersecretpassword123"; // Apparently passwords are not used nor required for mnemonics. ONLY wallet files use passwords
//std::cout << "Please upload your wallet file:\n";
std::cout << "Please enter your wallet password:\n";
std::getline(std::cin, wallet_password);
// Upload wallet via file dialog
wallet->upload(true, wallet_password);
// Get the hash of the primary address
std::string primary_address = wallet->get_monero_wallet()->get_primary_address();
std::string user_auth_key;// = neroshop::algo::sha256(primary_address);
Validator::generate_sha256_hash(primary_address, user_auth_key); // temp
neroshop::print("Primary address: \033[1;33m" + primary_address + "\033[1;37m\nSHA256 hash: " + user_auth_key);
//$ echo -n "528qdm2pXnYYesCy5VdmBneWeaSZutEijFVAKjpVHeVd4unsCSM55CjgViQsK9WFNHK1eZgcCuZ3fRqYpzKDokqSKp4yp38" | sha256sum
// Check database to see if user key (hash of primary address) exists
bool user_key_found = database->get_integer_params("SELECT EXISTS(SELECT * FROM users WHERE key = $1)", { user_auth_key });
// If user key is not found in the database, then create one. This is like registering for an account
if(!user_key_found) {
// In reality, this function will return false if user key is not registered in the database
neroshop::print("user key not found in database. Please try again or register", 1);
return false;
}
// Save user information in memory
int user_id = database->get_integer_params("SELECT id FROM users WHERE key = $1", { user_auth_key });
// This number will scale as the user count grows
int min_digits = 15; // 15 digits = 100 trillionth place (000,000,000,000,000)
int precision = min_digits - std::min<int>(min_digits, std::to_string(user_id).size());
std::string formatted_user_id = std::string(precision, '0').append(std::to_string(user_id));
neroshop::print("Welcome back, user " + formatted_user_id, 4);
// Set user_id
// ...
return true;
}
static bool auth_with_seed() {
db::Sqlite3 * database = db::Sqlite3::get_singleton();//std::unique_ptr<db::Sqlite3> database = std::make_unique<db::Sqlite3>();
if(!database->open("data.sqlite3")) {//(":memory:")) { // In-memory databases are temporary and written in RAM. They do not support WAL mode either
neroshop::print(SQLITE3_TAG "\033[91mSQLite::open failed");
}
//----------------------------
Wallet * wallet = new Wallet();
// Initialize monero wallet with existing wallet mnemonic
std::string wallet_mnemonic;// = "hefty value later extra artistic firm radar yodel talent future fungal nutshell because sanity awesome nail unjustly rage unafraid cedar delayed thumbs comb custom sanity";
std::string wallet_password;// = "supersecretpassword123"; // Apparently passwords are not used nor required for mnemonics. ONLY wallet files use passwords
std::cout << "Please enter your wallet mnemonic:\n";
std::getline(std::cin, wallet_mnemonic);
// todo: allow user to specify a custom location for the wallet keyfile or use a default location
wallet->restore_from_mnemonic(wallet_mnemonic);
// Get the hash of the primary address
std::string primary_address = wallet->get_monero_wallet()->get_primary_address();
std::string user_auth_key;// = neroshop::algo::sha256(primary_address);
Validator::generate_sha256_hash(primary_address, user_auth_key); // temp
neroshop::print("Primary address: \033[1;33m" + primary_address + "\033[1;37m\nSHA256 hash: " + user_auth_key);
//$ echo -n "528qdm2pXnYYesCy5VdmBneWeaSZutEijFVAKjpVHeVd4unsCSM55CjgViQsK9WFNHK1eZgcCuZ3fRqYpzKDokqSKp4yp38" | sha256sum
// Check database to see if user key (hash of primary address) exists
bool user_key_found = database->get_integer_params("SELECT EXISTS(SELECT * FROM users WHERE key = $1)", { user_auth_key });
// If user key is not found in the database, then create one. This is like registering for an account
if(!user_key_found) {
// In reality, this function will return false if user key is not registered in the database
neroshop::print("user key not found in database. Please try again or register", 1);
return false;
}
// Save user information in memory
int user_id = database->get_integer_params("SELECT id FROM users WHERE key = $1", { user_auth_key });
// This number will scale as the user count grows
int min_digits = 15; // 15 digits = 100 trillionth place (000,000,000,000,000)
int precision = min_digits - std::min<int>(min_digits, std::to_string(user_id).size());
std::string formatted_user_id = std::string(precision, '0').append(std::to_string(user_id));
neroshop::print("Welcome back, user " + formatted_user_id, 4);
// Set user_id
// ...
return true;
}
static bool auth_with_keys() {
db::Sqlite3 * database = db::Sqlite3::get_singleton();//std::unique_ptr<db::Sqlite3> database = std::make_unique<db::Sqlite3>();
if(!database->open("data.sqlite3")) {//(":memory:")) { // In-memory databases are temporary and written in RAM. They do not support WAL mode either
neroshop::print(SQLITE3_TAG "\033[91mSQLite::open failed");
}
//----------------------------
Wallet * wallet = new Wallet();
// Initialize monero wallet with existing wallet mnemonic
std::string primary_address;
std::string secret_view_key;
std::string secret_spend_key;
std::cout << "Please enter your primary address:\n";
std::getline(std::cin, primary_address);
std::cout << "Please enter your secret view key:\n";
std::getline(std::cin, secret_view_key);
std::cout << "Please enter your secret spend key (optional):\n";
std::getline(std::cin, secret_spend_key);
// todo: allow user to specify a custom location for the wallet keyfile or use a default location
wallet->restore_from_keys(primary_address, secret_view_key, secret_spend_key);
// Get the hash of the primary address
std::string user_auth_key;// = neroshop::algo::sha256(primary_address);
Validator::generate_sha256_hash(primary_address, user_auth_key); // temp
neroshop::print("Primary address: \033[1;33m" + primary_address + "\033[1;37m\nSHA256 hash: " + user_auth_key);
//$ echo -n "528qdm2pXnYYesCy5VdmBneWeaSZutEijFVAKjpVHeVd4unsCSM55CjgViQsK9WFNHK1eZgcCuZ3fRqYpzKDokqSKp4yp38" | sha256sum
// Check database to see if user key (hash of primary address) exists
bool user_key_found = database->get_integer_params("SELECT EXISTS(SELECT * FROM users WHERE key = $1)", { user_auth_key });
// If user key is not found in the database, then create one. This is like registering for an account
if(!user_key_found) {
// In reality, this function will return false if user key is not registered in the database
neroshop::print("user key not found in database. Please try again or register", 1);
return false;
}
// Save user information in memory
int user_id = database->get_integer_params("SELECT id FROM users WHERE key = $1", { user_auth_key });
// This number will scale as the user count grows
int min_digits = 15; // 15 digits = 100 trillionth place (000,000,000,000,000)
int precision = min_digits - std::min<int>(min_digits, std::to_string(user_id).size());
std::string formatted_user_id = std::string(precision, '0').append(std::to_string(user_id));
neroshop::print("Welcome back, user " + formatted_user_id, 4);
// Set user_id
// ...
return true;
}
int main() {
//register_user();
//auth_with_seed();
//auth_with_wallet_file();
auth_with_keys();
return 0;
}

@ -4,9 +4,8 @@
#include "../include/neroshop.hpp"
using namespace neroshop;
// dokun-ui
#include <build.hpp>
#include DOKUN_HEADER
using namespace dokun;
/*#include <dokun_ui.hpp>
using namespace dokun;*/
lua_State * neroshop::lua_state = luaL_newstate(); // lua_state should be initialized by default
int main() {

@ -4,9 +4,8 @@
#include "../include/neroshop.hpp"
using namespace neroshop;
// dokun-ui
#include <build.hpp>
#include DOKUN_HEADER
using namespace dokun;
/*#include <dokun_ui.hpp>
using namespace dokun;*/
lua_State * neroshop::lua_state = luaL_newstate(); // lua_state should be initialized by default
int main() {

@ -5,8 +5,7 @@
#include "../include/server.hpp"
using namespace neroshop;
// dokun-ui
#include <build.hpp>
#include DOKUN_HEADER
#include <dokun_ui.hpp>
using namespace dokun;
namespace neroshop {

@ -2,8 +2,8 @@
#include "../include/neroshop.hpp"
using namespace neroshop;
// dokun-ui
#include <dokun_ui.hpp>
using namespace dokun;
/*#include <dokun_ui.hpp>
using namespace dokun;*/
lua_State * neroshop::lua_state = luaL_newstate(); // lua_state should be initialized by default

Binary file not shown.

@ -4,9 +4,8 @@
#include "../include/neroshop.hpp"
using namespace neroshop;
// dokun-ui
#include <build.hpp>
#include DOKUN_HEADER
using namespace dokun;
//#include <dokun_ui.hpp>
//using namespace dokun;
lua_State * neroshop::lua_state = luaL_newstate(); // lua_state should be initialized by default

Binary file not shown.

@ -0,0 +1,32 @@
#include <iostream>
#include <string>
// neroshop
#include "../include/neroshop.hpp"
using namespace neroshop;
// dokun-ui
/*#include <dokun_ui.hpp>
using namespace dokun;*/
#include "../include/util.hpp"
lua_State * neroshop::lua_state = luaL_newstate(); // lua_state should be initialized by default
int main() {
std::cout << neroshop::string::precision("1.123456789", 9) << std::endl;
std::cout << neroshop::string::lower("LOWER") << std::endl;
std::cout << neroshop::string::upper("upper") << std::endl;
#if defined(__cplusplus) && (__cplusplus >= 201402L) // 14
std::cout << "This project is using C++ 14\n";
#endif
#if defined(__cplusplus) && (__cplusplus >= 201703L) // 17
std::cout << "This project is using C++ 17\n";
#endif
std::cout << "current dir: " << neroshop::filesystem::current_directory() << std::endl;
std::cout << "mkdir result: " << neroshop::filesystem::make_directory("dude") << std::endl;
std::cout << "get_user result: " << neroshop::device::get_user() << std::endl;
//std::cout << "filename result: " << neroshop::filesystem::get_file_extension("player.png") << std::endl;
//-------------------------
return 0;
}
Loading…
Cancel
Save