ObsidianDragon - DragonX ImGui Wallet

Full-node GUI wallet for DragonX cryptocurrency.
Built with Dear ImGui, SDL3, and OpenGL3/DX11.

Features:
- Send/receive shielded and transparent transactions
- Autoshield with merged transaction display
- Built-in CPU mining (xmrig)
- Peer management and network monitoring
- Wallet encryption with PIN lock
- QR code generation for receive addresses
- Transaction history with pagination
- Console for direct RPC commands
- Cross-platform (Linux, Windows)
This commit is contained in:
2026-02-26 02:31:52 -06:00
commit 3aee55b49c
306 changed files with 177789 additions and 0 deletions

184
src/data/address_book.cpp Normal file
View File

@@ -0,0 +1,184 @@
// DragonX Wallet - ImGui Edition
// Copyright 2024-2026 The Hush Developers
// Released under the GPLv3
#include "address_book.h"
#include <nlohmann/json.hpp>
#include <fstream>
#include <filesystem>
#include "../util/logger.h"
#ifdef _WIN32
#include <shlobj.h>
#else
#include <pwd.h>
#include <unistd.h>
#endif
namespace fs = std::filesystem;
using json = nlohmann::json;
namespace dragonx {
namespace data {
AddressBook::AddressBook() = default;
AddressBook::~AddressBook() = default;
std::string AddressBook::getDefaultPath()
{
#ifdef _WIN32
char path[MAX_PATH];
if (SUCCEEDED(SHGetFolderPathA(NULL, CSIDL_APPDATA, NULL, 0, path))) {
std::string dir = std::string(path) + "\\ObsidianDragon";
fs::create_directories(dir);
return dir + "\\addressbook.json";
}
return "addressbook.json";
#elif defined(__APPLE__)
const char* home = getenv("HOME");
if (!home) {
struct passwd* pw = getpwuid(getuid());
home = pw->pw_dir;
}
std::string dir = std::string(home) + "/Library/Application Support/ObsidianDragon";
fs::create_directories(dir);
return dir + "/addressbook.json";
#else
const char* home = getenv("HOME");
if (!home) {
struct passwd* pw = getpwuid(getuid());
home = pw->pw_dir;
}
std::string dir = std::string(home) + "/.config/ObsidianDragon";
fs::create_directories(dir);
return dir + "/addressbook.json";
#endif
}
bool AddressBook::load()
{
file_path_ = getDefaultPath();
std::ifstream file(file_path_);
if (!file.is_open()) {
// No file yet - that's OK
return true;
}
try {
json j;
file >> j;
entries_.clear();
if (j.contains("entries") && j["entries"].is_array()) {
for (const auto& entry : j["entries"]) {
AddressBookEntry e;
e.label = entry.value("label", "");
e.address = entry.value("address", "");
e.notes = entry.value("notes", "");
if (!e.address.empty()) {
entries_.push_back(e);
}
}
}
DEBUG_LOGF("Address book loaded: %zu entries\n", entries_.size());
return true;
} catch (const std::exception& e) {
DEBUG_LOGF("Error loading address book: %s\n", e.what());
return false;
}
}
bool AddressBook::save()
{
if (file_path_.empty()) {
file_path_ = getDefaultPath();
}
try {
json j;
j["entries"] = json::array();
for (const auto& entry : entries_) {
json e;
e["label"] = entry.label;
e["address"] = entry.address;
e["notes"] = entry.notes;
j["entries"].push_back(e);
}
// Ensure directory exists
fs::path p(file_path_);
fs::create_directories(p.parent_path());
std::ofstream file(file_path_);
if (!file.is_open()) {
DEBUG_LOGF("Could not open address book for writing: %s\n", file_path_.c_str());
return false;
}
file << j.dump(2);
DEBUG_LOGF("Address book saved: %zu entries\n", entries_.size());
return true;
} catch (const std::exception& e) {
DEBUG_LOGF("Error saving address book: %s\n", e.what());
return false;
}
}
bool AddressBook::addEntry(const AddressBookEntry& entry)
{
// Check for duplicate address
if (findByAddress(entry.address) >= 0) {
return false;
}
entries_.push_back(entry);
return save();
}
bool AddressBook::updateEntry(size_t index, const AddressBookEntry& entry)
{
if (index >= entries_.size()) {
return false;
}
// Check for duplicate address (excluding current entry)
int existing = findByAddress(entry.address);
if (existing >= 0 && static_cast<size_t>(existing) != index) {
return false;
}
entries_[index] = entry;
return save();
}
bool AddressBook::removeEntry(size_t index)
{
if (index >= entries_.size()) {
return false;
}
entries_.erase(entries_.begin() + index);
return save();
}
int AddressBook::findByAddress(const std::string& address) const
{
for (size_t i = 0; i < entries_.size(); i++) {
if (entries_[i].address == address) {
return static_cast<int>(i);
}
}
return -1;
}
} // namespace data
} // namespace dragonx