Add some functions to Backend

pull/64/head
larteyoh 1 year ago
parent db4f76da80
commit 0a83dfbad2

@ -3,4 +3,4 @@ There are many ways that you can contribute.
- Creating [pull requests](https://github.com/larteyoh/testshop/pulls) that solve issues found on the [Issues page](https://github.com/larteyoh/testshop/issues)
- Making a [donation](https://github.com/larteyoh/testshop#donations) to fund the development of the project
- Reporting any bugs or vulnerabilities found in the code as a GitHub [issue](https://github.com/larteyoh/testshop/issues)
- Sharing this project so more people can learn about its existence

@ -27,6 +27,8 @@ A distributed P2P (peer-to-peer) marketplace for [**Monero**](https://getmonero.
![Registration](https://github.com/larteyoh/testshop/blob/main/images/screenshots/Registration.png)
![CatalogGrid_Top](https://github.com/larteyoh/testshop/blob/main/images/screenshots/CatalogGrid_Top.png)
![CatalogGrid_Bottom](https://github.com/larteyoh/testshop/blob/main/images/screenshots/CatalogGrid_Bottom.png)
![SettingsDialog_Monero](https://github.com/larteyoh/testshop/blob/main/images/screenshots/SettingsDialog_Monero.png)
![HomePage](https://github.com/larteyoh/testshop/blob/main/images/screenshots/HomePage.png)
</details>

Binary file not shown.

After

Width:  |  Height:  |  Size: 112 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 233 KiB

@ -5,7 +5,7 @@ import QtQuick.Layouts 1.12
Item {
id: banner
implicitWidth: 300
implicitHeight: 150
implicitHeight: 300//150
default property alias content: view.contentData

@ -57,7 +57,12 @@ Item {
Layout.fillWidth: true
Layout.fillHeight: true
ScrollBar.vertical: ScrollBar { }
model: 50
model: {
let network_type = moneroNetworkTypeBox.displayText.toLowerCase()
return Script.getTableStrings("neroshop.monero.nodes." + network_type)
//Todo: replace Script.getTableStrings() with Backend.getNodeList() when app is released with mainnet
//return Backend.getNodeList() // <- This will only work for mainnet nodes
}//50
delegate: Item {
width: listView.width
height: 25
@ -89,7 +94,7 @@ Item {
Label {
id: nodeAddressLabel
Layout.fillWidth: true
text: "node.neroshop.org:38081"//:18081" // TODO create normal model
text: modelData//"node.neroshop.org:38081"//:18081"
color: (NeroshopComponents.Style.darkTheme) ? "#ffffff" : "#000000"
elide: Label.ElideRight
}
@ -98,7 +103,7 @@ Item {
id: nodeHeightLabel
Layout.minimumWidth: heightTitle.width//50
Layout.maximumWidth: heightTitle.width//50
text: "100500" // TODO create normal model
text: "1243821" // TODO create normal model
color: nodeAddressLabel.color
elide: Label.ElideRight
}

@ -14,6 +14,8 @@ import "." as NeroshopComponents
Popup {
id: settingsDialog
visible: false
modal: true//clip: true
closePolicy: Popup.CloseOnEscape
property bool hideTabText: false
property alias theme: themeBox
property alias currency: currencyBox
@ -21,14 +23,26 @@ Popup {
implicitWidth: 700
implicitHeight: 500
color: NeroshopComponents.Style.getColorsFromTheme()[2]
border.color: "white"
////border.color: "white"//; border.width: 1
radius: 8
//DragHandler { target: settingsDialog }
Rectangle {
id: titleBar
color: "#323232"
height: 40
height: 40//settingsDialog.topPadding
width: parent.width
anchors.left: parent.left
anchors.right: parent.right
radius: 6
// Rounded top corners??
Rectangle {
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
height: parent.height / 2
color: parent.color
}
Label {
text: "Settings"
@ -100,7 +114,7 @@ Popup {
}
TabButton {
text: (hideTabText) ? qsTr(FontAwesome.monero) : qsTr("%1 monerod").arg(FontAwesome.monero)//
text: (hideTabText) ? qsTr(FontAwesome.monero) : qsTr("Monero")//.arg(FontAwesome.monero)
width: implicitWidth + 20
onClicked: settingsStack.currentIndex = 1
display: AbstractButton.TextOnly
@ -317,8 +331,8 @@ Popup {
GridLayout {
id: moneroSettings
Layout.minimumWidth: parent.width - 10 // 10 is the scrollView's right margin
Layout.minimumHeight: 500 // Increase this value whenever more items are added inside the scrollview
//rowSpacing: // The default value is 5 but we'll set this later
////Layout.minimumHeight: 500 // Increase this value whenever more items are added inside the scrollview
/*Frame { //GroupBox {
@ -429,10 +443,49 @@ Item {
ColumnLayout {
anchors.fill: parent
// This will not be necessary once we switch to mainnet (permanently)
// Todo: remove this on release with mainnet
Rectangle {
Layout.alignment: Qt.AlignHCenter
Layout.preferredWidth: 500////Layout.fillWidth: true
Layout.preferredHeight: 50
radius: 3
color: "transparent"
//border.color: (NeroshopComponents.Style.darkTheme) ? "#ffffff" : "#000000"
RowLayout {
anchors.fill: parent
/*Label {
id: networkTypeLabel
text: qsTr("Network Type")
color: (NeroshopComponents.Style.darkTheme) ? "#ffffff" : "#000000"
Layout.alignment: Qt.AlignLeft
Layout.leftMargin: 5//25
}*/
ComboBox {
id: moneroNetworkTypeBox
model: ["mainnet", "stagenet", "testnet"]
currentIndex: model.indexOf(Script.getString("neroshop.monero.daemon.network_type").toLowerCase())
displayText: currentText
Layout.fillWidth: true////Layout.alignment: Qt.AlignRight; Layout.rightMargin: 5
onActivated: {
if(currentIndex == 0) moneroNodePortField.placeholderText = "18081"
if(currentIndex == 1) moneroNodePortField.placeholderText = "38081"
if(currentIndex == 2) moneroNodePortField.placeholderText = "28081"
displayText = currentText
// = displayText
}
}
}
}
Frame {
Layout.alignment: Qt.AlignHCenter
Layout.preferredWidth: 500
Layout.preferredHeight: 200//300////Layout.fillHeight: true
Layout.fillHeight: true////Layout.preferredHeight: 200//300
background: Rectangle {
radius: 3
color: "transparent"
@ -448,7 +501,7 @@ Item {
Layout.alignment: Qt.AlignHCenter
TextField {
id: customMoneroNodeIPField
id: moneroNodeIPField
Layout.preferredWidth: (moneroDaemonPortField.width * 3) - parent.spacing // Default row spacing is 5 so the width is reduced by 5
Layout.preferredHeight: 50
placeholderText: qsTr("Custom node IP address"); placeholderTextColor: (NeroshopComponents.Style.darkTheme) ? "#a9a9a9" : "#696969"
@ -463,10 +516,10 @@ Item {
}
TextField {
id: customMoneroNodePortField
id: moneroNodePortField
Layout.preferredWidth: (500 / 4)
Layout.preferredHeight: 50
placeholderText: qsTr("Custom node port number"); placeholderTextColor: (NeroshopComponents.Style.darkTheme) ? "#a9a9a9" : "#696969"
placeholderText: qsTr(Script.getString("neroshop.monero.daemon.port")); placeholderTextColor: (NeroshopComponents.Style.darkTheme) ? "#a9a9a9" : "#696969"
color: (NeroshopComponents.Style.darkTheme) ? "#ffffff" : "#000000"
selectByMouse: true
@ -695,11 +748,43 @@ Item {
radius: 3
}
}*/
/*// manage daemon buttons: stop daemon, start daemon, etc.
// manage daemon buttons: stop daemon, start daemon, etc.
RowLayout {
Layout.alignment: Qt.AlignHCenter
Layout.preferredWidth: 500
Button {
width: parent.width / visibleChildren.length//children.length
height: contentHeight + 20
text: qsTr("Launch daemon")
background: Rectangle {
color: NeroshopComponents.Style.moneroOrangeColor
radius: 6
}
contentItem: Text {
text: parent.text
color: "#ffffff"
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
onClicked: {
Wallet.daemonExecute(Backend.urlToLocalFile(monerodLocationField.text),
moneroDaemonIPField.placeholderText,
moneroDaemonPortField.placeholderText,
confirmExternalBindSwitch.checked,
restrictedRpcSwitch.checked,
(moneroDataDirField.text.length < 1) ? Backend.urlToLocalFile(moneroDataDirField.placeholderText) : Backend.urlToLocalFile(moneroDataDirField.text),
"stagenet", // change this later
0, // placeholder restore_height
);
if(!Wallet.isGenerated()) return; // no need for this if we are only launching the monerod executable
Wallet.daemonConnect(moneroDaemonIPField.placeholderText, moneroDaemonPortField.placeholderText)
}
}
}
//Button {
//id:saveSettingsButton
//}
*/
//}
} // ColumnLayout
FileDialog {
id: moneroDaemonFileDialog

@ -71,7 +71,6 @@ ApplicationWindow {
NeroshopComponents.SettingsDialog {
id: settingsDialog
anchors.centerIn: Overlay.overlay//parent: Overlay.overlay; anchors.centerIn: parent
closePolicy: Popup.CloseOnEscape
dim: true
enter: Transition {
NumberAnimation { property: "opacity"; from: 0.0; to: 1.0 }

@ -85,7 +85,12 @@ Page {
// Make sure username is not taken (requires a database check)
// ...
// Register hash of the wallet primary key to the database
// ...
let register_result = Backend.registerUser(Wallet.getPrimaryAddress(), optNameField.text)
if(!register_result [0] ) {
messageBox.text = register_result [1];
messageBox.open()
return; // exit function and do not proceed any further
}
// Switch to HomePage
pageLoader.source = "HomePage.qml"//stack.push(home_page)
console.log("Primary address: ", Wallet.getPrimaryAddress())

@ -109,7 +109,7 @@ sqlite3 * neroshop::db::Sqlite3::get_handle() const {
neroshop::db::Sqlite3 * neroshop::db::Sqlite3::get_database() {
std::string database_path = NEROSHOP_DEFAULT_DATABASE_PATH;
std::string database_file = "data.sqlite3";
static neroshop::db::Sqlite3 database_obj { database_path + "/" + database_file };
static neroshop::db::Sqlite3 database_obj { database_file };////static neroshop::db::Sqlite3 database_obj { database_path + "/" + database_file };
return &database_obj;
}
////////////////////
@ -215,7 +215,7 @@ std::string neroshop::db::Sqlite3::get_text_params(const std::string& command, c
// Check the type of the statement's return value
int column_type = sqlite3_column_type(statement, 0);
if(column_type != SQLITE_TEXT) {
neroshop::print("sqlite3_column_type: invalid column type", 1);
////neroshop::print("sqlite3_column_type: invalid column type", 1);
sqlite3_finalize(statement);
return "";
}

@ -357,13 +357,14 @@ void neroshop::Wallet::on_balances_changed(uint64_t new_balance, uint64_t new_un
// daemon
////////////////////
// open the daemon before opening the wallet
void neroshop::Wallet::daemon_open(const std::string& ip, const std::string& port, bool confirm_external_bind, bool restricted_rpc, bool remote, std::string data_dir, std::string network_type, unsigned int restore_height)
void neroshop::Wallet::daemon_open(const std::string& daemon_dir, const std::string& ip, const std::string& port, bool confirm_external_bind, bool restricted_rpc, std::string data_dir, std::string network_type, unsigned int restore_height)
{
// Todo: use QProcess to launch monerod
// search for monero daemon (that is packaged with neroshop executable)
std::string daemon_dir = static_cast<std::string>(std::filesystem::current_path()) + "/external/monero-cpp/external/monero-project/build/release/bin/monerod";
// connect to a remote node
// either neroshop's daemon does not exist or remote is set to true
if(!std::filesystem::is_regular_file(daemon_dir) || remote == true) { std::cout << "\033[1;90;49m" << "connecting to remote node - " << (ip + ":" + port) << "\033[0m" << std::endl; return;} // exit function
////std::string daemon_dir = static_cast<std::string>(std::filesystem::current_path()) + "/external/monero-cpp/external/monero-project/build/release/bin/monerod";
std::cout << "daemon_dir: " << daemon_dir << std::endl;
// either neroshop's daemon does not exist
if(!std::filesystem::is_regular_file(daemon_dir)) { std::cout << "monerod not found. Please set the path or use a remote node instead"/*"\033[1;90;49m" << "connecting to remote node - " << (ip + ":" + port) << "\033[0m"*/ << "\n"; return;} // exit function
// check if there is another monerod process running in the background
int monerod = Process::get_process_by_name("monerod");//(argv[1]);//cout << "pid: " << monerod << endl;
if(monerod != -1) { std::cout << "\033[1;90;49m" << "monerod is running (ID:" << monerod << ")\033[0m" << std::endl; return;} // daemon that was previously running in the background // exit function

@ -65,7 +65,7 @@ public:
void on_output_received(const monero_output_wallet& output);
////void on_output_spent (const monero_output_wallet &output);
// daemon or node-related functions
void daemon_open(const std::string& ip, const std::string& port, bool confirm_external_bind = false, bool restricted_rpc = true, bool remote = false, std::string data_dir = std::string("/home/") + neroshop::device::get_user() + std::string("/.bitmonero")/*""*/, std::string network_type = "stagenet", unsigned int restore_height = 0);
void daemon_open(const std::string& daemon_dir, const std::string& ip, const std::string& port, bool confirm_external_bind = false, bool restricted_rpc = true, std::string data_dir = std::string("/home/") + neroshop::device::get_user() + std::string("/.bitmonero")/*""*/, std::string network_type = "stagenet", unsigned int restore_height = 0);
bool daemon_connect_local(const std::string& ip, const std::string& port);
void daemon_connect_remote(const std::string& ip, const std::string& port);
void daemon_close();

@ -60,11 +60,11 @@ void neroshop::Backend::initializeDatabase() {
// table users
if(!database->table_exists("users")) {
database->execute("CREATE TABLE users(id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT);");
database->execute("ALTER TABLE users ADD COLUMN name TEXT;"); // optional display name
database->execute("ALTER TABLE users ADD COLUMN name TEXT;");// DEFAULT '' NOT NULL;"); // optional display name
database->execute("ALTER TABLE users ADD COLUMN monero_address TEXT;"); // verify_key - public_key used for logins and for verification of signatures
database->execute("ALTER TABLE users ADD COLUMN public_key TEXT;"); // encrypt_key - public_key used for encryption of messages
database->execute("ALTER TABLE users ADD COLUMN public_key TEXT DEFAULT NULL;"); // encrypt_key - public_key used for encryption of messages
database->execute("CREATE UNIQUE INDEX index_user_names ON users (name);"); // 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_user_names ON users (name);"); // Will not allow empty strings :(
database->execute("CREATE UNIQUE INDEX index_user_auth_keys ON users (monero_address);");
database->execute("CREATE UNIQUE INDEX index_public_keys ON users (public_key);");
}
@ -247,7 +247,7 @@ std::string neroshop::Backend::getDatabaseHash() {
QVariantList neroshop::Backend::getCategoryList() const {
// Do some database reading to fetch each category row (database reads do not require consensus)
neroshop::db::Sqlite3 * database = neroshop::db::Sqlite3::get_database();
if(!database->get_handle()) throw std::runtime_error("database is not connected");
if(!database) throw std::runtime_error("database is NULL");
sqlite3_stmt * stmt = nullptr;
// Prepare (compile) statement
if(sqlite3_prepare_v2(database->get_handle(), "SELECT * FROM categories;", -1, &stmt, nullptr) != SQLITE_OK) {
@ -281,21 +281,237 @@ QVariantList neroshop::Backend::getCategoryList() const {
return category_list;
}
// Todo: fetch monero nodes from monero.fail // Each node will represent a QML object (QVariantMap) with properties: address, height, and status
Q_INVOKABLE QVariantList neroshop::Backend::getMoneroNodeList() const {
QVariantList node_list;
return node_list;
}
void neroshop::Backend::registerUser() {
QVariantList neroshop::Backend::validateDisplayName(const QString& display_name) const {
// username (will appear only in lower-case letters within the app)
std::string username = display_name.toStdString();
// Empty display names are acceptable
if(display_name.isEmpty()) return { true, "" };
// If display name is set, make sure it is at least 2 characters short (min_user_length=2)
unsigned int min_user_length = 2;
if(username.length() < min_user_length) {
std::string message = "Your username must be at least " + std::to_string(min_user_length) + " characters in length";
return { false, QString::fromStdString(message) };
}
// make sure username is at least 30 characters long (max_user_length=30)
unsigned int max_user_length = 30; // what if a company has a long name? :o // also consider the textbox's max-length
if(username.length() > max_user_length) {
std::string message = "Your username must not exceed " + std::to_string(max_user_length) + " characters in length";
return { false, QString::fromStdString(message) };
}
for(int i = 0; i < username.length(); i++)
{
// make sure username does not contain any spaces //std::cout << username[i] << " - char\n";
if(isspace(username[i])) {
std::string message = "Your username cannot contain any spaces";
return { false, QString::fromStdString(message) };
}
// make sure username can only contain letters, numbers, and these specific symbols: a hyphen, underscore, and period (-,_,.) //https://stackoverflow.com/questions/39819830/what-are-the-allowed-character-in-snapchat-username#comment97381763_41959421
// symbols like @,#,$,etc. are invalid
if(!isalnum(username[i])) {
if(username[i] != '-'){
if(username[i] != '_'){
if(username[i] != '.'){
std::string message = "Your username cannot contain any symbols except (-, _, .)";// + username[i];
return { false, QString::fromStdString(message) };
}}}
}
}
// make sure username begins with a letter (username cannot start with a symbol or number)
char first_char = username.at(username.find_first_of(username));
if(!isalpha(first_char)) {
std::string message = "Your username must begin with a letter";// + first_char;
return { false, QString::fromStdString(message) };
}
// make sure username does not end with a symbol (username can end with a number, but NOT with a symbol)
char last_char = username.at(username.find_last_of(username));
if(!isalnum(last_char)) { //if(last_char != '_') { // underscore allowed at end of username? :o
std::string message = "Your username must end with a letter or number";// + last_char;
return { false, QString::fromStdString(message) };
}
// the name guest is reserved for guests only, so it cannot be used by any other user
if(neroshop::string::lower(username) == "guest") {
std::string message = "The name \"Guest\" is reserved for guests ONLY";
return { false, QString::fromStdString(message) };
}
// Check database to see if display name is available
auto name_check_result = checkDisplayName(display_name);
if(!name_check_result[0].toBool()) {////if(!Validator::validate_display_name(display_name.toStdString())) return false;
bool boolean_result = name_check_result[0].toBool();
QString message_result = name_check_result[1].toString();
return { boolean_result, message_result };
}
return { true, "" };
}
QVariantList neroshop::Backend::checkDisplayName(const QString& display_name) const {
neroshop::db::Sqlite3 * database = neroshop::db::Sqlite3::get_database();
if(!database->table_exists("users")) { return {true, ""}; }
std::string name = database->get_text_params("SELECT name FROM users WHERE name = $1;", { display_name.toLower().toStdString() });
if(name.empty()) return { true, "Display name is available for use" };// Name is not taken which means that the user is good to go!
// Empty display names are acceptable
bool is_name_empty = display_name.isEmpty();
if(is_name_empty) return { true, "No display name set" };
// Note: names are stored inside the database as lowercase strings
if(name == display_name.toLower().toStdString()) {
return { false, "This username is already taken" };////result_list << false << QString("This username is already taken");return result_list;
}
return { true, "" };
}
void neroshop::Backend::loginWithWalletFile() {
QVariantList neroshop::Backend::registerUser(const QString& primary_address/*gui::Wallet* wallet*/, const QString& display_name) {
neroshop::db::Sqlite3 * database = neroshop::db::Sqlite3::get_database();
if(!database) throw std::runtime_error("database is NULL");
// Validate display name
auto name_validation_result = validateDisplayName(display_name);
if(!name_validation_result[0].toBool()) {
bool boolean_result = name_validation_result[0].toBool();
QString message_result = name_validation_result[1].toString();
return { boolean_result, message_result };
}
// Get wallet primary address and check its validity
////std::string primary_address = wallet->get_monero_wallet()->get_primary_address();//neroshop::print("Primary address: \033[1;33m" + primary_address.toStdString() + "\033[1;37m\n");
if(!monero_utils::is_valid_address(primary_address.toStdString(), monero_network_type::STAGENET)) {//network_type)) {
return { false, "Invalid monero address" };
}
// Store login credentials in database
// Todo: make this command (DB entry) a client request that the server must respond to and the consensus must agree with
// Note: Multiple users cannot have the same display_name. Each display_name must be unique!
int user_id = database->get_integer_params("INSERT INTO users(name, monero_address) VALUES($1, $2) RETURNING id;", { display_name.toLower().toStdString(), primary_address.toStdString() });
if(user_id == 0) { return { false, "Account registration failed (due to database error)" }; }
// Display registration message
bool is_name_empty = display_name.isEmpty();
neroshop::print(((!is_name_empty) ? "Welcome to neroshop, " : "Welcome to neroshop") + display_name.toStdString(), 4);
return { true, "" };
}
void neroshop::Backend::loginWithWalletFile() {
/*
neroshop::db::Sqlite3 * database = neroshop::db::Sqlite3::get_database();
if(!database) throw std::runtime_error("database is NULL");
//----------------------------
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;
*/
}
void neroshop::Backend::loginWithMnemonic() {
/*
neroshop::db::Sqlite3 * database = neroshop::db::Sqlite3::get_database();
if(!database) throw std::runtime_error("database is NULL");
//----------------------------
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::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;
*/
}
void neroshop::Backend::loginWithKeys() {
/*
neroshop::db::Sqlite3 * database = neroshop::db::Sqlite3::get_database();
if(!database) throw std::runtime_error("database is NULL");
//----------------------------
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;
*/
}
void neroshop::Backend::loginWithHW() {

@ -36,7 +36,12 @@ public:
Q_INVOKABLE QVariantList getCategoryList() const;
//Q_INVOKABLE QStringList getSubCategoryList(int category_id);
Q_INVOKABLE void registerUser();
Q_INVOKABLE QVariantList getMoneroNodeList() const;
QVariantList validateDisplayName(const QString& display_name) const; // Validates display name based on regex requirements
QVariantList checkDisplayName(const QString& display_name) const; // Checks database for display name availability
Q_INVOKABLE QVariantList/*bool*/ registerUser(const QString& primary_address/*gui::Wallet* wallet*/, const QString& display_name);
Q_INVOKABLE void loginWithWalletFile();
Q_INVOKABLE void loginWithMnemonic();
Q_INVOKABLE void loginWithKeys();

@ -82,11 +82,11 @@ int main(int argc, char *argv[]) {
throw std::runtime_error("Failed to create neroshop datadir");
return 1;
}
}
////qmlRegisterType<neroshop::gui::Wallet/*WalletProxy*/>("neroshop.Wallet", 1, 0, "Wallet"); // Usage: import neroshop.Wallet ... Wallet { id: wallet }
}
// we can also register an instance of a class instead of the class itself
gui::Wallet wallet;
engine.rootContext()->setContextProperty("Wallet", &wallet);//new WalletProxy());//qmlRegisterUncreatableType<WalletProxy>("neroshop.Wallet", 1, 0, "Wallet", "Wallet cannot be instantiated directly.");
engine.rootContext()->setContextProperty("Wallet", &wallet);//new WalletProxy());//qmlRegisterUncreatableType<WalletProxy>("neroshop.Wallet", 1, 0, "Wallet", "Wallet cannot be instantiated directly.");//qmlRegisterType<WalletProxy>("neroshop.Wallet", 1, 0, "Wallet"); // Usage: import neroshop.Wallet ... Wallet { id: wallet }
//qRegisterMetaType<gui::Wallet*>("const gui::Wallet*");
// register script
engine.rootContext()->setContextProperty("Script", new ScriptProxy());//qmlRegisterType<ScriptProxy>("neroshop.Script", 1, 0, "Script");
// register backend

@ -128,8 +128,8 @@ double neroshop::gui::Wallet::getBalanceUnlocked(unsigned int account_index, uns
}
void neroshop::gui::Wallet::daemonExecute(const QString& ip, const QString& port, bool confirm_external_bind, bool restricted_rpc, bool remote, QString data_dir, QString network_type, unsigned int restore_height) {//const {
wallet->daemon_open(ip.toStdString(), port.toStdString(), confirm_external_bind, restricted_rpc, remote, data_dir.toStdString(), network_type.toStdString(), restore_height);
void neroshop::gui::Wallet::daemonExecute(const QString& daemon_dir, const QString& ip, const QString& port, bool confirm_external_bind, bool restricted_rpc, QString data_dir, QString network_type, unsigned int restore_height) {//const {
wallet->daemon_open(daemon_dir.toStdString(), ip.toStdString(), port.toStdString(), confirm_external_bind, restricted_rpc, data_dir.toStdString(), network_type.toStdString(), restore_height);
}
void neroshop::gui::Wallet::daemonConnect(const QString& ip, const QString& port) {

@ -56,7 +56,7 @@ public:
Q_INVOKABLE neroshop::Wallet * getWallet() const;
Q_INVOKABLE void setWallet(const neroshop::Wallet* wallet/*const neroshop::Wallet& wallet*/) {}//const { /*this->wallet = const_cast<neroshop::Wallet*>(wallet);*//*this->wallet = &const_cast<neroshop::Wallet&>(wallet);*//*emit wallet_changed(status);*/ }
//Q_INVOKABLE <type> <function_name>() const {}
Q_INVOKABLE void daemonExecute(const QString& ip, const QString& port, bool confirm_external_bind, bool restricted_rpc, bool remote, QString data_dir, QString network_type, unsigned int restore_height);// const;
Q_INVOKABLE void daemonExecute(const QString& daemon_dir, const QString& ip, const QString& port, bool confirm_external_bind, bool restricted_rpc, QString data_dir, QString network_type, unsigned int restore_height);// const;
Q_INVOKABLE bool isGenerated() const;
Q_INVOKABLE bool fileExists(const QString& filename) const;
public slots:

Loading…
Cancel
Save