fix: Windows identity, async address creation, mining UI, and chart artifacts
Windows identity: - Add VERSIONINFO resource (.rc) with ObsidianDragon file description - Embed application manifest for DPI awareness and shell identity - Patch libwinpthread/libpthread to remove competing VERSIONINFO - Set AppUserModelID and HWND property store to override Task Manager cache - Link patched pthread libs to eliminate "POSIX WinThreads" description Address creation (+New button): - Move z_getnewaddress/getnewaddress off UI thread to async worker - Inject new address into state immediately for instant UI selection - Trigger background refresh for balance updates Mining tab: - Add pool mining dropdown with saved URLs/workers and bookmarks - Add solo mining log panel from daemon output with chart/log toggle - Fix toggle button cursor (render after InputTextMultiline) - Auto-restart miner on pool config change - Migrate default pool URL to include stratum port Transactions: - Sort pending (0-conf) transactions to top of history - Fall back to timereceived when timestamp is missing Shutdown: - Replace blocking sleep_for calls with 100ms polling loops - Check shutting_down_ flag throughout daemon restart/bootstrap flows - Reduce daemon stop timeout from 30s to 10s Other: - Fix market chart fill artifact (single concave polygon vs per-segment quads) - Add bootstrap checksum verification state display - Rename daemon client identifier to ObsidianDragon
This commit is contained in:
@@ -493,6 +493,7 @@ void App::refreshData()
|
||||
if (tx.contains("category")) info.type = tx["category"].get<std::string>();
|
||||
if (tx.contains("amount")) info.amount = tx["amount"].get<double>();
|
||||
if (tx.contains("time")) info.timestamp = tx["time"].get<int64_t>();
|
||||
else if (tx.contains("timereceived")) info.timestamp = tx["timereceived"].get<int64_t>();
|
||||
if (tx.contains("confirmations")) info.confirmations = tx["confirmations"].get<int>();
|
||||
if (tx.contains("address")) info.address = tx["address"].get<std::string>();
|
||||
knownTxids.insert(info.txid);
|
||||
@@ -1408,25 +1409,61 @@ void App::clearBans()
|
||||
|
||||
void App::createNewZAddress(std::function<void(const std::string&)> callback)
|
||||
{
|
||||
if (!state_.connected || !rpc_) return;
|
||||
|
||||
rpc_->z_getNewAddress([this, callback](const json& result) {
|
||||
std::string addr = result.get<std::string>();
|
||||
addresses_dirty_ = true;
|
||||
refreshAddresses();
|
||||
if (callback) callback(addr);
|
||||
if (!state_.connected || !rpc_ || !worker_) return;
|
||||
|
||||
worker_->post([this, callback]() -> rpc::RPCWorker::MainCb {
|
||||
std::string addr;
|
||||
try {
|
||||
json result = rpc_->call("z_getnewaddress");
|
||||
addr = result.get<std::string>();
|
||||
} catch (const std::exception& e) {
|
||||
DEBUG_LOGF("z_getnewaddress error: %s\n", e.what());
|
||||
}
|
||||
return [this, callback, addr]() {
|
||||
if (!addr.empty()) {
|
||||
// Inject immediately so UI can select the address next frame
|
||||
AddressInfo info;
|
||||
info.address = addr;
|
||||
info.type = "shielded";
|
||||
info.balance = 0.0;
|
||||
state_.z_addresses.push_back(info);
|
||||
address_list_dirty_ = true;
|
||||
// Also trigger full refresh to get proper balances
|
||||
addresses_dirty_ = true;
|
||||
refreshAddresses();
|
||||
}
|
||||
if (callback) callback(addr);
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
void App::createNewTAddress(std::function<void(const std::string&)> callback)
|
||||
{
|
||||
if (!state_.connected || !rpc_) return;
|
||||
|
||||
rpc_->getNewAddress([this, callback](const json& result) {
|
||||
std::string addr = result.get<std::string>();
|
||||
addresses_dirty_ = true;
|
||||
refreshAddresses();
|
||||
if (callback) callback(addr);
|
||||
if (!state_.connected || !rpc_ || !worker_) return;
|
||||
|
||||
worker_->post([this, callback]() -> rpc::RPCWorker::MainCb {
|
||||
std::string addr;
|
||||
try {
|
||||
json result = rpc_->call("getnewaddress");
|
||||
addr = result.get<std::string>();
|
||||
} catch (const std::exception& e) {
|
||||
DEBUG_LOGF("getnewaddress error: %s\n", e.what());
|
||||
}
|
||||
return [this, callback, addr]() {
|
||||
if (!addr.empty()) {
|
||||
// Inject immediately so UI can select the address next frame
|
||||
AddressInfo info;
|
||||
info.address = addr;
|
||||
info.type = "transparent";
|
||||
info.balance = 0.0;
|
||||
state_.t_addresses.push_back(info);
|
||||
address_list_dirty_ = true;
|
||||
// Also trigger full refresh to get proper balances
|
||||
addresses_dirty_ = true;
|
||||
refreshAddresses();
|
||||
}
|
||||
if (callback) callback(addr);
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user