commit 6c331f161f0e04b4a8796b371b220bd5524808b0 Author: Khushboo Mehta Date: Wed Feb 11 20:39:32 2026 +0100 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..de7c99f --- /dev/null +++ b/.gitignore @@ -0,0 +1,12 @@ +.DS_Store +build/ +result +*.dylib +*.so +*.dll +*.a +CMakeCache.txt +CMakeFiles/ +*.cmake +generated_code/ +db/ diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..f17745d --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,271 @@ +cmake_minimum_required(VERSION 3.16) +project(BlockchainUIPlugin VERSION 1.0.0 LANGUAGES CXX) + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_AUTOMOC ON) +set(CMAKE_AUTORCC ON) +set(CMAKE_AUTOUIC ON) + +# Allow override from environment or command line +if(NOT DEFINED LOGOS_LIBLOGOS_ROOT) + set(_parent_liblogos "${CMAKE_SOURCE_DIR}/../logos-liblogos") + set(_use_vendor ${LOGOS_BLOCKCHAIN_UI_USE_VENDOR}) + if(NOT _use_vendor) + if(NOT EXISTS "${_parent_liblogos}/interface.h") + set(_use_vendor ON) + endif() + endif() + if(_use_vendor) + set(LOGOS_LIBLOGOS_ROOT "${CMAKE_SOURCE_DIR}/vendor/logos-liblogos") + else() + set(LOGOS_LIBLOGOS_ROOT "${_parent_liblogos}") + endif() +endif() + +if(NOT DEFINED LOGOS_CPP_SDK_ROOT) + set(_parent_cpp_sdk "${CMAKE_SOURCE_DIR}/../logos-cpp-sdk") + set(_use_vendor ${LOGOS_BLOCKCHAIN_UI_USE_VENDOR}) + if(NOT _use_vendor) + if(NOT EXISTS "${_parent_cpp_sdk}/cpp/logos_api.h") + set(_use_vendor ON) + endif() + endif() + if(_use_vendor) + set(LOGOS_CPP_SDK_ROOT "${CMAKE_SOURCE_DIR}/vendor/logos-cpp-sdk") + else() + set(LOGOS_CPP_SDK_ROOT "${_parent_cpp_sdk}") + endif() +endif() + +# Check if dependencies are available (support both source and installed layouts) +set(_liblogos_found FALSE) +if(EXISTS "${LOGOS_LIBLOGOS_ROOT}/interface.h") + set(_liblogos_found TRUE) + set(_liblogos_is_source TRUE) +elseif(EXISTS "${LOGOS_LIBLOGOS_ROOT}/include/interface.h") + set(_liblogos_found TRUE) + set(_liblogos_is_source FALSE) +endif() + +set(_cpp_sdk_found FALSE) +if(EXISTS "${LOGOS_CPP_SDK_ROOT}/cpp/logos_api.h") + set(_cpp_sdk_found TRUE) + set(_cpp_sdk_is_source TRUE) +elseif(EXISTS "${LOGOS_CPP_SDK_ROOT}/include/cpp/logos_api.h") + set(_cpp_sdk_found TRUE) + set(_cpp_sdk_is_source FALSE) +endif() + +if(NOT _liblogos_found) + message(FATAL_ERROR "logos-liblogos not found at ${LOGOS_LIBLOGOS_ROOT}. " + "Set LOGOS_LIBLOGOS_ROOT or run git submodule update --init --recursive.") +endif() + +if(NOT _cpp_sdk_found) + message(FATAL_ERROR "logos-cpp-sdk not found at ${LOGOS_CPP_SDK_ROOT}. " + "Set LOGOS_CPP_SDK_ROOT or run git submodule update --init --recursive.") +endif() + +# Find Qt packages +find_package(Qt6 REQUIRED COMPONENTS Core Widgets RemoteObjects Quick QuickWidgets) + +# Get the real path to handle symlinks correctly +get_filename_component(REAL_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}" REALPATH) + +# Try to find the component-interfaces package first +find_package(component-interfaces QUIET) + +# If not found, use the local interfaces folder +if(NOT component-interfaces_FOUND) + # Include the local interfaces directory + include_directories(${CMAKE_CURRENT_SOURCE_DIR}/interfaces) + + # Create a component-interfaces library + add_library(component-interfaces INTERFACE) + target_include_directories(component-interfaces INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/interfaces) +endif() + +# Source files +set(SOURCES + src/BlockchainPlugin.cpp + src/BlockchainPlugin.h + src/BlockchainBackend.cpp + src/BlockchainBackend.h + src/blockchain_resources.qrc +) + +# Add SDK sources (only if source layout, installed layout uses the library) +if(_cpp_sdk_is_source) + list(APPEND SOURCES + ${LOGOS_CPP_SDK_ROOT}/cpp/logos_api.cpp + ${LOGOS_CPP_SDK_ROOT}/cpp/logos_api.h + ${LOGOS_CPP_SDK_ROOT}/cpp/logos_api_client.cpp + ${LOGOS_CPP_SDK_ROOT}/cpp/logos_api_client.h + ${LOGOS_CPP_SDK_ROOT}/cpp/logos_api_consumer.cpp + ${LOGOS_CPP_SDK_ROOT}/cpp/logos_api_consumer.h + ${LOGOS_CPP_SDK_ROOT}/cpp/logos_api_provider.cpp + ${LOGOS_CPP_SDK_ROOT}/cpp/logos_api_provider.h + ${LOGOS_CPP_SDK_ROOT}/cpp/token_manager.cpp + ${LOGOS_CPP_SDK_ROOT}/cpp/token_manager.h + ${LOGOS_CPP_SDK_ROOT}/cpp/module_proxy.cpp + ${LOGOS_CPP_SDK_ROOT}/cpp/module_proxy.h + ) +endif() + +# Run Logos C++ generator on metadata before compilation (only for source layout) +set(METADATA_JSON "${CMAKE_CURRENT_SOURCE_DIR}/metadata.json") + +# Only run generator for source layout - nix builds already have generated files +if(_cpp_sdk_is_source) + # Source layout: build and run the generator + # Generate into build directory + set(PLUGINS_OUTPUT_DIR "${CMAKE_BINARY_DIR}/generated_code") + set(CPP_GENERATOR_BUILD_DIR "${LOGOS_CPP_SDK_ROOT}/../build/cpp-generator") + set(CPP_GENERATOR "${CPP_GENERATOR_BUILD_DIR}/bin/logos-cpp-generator") + + if(NOT TARGET cpp_generator_build) + add_custom_target(cpp_generator_build + COMMAND bash "${LOGOS_CPP_SDK_ROOT}/cpp-generator/compile.sh" + WORKING_DIRECTORY "${LOGOS_CPP_SDK_ROOT}/.." + COMMENT "Building logos-cpp-generator via ${LOGOS_CPP_SDK_ROOT}/cpp-generator/compile.sh" + VERBATIM + ) + endif() + + add_custom_target(run_cpp_generator_blockchain_ui + COMMAND "${CPP_GENERATOR}" --metadata "${METADATA_JSON}" --general-only --output-dir "${PLUGINS_OUTPUT_DIR}" + WORKING_DIRECTORY "${LOGOS_CPP_SDK_ROOT}/.." + COMMENT "Running logos-cpp-generator on ${METADATA_JSON} with output-dir ${PLUGINS_OUTPUT_DIR}" + VERBATIM + ) + add_dependencies(run_cpp_generator_blockchain_ui cpp_generator_build) + + # Add generated logos_sdk.cpp - will be generated by run_cpp_generator_blockchain_ui + list(APPEND SOURCES ${PLUGINS_OUTPUT_DIR}/logos_sdk.cpp) + # Mark as generated so CMake knows to wait for it + set_source_files_properties( + ${PLUGINS_OUTPUT_DIR}/logos_sdk.cpp + PROPERTIES GENERATED TRUE + ) +else() + # Installed/nix layout: lib.nix preConfigure populates generated_code before CMake. + # May be overridden by -DPLUGINS_OUTPUT_DIR= when source tree is read-only (e.g. Nix sandbox). + set(PLUGINS_OUTPUT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/generated_code" CACHE PATH "Generated code directory (nix layout)") + list(APPEND SOURCES ${PLUGINS_OUTPUT_DIR}/include/logos_sdk.cpp) +endif() + +# Create the plugin library +add_library(blockchain_ui SHARED ${SOURCES}) + +# Set output name without lib prefix and with correct name for generator +set_target_properties(blockchain_ui PROPERTIES + PREFIX "" + OUTPUT_NAME "blockchain_ui" +) + +# Ensure generator runs before building the plugin (only for source layout) +if(_cpp_sdk_is_source) + add_dependencies(blockchain_ui run_cpp_generator_blockchain_ui) +endif() + +# Include directories +target_include_directories(blockchain_ui PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/src + ${CMAKE_CURRENT_BINARY_DIR} + ${PLUGINS_OUTPUT_DIR} +) + +# Add include directories based on layout type +if(_liblogos_is_source) + target_include_directories(blockchain_ui PRIVATE ${LOGOS_LIBLOGOS_ROOT}) +else() + target_include_directories(blockchain_ui PRIVATE ${LOGOS_LIBLOGOS_ROOT}/include) +endif() + +if(_cpp_sdk_is_source) + target_include_directories(blockchain_ui PRIVATE + ${LOGOS_CPP_SDK_ROOT}/cpp + ${LOGOS_CPP_SDK_ROOT}/cpp/generated + ) +else() + # For nix builds, also include the include subdirectory + # (lib.nix moves header files to ./generated_code/include/) + target_include_directories(blockchain_ui PRIVATE + ${LOGOS_CPP_SDK_ROOT}/include + ${LOGOS_CPP_SDK_ROOT}/include/cpp + ${LOGOS_CPP_SDK_ROOT}/include/core + ${PLUGINS_OUTPUT_DIR}/include + ) +endif() + +# Link against libraries +target_link_libraries(blockchain_ui PRIVATE + Qt6::Core + Qt6::Widgets + Qt6::RemoteObjects + Qt6::Quick + Qt6::QuickWidgets + component-interfaces +) + +# Link SDK library if using installed layout +if(NOT _cpp_sdk_is_source) + find_library(LOGOS_SDK_LIB logos_sdk PATHS ${LOGOS_CPP_SDK_ROOT}/lib NO_DEFAULT_PATH REQUIRED) + target_link_libraries(blockchain_ui PRIVATE ${LOGOS_SDK_LIB}) +endif() + +# Link against Abseil libraries if found +find_package(absl QUIET) +if(absl_FOUND) + target_link_libraries(blockchain_ui PRIVATE + absl::base + absl::strings + absl::log + absl::check + ) +endif() + +# Set common properties for both platforms +set_target_properties(blockchain_ui PROPERTIES + LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/modules" + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/modules" # For Windows .dll + BUILD_WITH_INSTALL_RPATH TRUE + SKIP_BUILD_RPATH FALSE) + +if(APPLE) + # macOS specific settings + set_target_properties(blockchain_ui PROPERTIES + INSTALL_RPATH "@loader_path" + INSTALL_NAME_DIR "@rpath" + BUILD_WITH_INSTALL_NAME_DIR TRUE) + + add_custom_command(TARGET blockchain_ui POST_BUILD + COMMAND install_name_tool -id "@rpath/blockchain_ui.dylib" $ + COMMENT "Updating library paths for macOS" + ) +else() + # Linux specific settings + set_target_properties(blockchain_ui PROPERTIES + INSTALL_RPATH "$ORIGIN" + INSTALL_RPATH_USE_LINK_PATH FALSE) +endif() + +install(TARGETS blockchain_ui + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/logos/modules + RUNTIME DESTINATION ${CMAKE_INSTALL_LIBDIR}/logos/modules + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}/logos/modules +) + +install(FILES ${METADATA_JSON} + DESTINATION ${CMAKE_INSTALL_DATADIR}/logos-blockchain-ui-new +) + +install(DIRECTORY "${PLUGINS_OUTPUT_DIR}/" + DESTINATION ${CMAKE_INSTALL_DATADIR}/logos-blockchain-ui-new/generated + OPTIONAL +) + +# Print status messages +message(STATUS "Blockchain UI Plugin configured successfully") diff --git a/README.md b/README.md new file mode 100644 index 0000000..116bc47 --- /dev/null +++ b/README.md @@ -0,0 +1,120 @@ +# logos-blockchain-ui-new + +A Qt UI plugin for the Logos Blockchain Module, providing a graphical interface to control and monitor the Logos blockchain node. + +## Features + +- Start/Stop blockchain node +- Configure node parameters (config path, deployment) +- Check wallet balances +- Monitor node status and information + +## How to Build + +### Using Nix (Recommended) + +#### Build Complete UI Plugin + +```bash +# Build everything (default) +nix build + +# Or explicitly +nix build '.#default' +``` + +The result will include: +- `/lib/blockchain_ui.dylib` (or `.so` on Linux) - The Blockchain UI plugin + +#### Build Individual Components + +```bash +# Build only the library (plugin) +nix build '.#lib' + +# Build the standalone Qt application +nix build '.#app' +``` + +#### Development Shell + +```bash +# Enter development shell with all dependencies +nix develop +``` + +**Note:** In zsh, you need to quote the target (e.g., `'.#default'`) to prevent glob expansion. + +If you don't have flakes enabled globally, add experimental flags: + +```bash +nix build --extra-experimental-features 'nix-command flakes' +``` + +The compiled artifacts can be found at `result/` + +#### Running the Standalone App + +After building the app with `nix build '.#app'`, you can run it: + +```bash +# Run the standalone Qt application +./result/bin/logos-blockchain-ui-app +``` + +The app will automatically load the required modules (capability_module, liblogos_blockchain_module) and the blockchain_ui Qt plugin. All dependencies are bundled in the Nix store layout. + +#### Nix Organization + +The nix build system is organized into modular files in the `/nix` directory: +- `nix/default.nix` - Common configuration (dependencies, flags, metadata) +- `nix/lib.nix` - UI plugin compilation +- `nix/app.nix` - Standalone Qt application compilation + +## Output Structure + +When built with Nix: + +**Library build (`nix build '.#lib'`):** +``` +result/ +└── lib/ + └── blockchain_ui.dylib # Logos Blockchain UI plugin +``` + +**App build (`nix build '.#app'`):** +``` +result/ +├── bin/ +│ ├── logos-blockchain-ui-app # Standalone Qt application +│ ├── logos_host # Logos host executable (for plugins) +│ └── logoscore # Logos core executable +├── lib/ +│ ├── liblogos_core.dylib # Logos core library +│ ├── liblogos_sdk.dylib # Logos SDK library +│ └── Logos/DesignSystem/ # QML design system +├── modules/ +│ ├── capability_module_plugin.dylib +│ ├── liblogos_blockchain_module.dylib +│ └── liblogos_blockchain.dylib +└── blockchain_ui.dylib # Qt plugin (loaded by app) +``` + +## Configuration + +### Blockchain Node Configuration + +The blockchain node can be configured in two ways: + +1. **Via UI**: Enter the config path in the "Config Path" field +2. **Via Environment Variable**: Set `LB_CONFIG_PATH` to your configuration file path + +Example configuration file can be found in the logos-blockchain-module repository at `config/node_config.yaml`. + +### QML Hot Reload + +During development, you can enable QML hot reload by setting an environment variable: +```bash +export BLOCKCHAIN_UI_QML_PATH=/path/to/logos-blockchain-ui-new/src/BlockchainView.qml +``` +This allows you to edit the QML file and see changes by reloading the plugin without recompiling. \ No newline at end of file diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt new file mode 100644 index 0000000..bdb008d --- /dev/null +++ b/app/CMakeLists.txt @@ -0,0 +1,84 @@ +cmake_minimum_required(VERSION 3.16) +project(LogosBlockchainUIApp LANGUAGES CXX) + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_AUTOMOC ON) +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +# Find Qt packages +find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Core Widgets) +find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core Widgets) + +# Find logos-liblogos +if(NOT DEFINED LOGOS_LIBLOGOS_ROOT) + message(FATAL_ERROR "LOGOS_LIBLOGOS_ROOT must be defined") +endif() + +# Find logos-cpp-sdk +if(NOT DEFINED LOGOS_CPP_SDK_ROOT) + message(FATAL_ERROR "LOGOS_CPP_SDK_ROOT must be defined") +endif() + +message(STATUS "Using logos-liblogos at: ${LOGOS_LIBLOGOS_ROOT}") +message(STATUS "Using logos-cpp-sdk at: ${LOGOS_CPP_SDK_ROOT}") + +# Check if logos_sdk library exists +if(NOT EXISTS "${LOGOS_CPP_SDK_ROOT}/lib/liblogos_sdk.a" AND NOT EXISTS "${LOGOS_CPP_SDK_ROOT}/lib/liblogos_sdk.dylib" AND NOT EXISTS "${LOGOS_CPP_SDK_ROOT}/lib/liblogos_sdk.so") + message(WARNING "logos_sdk library not found in ${LOGOS_CPP_SDK_ROOT}/lib/") + message(STATUS "Available files in ${LOGOS_CPP_SDK_ROOT}/lib/:") + file(GLOB SDK_LIB_FILES "${LOGOS_CPP_SDK_ROOT}/lib/*") + foreach(file ${SDK_LIB_FILES}) + message(STATUS " ${file}") + endforeach() +endif() + +# Include directories - the new structure has headers in /include with subdirectories +include_directories( + ${LOGOS_LIBLOGOS_ROOT}/include + ${LOGOS_CPP_SDK_ROOT}/include + ${LOGOS_CPP_SDK_ROOT}/include/cpp + ${LOGOS_CPP_SDK_ROOT}/include/core +) + +# Link directories +link_directories( + ${LOGOS_LIBLOGOS_ROOT}/lib + ${LOGOS_CPP_SDK_ROOT}/lib +) + +# Set output directories +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) + +# Create the executable +add_executable(logos-blockchain-ui-app + main.cpp + mainwindow.cpp + mainwindow.h +) + +# Link libraries +target_link_libraries(logos-blockchain-ui-app PRIVATE + Qt${QT_VERSION_MAJOR}::Core + Qt${QT_VERSION_MAJOR}::Widgets + logos_core + logos_sdk +) + +# Set RPATH settings for the executable +if(APPLE) + set_target_properties(logos-blockchain-ui-app PROPERTIES + INSTALL_RPATH "@executable_path/../lib" + BUILD_WITH_INSTALL_RPATH TRUE + ) +elseif(UNIX) + set_target_properties(logos-blockchain-ui-app PROPERTIES + INSTALL_RPATH "$ORIGIN/../lib" + BUILD_WITH_INSTALL_RPATH TRUE + ) +endif() + +# Install rules +install(TARGETS logos-blockchain-ui-app + RUNTIME DESTINATION bin +) diff --git a/app/main.cpp b/app/main.cpp new file mode 100644 index 0000000..6c0ba25 --- /dev/null +++ b/app/main.cpp @@ -0,0 +1,56 @@ +#include "mainwindow.h" + +#include +#include +#include +#include +#include + +// CoreManager C API functions +extern "C" { + void logos_core_set_plugins_dir(const char* plugins_dir); + void logos_core_start(); + void logos_core_cleanup(); + char** logos_core_get_loaded_plugins(); + int logos_core_load_plugin(const char* plugin_name); +} + +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + + QString pluginsDir = QDir::cleanPath(QCoreApplication::applicationDirPath() + "/../modules"); + logos_core_set_plugins_dir(pluginsDir.toUtf8().constData()); + + logos_core_start(); + + if (!logos_core_load_plugin("capability_module")) { + qWarning() << "Failed to load capability_module plugin"; + } + + if (!logos_core_load_plugin("liblogos_blockchain_module")) { + qWarning() << "Failed to load blockchain module plugin"; + } + + char** loadedPlugins = logos_core_get_loaded_plugins(); + int count = 0; + if (loadedPlugins) { + qInfo() << "Currently loaded plugins:"; + for (char** p = loadedPlugins; *p != nullptr; ++p) { + qInfo() << " -" << *p; + ++count; + } + qInfo() << "Total plugins:" << count; + } else { + qInfo() << "No plugins loaded."; + } + + MainWindow window; + window.show(); + + int result = app.exec(); + + logos_core_cleanup(); + + return result; +} diff --git a/app/mainwindow.cpp b/app/mainwindow.cpp new file mode 100644 index 0000000..b749dce --- /dev/null +++ b/app/mainwindow.cpp @@ -0,0 +1,66 @@ +#include +#include "mainwindow.h" + +MainWindow::MainWindow(QWidget *parent) + : QMainWindow(parent) +{ + setupUi(); +} + +MainWindow::~MainWindow() +{ +} + +void MainWindow::setupUi() +{ + // Determine the appropriate plugin extension based on the platform + QString pluginExtension; + #if defined(Q_OS_WIN) + pluginExtension = ".dll"; + #elif defined(Q_OS_MAC) + pluginExtension = ".dylib"; + #else // Linux and other Unix-like systems + pluginExtension = ".so"; + #endif + + QString pluginPath = QCoreApplication::applicationDirPath() + "/../blockchain_ui" + pluginExtension; + QPluginLoader loader(pluginPath); + + QWidget* blockchainWidget = nullptr; + + if (loader.load()) { + QObject* plugin = loader.instance(); + if (plugin) { + // Try to create the blockchain widget using the plugin's createWidget method + QMetaObject::invokeMethod(plugin, "createWidget", + Qt::DirectConnection, + Q_RETURN_ARG(QWidget*, blockchainWidget)); + } + } + + if (blockchainWidget) { + setCentralWidget(blockchainWidget); + } else { + qWarning() << "================================================"; + qWarning() << "Failed to load blockchain UI plugin from:" << pluginPath; + qWarning() << "Error:" << loader.errorString(); + qWarning() << "================================================"; + + // Fallback: show a message when plugin is not found + QWidget* fallbackWidget = new QWidget(this); + QVBoxLayout* layout = new QVBoxLayout(fallbackWidget); + + QLabel* messageLabel = new QLabel("Blockchain UI module not loaded", fallbackWidget); + QFont font = messageLabel->font(); + font.setPointSize(14); + messageLabel->setFont(font); + messageLabel->setAlignment(Qt::AlignCenter); + + layout->addWidget(messageLabel); + setCentralWidget(fallbackWidget); + } + + // Set window title and size + setWindowTitle("Logos Blockchain UI App"); + resize(800, 600); +} diff --git a/app/mainwindow.h b/app/mainwindow.h new file mode 100644 index 0000000..c90ddc9 --- /dev/null +++ b/app/mainwindow.h @@ -0,0 +1,18 @@ +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include + +class MainWindow : public QMainWindow +{ + Q_OBJECT + +public: + MainWindow(QWidget *parent = nullptr); + ~MainWindow(); + +private: + void setupUi(); +}; + +#endif // MAINWINDOW_H diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..a9c102c --- /dev/null +++ b/flake.lock @@ -0,0 +1,1407 @@ +{ + "nodes": { + "crane": { + "locked": { + "lastModified": 1769737823, + "narHash": "sha256-DrBaNpZ+sJ4stXm+0nBX7zqZT9t9P22zbk6m5YhQxS4=", + "owner": "ipetkov", + "repo": "crane", + "rev": "b2f45c3830aa96b7456a4c4bc327d04d7a43e1ba", + "type": "github" + }, + "original": { + "owner": "ipetkov", + "repo": "crane", + "type": "github" + } + }, + "logos-blockchain": { + "inputs": { + "crane": "crane", + "logos-blockchain-circuits": "logos-blockchain-circuits", + "nixpkgs": "nixpkgs_2", + "rust-overlay": "rust-overlay" + }, + "locked": { + "lastModified": 1770911078, + "narHash": "sha256-+asG6HJ/9vuUprjgstZDrvfIo1Zm9Msox3EV8auMDwg=", + "owner": "logos-blockchain", + "repo": "logos-blockchain", + "rev": "71b75c6711779937a0aed383232a6a1920dc13e6", + "type": "github" + }, + "original": { + "owner": "logos-blockchain", + "repo": "logos-blockchain", + "type": "github" + } + }, + "logos-blockchain-circuits": { + "inputs": { + "nixpkgs": "nixpkgs" + }, + "locked": { + "lastModified": 1769780029, + "narHash": "sha256-B2CYcJWuJIXAJaWgBcY4k0FTxo62mI8Hd9RqBECfq4o=", + "owner": "logos-blockchain", + "repo": "logos-blockchain-circuits", + "rev": "480b9bc4fddb4643f528d607f046f27610439a78", + "type": "github" + }, + "original": { + "owner": "logos-blockchain", + "repo": "logos-blockchain-circuits", + "type": "github" + } + }, + "logos-blockchain-module": { + "inputs": { + "logos-blockchain": "logos-blockchain", + "logos-core": "logos-core", + "logos-liblogos": "logos-liblogos", + "logos-module-viewer": "logos-module-viewer", + "nixpkgs": [ + "logos-blockchain-module", + "logos-liblogos", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1770917148, + "narHash": "sha256-fz8KwDBCa8ZCTdPxRqaNrjeY/kGSZRrPJC1llG22CN0=", + "path": "/Users/khushboomehta/Documents/logos/logos-blockchain-module", + "type": "path" + }, + "original": { + "path": "/Users/khushboomehta/Documents/logos/logos-blockchain-module", + "type": "path" + } + }, + "logos-capability-module": { + "inputs": { + "logos-cpp-sdk": "logos-cpp-sdk", + "logos-liblogos": "logos-liblogos_2", + "nixpkgs": [ + "logos-blockchain-module", + "logos-liblogos", + "logos-capability-module", + "logos-liblogos", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1767809111, + "narHash": "sha256-jehjsB+BpDJlVu3I7x+vFVOdXmy9MDmFTJtRqzFUONo=", + "owner": "logos-co", + "repo": "logos-capability-module", + "rev": "7b35383e0aa4e28a4633ed18a87efb57636939b1", + "type": "github" + }, + "original": { + "owner": "logos-co", + "repo": "logos-capability-module", + "type": "github" + } + }, + "logos-capability-module_2": { + "inputs": { + "logos-cpp-sdk": "logos-cpp-sdk_5", + "logos-liblogos": "logos-liblogos_3", + "nixpkgs": [ + "logos-blockchain-module", + "logos-module-viewer", + "logos-capability-module", + "logos-liblogos", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1767809111, + "narHash": "sha256-jehjsB+BpDJlVu3I7x+vFVOdXmy9MDmFTJtRqzFUONo=", + "owner": "logos-co", + "repo": "logos-capability-module", + "rev": "7b35383e0aa4e28a4633ed18a87efb57636939b1", + "type": "github" + }, + "original": { + "owner": "logos-co", + "repo": "logos-capability-module", + "type": "github" + } + }, + "logos-capability-module_3": { + "inputs": { + "logos-cpp-sdk": "logos-cpp-sdk_8", + "logos-liblogos": "logos-liblogos_5", + "nixpkgs": [ + "logos-blockchain-module", + "logos-module-viewer", + "logos-liblogos", + "logos-capability-module", + "logos-liblogos", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1767809111, + "narHash": "sha256-jehjsB+BpDJlVu3I7x+vFVOdXmy9MDmFTJtRqzFUONo=", + "owner": "logos-co", + "repo": "logos-capability-module", + "rev": "7b35383e0aa4e28a4633ed18a87efb57636939b1", + "type": "github" + }, + "original": { + "owner": "logos-co", + "repo": "logos-capability-module", + "type": "github" + } + }, + "logos-capability-module_4": { + "inputs": { + "logos-cpp-sdk": "logos-cpp-sdk_14", + "logos-liblogos": "logos-liblogos_7", + "nixpkgs": [ + "logos-capability-module", + "logos-liblogos", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1767809111, + "narHash": "sha256-jehjsB+BpDJlVu3I7x+vFVOdXmy9MDmFTJtRqzFUONo=", + "owner": "logos-co", + "repo": "logos-capability-module", + "rev": "7b35383e0aa4e28a4633ed18a87efb57636939b1", + "type": "github" + }, + "original": { + "owner": "logos-co", + "repo": "logos-capability-module", + "type": "github" + } + }, + "logos-capability-module_5": { + "inputs": { + "logos-cpp-sdk": "logos-cpp-sdk_17", + "logos-liblogos": "logos-liblogos_9", + "nixpkgs": [ + "logos-liblogos", + "logos-capability-module", + "logos-liblogos", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1767809111, + "narHash": "sha256-jehjsB+BpDJlVu3I7x+vFVOdXmy9MDmFTJtRqzFUONo=", + "owner": "logos-co", + "repo": "logos-capability-module", + "rev": "7b35383e0aa4e28a4633ed18a87efb57636939b1", + "type": "github" + }, + "original": { + "owner": "logos-co", + "repo": "logos-capability-module", + "type": "github" + } + }, + "logos-core": { + "inputs": { + "nixpkgs": "nixpkgs_3" + }, + "locked": { + "lastModified": 1770132997, + "narHash": "sha256-Iv0QMXMD6kf+y2Qx37jXR7Ik6h1dqOzuxBzCdc5S6KA=", + "owner": "logos-co", + "repo": "logos-cpp-sdk", + "rev": "30ef7986f4b65b7dcf43af84bb073233b1b77821", + "type": "github" + }, + "original": { + "owner": "logos-co", + "repo": "logos-cpp-sdk", + "type": "github" + } + }, + "logos-cpp-sdk": { + "inputs": { + "nixpkgs": "nixpkgs_4" + }, + "locked": { + "lastModified": 1761230734, + "narHash": "sha256-CMRUwXH7pJZ1OI6bd/TDDDXKqQ1tQZHQEOOwK8TgYHI=", + "owner": "logos-co", + "repo": "logos-cpp-sdk", + "rev": "4b143922c190df00bb3835441c9f0075cb28283b", + "type": "github" + }, + "original": { + "owner": "logos-co", + "repo": "logos-cpp-sdk", + "type": "github" + } + }, + "logos-cpp-sdk_10": { + "inputs": { + "nixpkgs": "nixpkgs_13" + }, + "locked": { + "lastModified": 1767724329, + "narHash": "sha256-UPkqxqxbKwU5Dmu00TnjiJVXUmfVylF3p1qziEuYwIE=", + "owner": "logos-co", + "repo": "logos-cpp-sdk", + "rev": "32f1d7080d784ff044d91d076ef2f0c7305d4784", + "type": "github" + }, + "original": { + "owner": "logos-co", + "repo": "logos-cpp-sdk", + "type": "github" + } + }, + "logos-cpp-sdk_11": { + "inputs": { + "nixpkgs": "nixpkgs_14" + }, + "locked": { + "lastModified": 1767724329, + "narHash": "sha256-UPkqxqxbKwU5Dmu00TnjiJVXUmfVylF3p1qziEuYwIE=", + "owner": "logos-co", + "repo": "logos-cpp-sdk", + "rev": "32f1d7080d784ff044d91d076ef2f0c7305d4784", + "type": "github" + }, + "original": { + "owner": "logos-co", + "repo": "logos-cpp-sdk", + "type": "github" + } + }, + "logos-cpp-sdk_12": { + "inputs": { + "nixpkgs": "nixpkgs_15" + }, + "locked": { + "lastModified": 1767724329, + "narHash": "sha256-UPkqxqxbKwU5Dmu00TnjiJVXUmfVylF3p1qziEuYwIE=", + "owner": "logos-co", + "repo": "logos-cpp-sdk", + "rev": "32f1d7080d784ff044d91d076ef2f0c7305d4784", + "type": "github" + }, + "original": { + "owner": "logos-co", + "repo": "logos-cpp-sdk", + "type": "github" + } + }, + "logos-cpp-sdk_13": { + "inputs": { + "nixpkgs": "nixpkgs_16" + }, + "locked": { + "lastModified": 1764699992, + "narHash": "sha256-nCmK9C9F31cHvy6lWKR5WGl99aJbS3kIsROAoZ4OrwI=", + "owner": "logos-co", + "repo": "logos-cpp-sdk", + "rev": "5d0bbd0d1e00aad0532ffa7c8bf2c80f460a4f6d", + "type": "github" + }, + "original": { + "owner": "logos-co", + "repo": "logos-cpp-sdk", + "type": "github" + } + }, + "logos-cpp-sdk_14": { + "inputs": { + "nixpkgs": "nixpkgs_18" + }, + "locked": { + "lastModified": 1761230734, + "narHash": "sha256-CMRUwXH7pJZ1OI6bd/TDDDXKqQ1tQZHQEOOwK8TgYHI=", + "owner": "logos-co", + "repo": "logos-cpp-sdk", + "rev": "4b143922c190df00bb3835441c9f0075cb28283b", + "type": "github" + }, + "original": { + "owner": "logos-co", + "repo": "logos-cpp-sdk", + "type": "github" + } + }, + "logos-cpp-sdk_15": { + "inputs": { + "nixpkgs": "nixpkgs_19" + }, + "locked": { + "lastModified": 1761230734, + "narHash": "sha256-CMRUwXH7pJZ1OI6bd/TDDDXKqQ1tQZHQEOOwK8TgYHI=", + "owner": "logos-co", + "repo": "logos-cpp-sdk", + "rev": "4b143922c190df00bb3835441c9f0075cb28283b", + "type": "github" + }, + "original": { + "owner": "logos-co", + "repo": "logos-cpp-sdk", + "type": "github" + } + }, + "logos-cpp-sdk_16": { + "inputs": { + "nixpkgs": "nixpkgs_20" + }, + "locked": { + "lastModified": 1770132997, + "narHash": "sha256-Iv0QMXMD6kf+y2Qx37jXR7Ik6h1dqOzuxBzCdc5S6KA=", + "owner": "logos-co", + "repo": "logos-cpp-sdk", + "rev": "30ef7986f4b65b7dcf43af84bb073233b1b77821", + "type": "github" + }, + "original": { + "owner": "logos-co", + "repo": "logos-cpp-sdk", + "type": "github" + } + }, + "logos-cpp-sdk_17": { + "inputs": { + "nixpkgs": "nixpkgs_21" + }, + "locked": { + "lastModified": 1761230734, + "narHash": "sha256-CMRUwXH7pJZ1OI6bd/TDDDXKqQ1tQZHQEOOwK8TgYHI=", + "owner": "logos-co", + "repo": "logos-cpp-sdk", + "rev": "4b143922c190df00bb3835441c9f0075cb28283b", + "type": "github" + }, + "original": { + "owner": "logos-co", + "repo": "logos-cpp-sdk", + "type": "github" + } + }, + "logos-cpp-sdk_18": { + "inputs": { + "nixpkgs": "nixpkgs_22" + }, + "locked": { + "lastModified": 1761230734, + "narHash": "sha256-CMRUwXH7pJZ1OI6bd/TDDDXKqQ1tQZHQEOOwK8TgYHI=", + "owner": "logos-co", + "repo": "logos-cpp-sdk", + "rev": "4b143922c190df00bb3835441c9f0075cb28283b", + "type": "github" + }, + "original": { + "owner": "logos-co", + "repo": "logos-cpp-sdk", + "type": "github" + } + }, + "logos-cpp-sdk_19": { + "inputs": { + "nixpkgs": "nixpkgs_23" + }, + "locked": { + "lastModified": 1767724329, + "narHash": "sha256-UPkqxqxbKwU5Dmu00TnjiJVXUmfVylF3p1qziEuYwIE=", + "owner": "logos-co", + "repo": "logos-cpp-sdk", + "rev": "32f1d7080d784ff044d91d076ef2f0c7305d4784", + "type": "github" + }, + "original": { + "owner": "logos-co", + "repo": "logos-cpp-sdk", + "type": "github" + } + }, + "logos-cpp-sdk_2": { + "inputs": { + "nixpkgs": "nixpkgs_5" + }, + "locked": { + "lastModified": 1761230734, + "narHash": "sha256-CMRUwXH7pJZ1OI6bd/TDDDXKqQ1tQZHQEOOwK8TgYHI=", + "owner": "logos-co", + "repo": "logos-cpp-sdk", + "rev": "4b143922c190df00bb3835441c9f0075cb28283b", + "type": "github" + }, + "original": { + "owner": "logos-co", + "repo": "logos-cpp-sdk", + "type": "github" + } + }, + "logos-cpp-sdk_20": { + "inputs": { + "nixpkgs": "nixpkgs_24" + }, + "locked": { + "lastModified": 1767724329, + "narHash": "sha256-UPkqxqxbKwU5Dmu00TnjiJVXUmfVylF3p1qziEuYwIE=", + "owner": "logos-co", + "repo": "logos-cpp-sdk", + "rev": "32f1d7080d784ff044d91d076ef2f0c7305d4784", + "type": "github" + }, + "original": { + "owner": "logos-co", + "repo": "logos-cpp-sdk", + "type": "github" + } + }, + "logos-cpp-sdk_3": { + "inputs": { + "nixpkgs": "nixpkgs_6" + }, + "locked": { + "lastModified": 1767724329, + "narHash": "sha256-UPkqxqxbKwU5Dmu00TnjiJVXUmfVylF3p1qziEuYwIE=", + "owner": "logos-co", + "repo": "logos-cpp-sdk", + "rev": "32f1d7080d784ff044d91d076ef2f0c7305d4784", + "type": "github" + }, + "original": { + "owner": "logos-co", + "repo": "logos-cpp-sdk", + "type": "github" + } + }, + "logos-cpp-sdk_4": { + "inputs": { + "nixpkgs": "nixpkgs_7" + }, + "locked": { + "lastModified": 1767724329, + "narHash": "sha256-UPkqxqxbKwU5Dmu00TnjiJVXUmfVylF3p1qziEuYwIE=", + "owner": "logos-co", + "repo": "logos-cpp-sdk", + "rev": "32f1d7080d784ff044d91d076ef2f0c7305d4784", + "type": "github" + }, + "original": { + "owner": "logos-co", + "repo": "logos-cpp-sdk", + "type": "github" + } + }, + "logos-cpp-sdk_5": { + "inputs": { + "nixpkgs": "nixpkgs_8" + }, + "locked": { + "lastModified": 1761230734, + "narHash": "sha256-CMRUwXH7pJZ1OI6bd/TDDDXKqQ1tQZHQEOOwK8TgYHI=", + "owner": "logos-co", + "repo": "logos-cpp-sdk", + "rev": "4b143922c190df00bb3835441c9f0075cb28283b", + "type": "github" + }, + "original": { + "owner": "logos-co", + "repo": "logos-cpp-sdk", + "type": "github" + } + }, + "logos-cpp-sdk_6": { + "inputs": { + "nixpkgs": "nixpkgs_9" + }, + "locked": { + "lastModified": 1761230734, + "narHash": "sha256-CMRUwXH7pJZ1OI6bd/TDDDXKqQ1tQZHQEOOwK8TgYHI=", + "owner": "logos-co", + "repo": "logos-cpp-sdk", + "rev": "4b143922c190df00bb3835441c9f0075cb28283b", + "type": "github" + }, + "original": { + "owner": "logos-co", + "repo": "logos-cpp-sdk", + "type": "github" + } + }, + "logos-cpp-sdk_7": { + "inputs": { + "nixpkgs": "nixpkgs_10" + }, + "locked": { + "lastModified": 1770132997, + "narHash": "sha256-Iv0QMXMD6kf+y2Qx37jXR7Ik6h1dqOzuxBzCdc5S6KA=", + "owner": "logos-co", + "repo": "logos-cpp-sdk", + "rev": "30ef7986f4b65b7dcf43af84bb073233b1b77821", + "type": "github" + }, + "original": { + "owner": "logos-co", + "repo": "logos-cpp-sdk", + "type": "github" + } + }, + "logos-cpp-sdk_8": { + "inputs": { + "nixpkgs": "nixpkgs_11" + }, + "locked": { + "lastModified": 1761230734, + "narHash": "sha256-CMRUwXH7pJZ1OI6bd/TDDDXKqQ1tQZHQEOOwK8TgYHI=", + "owner": "logos-co", + "repo": "logos-cpp-sdk", + "rev": "4b143922c190df00bb3835441c9f0075cb28283b", + "type": "github" + }, + "original": { + "owner": "logos-co", + "repo": "logos-cpp-sdk", + "type": "github" + } + }, + "logos-cpp-sdk_9": { + "inputs": { + "nixpkgs": "nixpkgs_12" + }, + "locked": { + "lastModified": 1761230734, + "narHash": "sha256-CMRUwXH7pJZ1OI6bd/TDDDXKqQ1tQZHQEOOwK8TgYHI=", + "owner": "logos-co", + "repo": "logos-cpp-sdk", + "rev": "4b143922c190df00bb3835441c9f0075cb28283b", + "type": "github" + }, + "original": { + "owner": "logos-co", + "repo": "logos-cpp-sdk", + "type": "github" + } + }, + "logos-design-system": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1770058741, + "narHash": "sha256-9Gx5zJqLZKCuI5BXoCQt39IYrqPR8VSLjT/NQawKdxk=", + "owner": "logos-co", + "repo": "logos-design-system", + "rev": "7d3ae424b77adef1bfa4a728e951c3b029887e45", + "type": "github" + }, + "original": { + "owner": "logos-co", + "repo": "logos-design-system", + "type": "github" + } + }, + "logos-liblogos": { + "inputs": { + "logos-capability-module": "logos-capability-module", + "logos-cpp-sdk": "logos-cpp-sdk_3", + "logos-module": "logos-module", + "nixpkgs": [ + "logos-blockchain-module", + "logos-liblogos", + "logos-cpp-sdk", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1770837874, + "narHash": "sha256-wr75lv1q4U1FS5+l/6ypwzJFJe06l2RyUvx1npoRS88=", + "owner": "logos-co", + "repo": "logos-liblogos", + "rev": "e3741c01fd3abf6b7bd9ff2fa8edf89c41fc0cea", + "type": "github" + }, + "original": { + "owner": "logos-co", + "repo": "logos-liblogos", + "type": "github" + } + }, + "logos-liblogos_2": { + "inputs": { + "logos-cpp-sdk": "logos-cpp-sdk_2", + "nixpkgs": [ + "logos-blockchain-module", + "logos-liblogos", + "logos-capability-module", + "logos-liblogos", + "logos-cpp-sdk", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1761845775, + "narHash": "sha256-ulK8xq05ejK6qIgZ7WtWb/MJt2rk5BKfDA2z7mM3wq8=", + "owner": "logos-co", + "repo": "logos-liblogos", + "rev": "a92c2c1268bc70764c8f73c7bce07d21024f5af9", + "type": "github" + }, + "original": { + "owner": "logos-co", + "repo": "logos-liblogos", + "type": "github" + } + }, + "logos-liblogos_3": { + "inputs": { + "logos-cpp-sdk": "logos-cpp-sdk_6", + "nixpkgs": [ + "logos-blockchain-module", + "logos-module-viewer", + "logos-capability-module", + "logos-liblogos", + "logos-cpp-sdk", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1761845775, + "narHash": "sha256-ulK8xq05ejK6qIgZ7WtWb/MJt2rk5BKfDA2z7mM3wq8=", + "owner": "logos-co", + "repo": "logos-liblogos", + "rev": "a92c2c1268bc70764c8f73c7bce07d21024f5af9", + "type": "github" + }, + "original": { + "owner": "logos-co", + "repo": "logos-liblogos", + "type": "github" + } + }, + "logos-liblogos_4": { + "inputs": { + "logos-capability-module": "logos-capability-module_3", + "logos-cpp-sdk": "logos-cpp-sdk_10", + "logos-module": "logos-module_2", + "nixpkgs": [ + "logos-blockchain-module", + "logos-module-viewer", + "logos-liblogos", + "logos-cpp-sdk", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1770154824, + "narHash": "sha256-WGI+3FkPdeytfLJ3ZJYr1O8esUnQjcmMJEYwB/EBZMs=", + "owner": "logos-co", + "repo": "logos-liblogos", + "rev": "901dd86d47216b15b6f1260b7b6bb4ecd88a8f9d", + "type": "github" + }, + "original": { + "owner": "logos-co", + "repo": "logos-liblogos", + "type": "github" + } + }, + "logos-liblogos_5": { + "inputs": { + "logos-cpp-sdk": "logos-cpp-sdk_9", + "nixpkgs": [ + "logos-blockchain-module", + "logos-module-viewer", + "logos-liblogos", + "logos-capability-module", + "logos-liblogos", + "logos-cpp-sdk", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1761845775, + "narHash": "sha256-ulK8xq05ejK6qIgZ7WtWb/MJt2rk5BKfDA2z7mM3wq8=", + "owner": "logos-co", + "repo": "logos-liblogos", + "rev": "a92c2c1268bc70764c8f73c7bce07d21024f5af9", + "type": "github" + }, + "original": { + "owner": "logos-co", + "repo": "logos-liblogos", + "type": "github" + } + }, + "logos-liblogos_6": { + "inputs": { + "logos-cpp-sdk": "logos-cpp-sdk_13", + "nixpkgs": [ + "logos-blockchain-module", + "logos-module-viewer", + "logos-package-manager", + "logos-liblogos", + "logos-cpp-sdk", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1768343028, + "narHash": "sha256-4LvsuZTDTlLtfMF4C69ls+lmkYJWD7LZitS04Mc+8UI=", + "owner": "logos-co", + "repo": "logos-liblogos", + "rev": "a76d33f5519af0ee12317c8f149eee2ac5d292a0", + "type": "github" + }, + "original": { + "owner": "logos-co", + "repo": "logos-liblogos", + "type": "github" + } + }, + "logos-liblogos_7": { + "inputs": { + "logos-cpp-sdk": "logos-cpp-sdk_15", + "nixpkgs": [ + "logos-capability-module", + "logos-liblogos", + "logos-cpp-sdk", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1761845775, + "narHash": "sha256-ulK8xq05ejK6qIgZ7WtWb/MJt2rk5BKfDA2z7mM3wq8=", + "owner": "logos-co", + "repo": "logos-liblogos", + "rev": "a92c2c1268bc70764c8f73c7bce07d21024f5af9", + "type": "github" + }, + "original": { + "owner": "logos-co", + "repo": "logos-liblogos", + "type": "github" + } + }, + "logos-liblogos_8": { + "inputs": { + "logos-capability-module": "logos-capability-module_5", + "logos-cpp-sdk": "logos-cpp-sdk_19", + "logos-module": "logos-module_3", + "nixpkgs": [ + "logos-liblogos", + "logos-cpp-sdk", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1770837874, + "narHash": "sha256-wr75lv1q4U1FS5+l/6ypwzJFJe06l2RyUvx1npoRS88=", + "owner": "logos-co", + "repo": "logos-liblogos", + "rev": "e3741c01fd3abf6b7bd9ff2fa8edf89c41fc0cea", + "type": "github" + }, + "original": { + "owner": "logos-co", + "repo": "logos-liblogos", + "type": "github" + } + }, + "logos-liblogos_9": { + "inputs": { + "logos-cpp-sdk": "logos-cpp-sdk_18", + "nixpkgs": [ + "logos-liblogos", + "logos-capability-module", + "logos-liblogos", + "logos-cpp-sdk", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1761845775, + "narHash": "sha256-ulK8xq05ejK6qIgZ7WtWb/MJt2rk5BKfDA2z7mM3wq8=", + "owner": "logos-co", + "repo": "logos-liblogos", + "rev": "a92c2c1268bc70764c8f73c7bce07d21024f5af9", + "type": "github" + }, + "original": { + "owner": "logos-co", + "repo": "logos-liblogos", + "type": "github" + } + }, + "logos-module": { + "inputs": { + "logos-cpp-sdk": "logos-cpp-sdk_4", + "nixpkgs": [ + "logos-blockchain-module", + "logos-liblogos", + "logos-module", + "logos-cpp-sdk", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1770062426, + "narHash": "sha256-zc7ZxDTlqOCYGyEHhrTA/7GS1EWh7+4amdPUKh+gGds=", + "owner": "logos-co", + "repo": "logos-module", + "rev": "f7ee69d9ad9f27c84f04f59896e9194125e951dc", + "type": "github" + }, + "original": { + "owner": "logos-co", + "repo": "logos-module", + "type": "github" + } + }, + "logos-module-viewer": { + "inputs": { + "logos-capability-module": "logos-capability-module_2", + "logos-cpp-sdk": "logos-cpp-sdk_7", + "logos-liblogos": "logos-liblogos_4", + "logos-package-manager": "logos-package-manager", + "nixpkgs": [ + "logos-blockchain-module", + "logos-module-viewer", + "logos-liblogos", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1770804615, + "narHash": "sha256-0DuGGEgGHpRcVElWlQXqgseGN+xZ6cqXplRayqdNZQY=", + "owner": "logos-co", + "repo": "logos-module-viewer", + "rev": "2ed9def5db6d5b8d83e5a9671ce5c571bc86deff", + "type": "github" + }, + "original": { + "owner": "logos-co", + "repo": "logos-module-viewer", + "type": "github" + } + }, + "logos-module_2": { + "inputs": { + "logos-cpp-sdk": "logos-cpp-sdk_11", + "nixpkgs": [ + "logos-blockchain-module", + "logos-module-viewer", + "logos-liblogos", + "logos-module", + "logos-cpp-sdk", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1770062426, + "narHash": "sha256-zc7ZxDTlqOCYGyEHhrTA/7GS1EWh7+4amdPUKh+gGds=", + "owner": "logos-co", + "repo": "logos-module", + "rev": "f7ee69d9ad9f27c84f04f59896e9194125e951dc", + "type": "github" + }, + "original": { + "owner": "logos-co", + "repo": "logos-module", + "type": "github" + } + }, + "logos-module_3": { + "inputs": { + "logos-cpp-sdk": "logos-cpp-sdk_20", + "nixpkgs": [ + "logos-liblogos", + "logos-module", + "logos-cpp-sdk", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1770062426, + "narHash": "sha256-zc7ZxDTlqOCYGyEHhrTA/7GS1EWh7+4amdPUKh+gGds=", + "owner": "logos-co", + "repo": "logos-module", + "rev": "f7ee69d9ad9f27c84f04f59896e9194125e951dc", + "type": "github" + }, + "original": { + "owner": "logos-co", + "repo": "logos-module", + "type": "github" + } + }, + "logos-package": { + "inputs": { + "nixpkgs": "nixpkgs_17" + }, + "locked": { + "lastModified": 1768925546, + "narHash": "sha256-Y4sgYs9wtZ9sHAuKl9LUy//ReeF4/AyK8HlnZsYrSqg=", + "owner": "logos-co", + "repo": "logos-package", + "rev": "9230ae37c9d289c0c355dcf9fa40fd3be2e99f17", + "type": "github" + }, + "original": { + "owner": "logos-co", + "repo": "logos-package", + "type": "github" + } + }, + "logos-package-manager": { + "inputs": { + "logos-cpp-sdk": "logos-cpp-sdk_12", + "logos-liblogos": "logos-liblogos_6", + "logos-package": "logos-package", + "nixpkgs": [ + "logos-blockchain-module", + "logos-module-viewer", + "logos-package-manager", + "logos-liblogos", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1770753928, + "narHash": "sha256-61+3D+svB2mqyLpDFlHoIN+hBlbRGZUaueKysEiorNE=", + "owner": "logos-co", + "repo": "logos-package-manager-module", + "rev": "0cbf250ad2fec20c79dc5f61729a07c3a2bd50e1", + "type": "github" + }, + "original": { + "owner": "logos-co", + "repo": "logos-package-manager-module", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1769461804, + "narHash": "sha256-msG8SU5WsBUfVVa/9RPLaymvi5bI8edTavbIq3vRlhI=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "bfc1b8a4574108ceef22f02bafcf6611380c100d", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_10": { + "locked": { + "lastModified": 1759036355, + "narHash": "sha256-0m27AKv6ka+q270dw48KflE0LwQYrO7Fm4/2//KCVWg=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "e9f00bd893984bc8ce46c895c3bf7cac95331127", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_11": { + "locked": { + "lastModified": 1759036355, + "narHash": "sha256-0m27AKv6ka+q270dw48KflE0LwQYrO7Fm4/2//KCVWg=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "e9f00bd893984bc8ce46c895c3bf7cac95331127", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_12": { + "locked": { + "lastModified": 1759036355, + "narHash": "sha256-0m27AKv6ka+q270dw48KflE0LwQYrO7Fm4/2//KCVWg=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "e9f00bd893984bc8ce46c895c3bf7cac95331127", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_13": { + "locked": { + "lastModified": 1759036355, + "narHash": "sha256-0m27AKv6ka+q270dw48KflE0LwQYrO7Fm4/2//KCVWg=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "e9f00bd893984bc8ce46c895c3bf7cac95331127", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_14": { + "locked": { + "lastModified": 1759036355, + "narHash": "sha256-0m27AKv6ka+q270dw48KflE0LwQYrO7Fm4/2//KCVWg=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "e9f00bd893984bc8ce46c895c3bf7cac95331127", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_15": { + "locked": { + "lastModified": 1759036355, + "narHash": "sha256-0m27AKv6ka+q270dw48KflE0LwQYrO7Fm4/2//KCVWg=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "e9f00bd893984bc8ce46c895c3bf7cac95331127", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_16": { + "locked": { + "lastModified": 1759036355, + "narHash": "sha256-0m27AKv6ka+q270dw48KflE0LwQYrO7Fm4/2//KCVWg=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "e9f00bd893984bc8ce46c895c3bf7cac95331127", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_17": { + "locked": { + "lastModified": 1768127708, + "narHash": "sha256-1Sm77VfZh3mU0F5OqKABNLWxOuDeHIlcFjsXeeiPazs=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "ffbc9f8cbaacfb331b6017d5a5abb21a492c9a38", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_18": { + "locked": { + "lastModified": 1759036355, + "narHash": "sha256-0m27AKv6ka+q270dw48KflE0LwQYrO7Fm4/2//KCVWg=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "e9f00bd893984bc8ce46c895c3bf7cac95331127", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_19": { + "locked": { + "lastModified": 1759036355, + "narHash": "sha256-0m27AKv6ka+q270dw48KflE0LwQYrO7Fm4/2//KCVWg=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "e9f00bd893984bc8ce46c895c3bf7cac95331127", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_2": { + "locked": { + "lastModified": 1769461804, + "narHash": "sha256-msG8SU5WsBUfVVa/9RPLaymvi5bI8edTavbIq3vRlhI=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "bfc1b8a4574108ceef22f02bafcf6611380c100d", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_20": { + "locked": { + "lastModified": 1759036355, + "narHash": "sha256-0m27AKv6ka+q270dw48KflE0LwQYrO7Fm4/2//KCVWg=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "e9f00bd893984bc8ce46c895c3bf7cac95331127", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_21": { + "locked": { + "lastModified": 1759036355, + "narHash": "sha256-0m27AKv6ka+q270dw48KflE0LwQYrO7Fm4/2//KCVWg=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "e9f00bd893984bc8ce46c895c3bf7cac95331127", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_22": { + "locked": { + "lastModified": 1759036355, + "narHash": "sha256-0m27AKv6ka+q270dw48KflE0LwQYrO7Fm4/2//KCVWg=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "e9f00bd893984bc8ce46c895c3bf7cac95331127", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_23": { + "locked": { + "lastModified": 1759036355, + "narHash": "sha256-0m27AKv6ka+q270dw48KflE0LwQYrO7Fm4/2//KCVWg=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "e9f00bd893984bc8ce46c895c3bf7cac95331127", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_24": { + "locked": { + "lastModified": 1759036355, + "narHash": "sha256-0m27AKv6ka+q270dw48KflE0LwQYrO7Fm4/2//KCVWg=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "e9f00bd893984bc8ce46c895c3bf7cac95331127", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_3": { + "locked": { + "lastModified": 1759036355, + "narHash": "sha256-0m27AKv6ka+q270dw48KflE0LwQYrO7Fm4/2//KCVWg=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "e9f00bd893984bc8ce46c895c3bf7cac95331127", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_4": { + "locked": { + "lastModified": 1759036355, + "narHash": "sha256-0m27AKv6ka+q270dw48KflE0LwQYrO7Fm4/2//KCVWg=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "e9f00bd893984bc8ce46c895c3bf7cac95331127", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_5": { + "locked": { + "lastModified": 1759036355, + "narHash": "sha256-0m27AKv6ka+q270dw48KflE0LwQYrO7Fm4/2//KCVWg=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "e9f00bd893984bc8ce46c895c3bf7cac95331127", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_6": { + "locked": { + "lastModified": 1759036355, + "narHash": "sha256-0m27AKv6ka+q270dw48KflE0LwQYrO7Fm4/2//KCVWg=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "e9f00bd893984bc8ce46c895c3bf7cac95331127", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_7": { + "locked": { + "lastModified": 1759036355, + "narHash": "sha256-0m27AKv6ka+q270dw48KflE0LwQYrO7Fm4/2//KCVWg=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "e9f00bd893984bc8ce46c895c3bf7cac95331127", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_8": { + "locked": { + "lastModified": 1759036355, + "narHash": "sha256-0m27AKv6ka+q270dw48KflE0LwQYrO7Fm4/2//KCVWg=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "e9f00bd893984bc8ce46c895c3bf7cac95331127", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_9": { + "locked": { + "lastModified": 1759036355, + "narHash": "sha256-0m27AKv6ka+q270dw48KflE0LwQYrO7Fm4/2//KCVWg=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "e9f00bd893984bc8ce46c895c3bf7cac95331127", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "logos-blockchain-module": "logos-blockchain-module", + "logos-capability-module": "logos-capability-module_4", + "logos-cpp-sdk": "logos-cpp-sdk_16", + "logos-design-system": "logos-design-system", + "logos-liblogos": "logos-liblogos_8", + "nixpkgs": [ + "logos-liblogos", + "nixpkgs" + ] + } + }, + "rust-overlay": { + "inputs": { + "nixpkgs": [ + "logos-blockchain-module", + "logos-blockchain", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1769742225, + "narHash": "sha256-roSD/OJ3x9nF+Dxr+/bLClX3U8FP9EkCQIFpzxKjSUM=", + "owner": "oxalica", + "repo": "rust-overlay", + "rev": "bcdd8d37594f0e201639f55889c01c827baf5c75", + "type": "github" + }, + "original": { + "owner": "oxalica", + "repo": "rust-overlay", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..bdc1009 --- /dev/null +++ b/flake.nix @@ -0,0 +1,84 @@ +{ + description = "Logos Blockchain UI - A Qt UI plugin for Logos Blockchain Module"; + + inputs = { + # Follow the same nixpkgs as logos-liblogos to ensure compatibility + nixpkgs.follows = "logos-liblogos/nixpkgs"; + logos-cpp-sdk.url = "github:logos-co/logos-cpp-sdk"; + logos-liblogos.url = "github:logos-co/logos-liblogos"; + logos-blockchain-module.url = "github:logos-co/logos-blockchain-module"; + logos-capability-module.url = "github:logos-co/logos-capability-module"; + logos-design-system.url = "github:logos-co/logos-design-system"; + logos-design-system.inputs.nixpkgs.follows = "nixpkgs"; + }; + + outputs = { self, nixpkgs, logos-cpp-sdk, logos-liblogos, logos-blockchain-module, logos-capability-module, logos-design-system }: + let + systems = [ "aarch64-darwin" "x86_64-darwin" "aarch64-linux" "x86_64-linux" ]; + forAllSystems = f: nixpkgs.lib.genAttrs systems (system: f { + pkgs = import nixpkgs { inherit system; }; + logosSdk = logos-cpp-sdk.packages.${system}.default; + logosLiblogos = logos-liblogos.packages.${system}.default; + logosBlockchainModule = logos-blockchain-module.packages.${system}.default; + logosCapabilityModule = logos-capability-module.packages.${system}.default; + logosDesignSystem = logos-design-system.packages.${system}.default; + }); + in + { + packages = forAllSystems ({ pkgs, logosSdk, logosLiblogos, logosBlockchainModule, logosCapabilityModule, logosDesignSystem }: + let + # Common configuration + common = import ./nix/default.nix { + inherit pkgs logosSdk logosLiblogos; + }; + src = ./.; + + # Library package (default blockchain-module has lib + include via symlinkJoin) + lib = import ./nix/lib.nix { + inherit pkgs common src logosBlockchainModule logosSdk; + }; + + # App package + app = import ./nix/app.nix { + inherit pkgs common src logosLiblogos logosSdk logosBlockchainModule logosCapabilityModule logosDesignSystem; + logosBlockchainUI = lib; + }; + in + { + # Individual outputs + logos-blockchain-ui-lib = lib; + app = app; + lib = lib; + + # Default package + default = lib; + } + ); + + devShells = forAllSystems ({ pkgs, logosSdk, logosLiblogos, logosBlockchainModule, logosCapabilityModule, logosDesignSystem }: { + default = pkgs.mkShell { + nativeBuildInputs = [ + pkgs.cmake + pkgs.ninja + pkgs.pkg-config + ]; + buildInputs = [ + pkgs.qt6.qtbase + pkgs.qt6.qtremoteobjects + pkgs.zstd + pkgs.krb5 + pkgs.abseil-cpp + ]; + + shellHook = '' + export LOGOS_CPP_SDK_ROOT="${logosSdk}" + export LOGOS_LIBLOGOS_ROOT="${logosLiblogos}" + export LOGOS_DESIGN_SYSTEM_ROOT="${logosDesignSystem}" + echo "Logos Blockchain UI development environment" + echo "LOGOS_CPP_SDK_ROOT: $LOGOS_CPP_SDK_ROOT" + echo "LOGOS_LIBLOGOS_ROOT: $LOGOS_LIBLOGOS_ROOT" + ''; + }; + }); + }; +} diff --git a/interfaces/IComponent.h b/interfaces/IComponent.h new file mode 100644 index 0000000..06ad57a --- /dev/null +++ b/interfaces/IComponent.h @@ -0,0 +1,17 @@ +#pragma once + +#include +#include +#include + +class LogosAPI; + +class IComponent { +public: + virtual ~IComponent() = default; + virtual QWidget* createWidget(LogosAPI* logosAPI = nullptr) = 0; + virtual void destroyWidget(QWidget* widget) = 0; +}; + +#define IComponent_iid "com.logos.component.IComponent" +Q_DECLARE_INTERFACE(IComponent, IComponent_iid) diff --git a/metadata.json b/metadata.json new file mode 100644 index 0000000..981bbc5 --- /dev/null +++ b/metadata.json @@ -0,0 +1,24 @@ +{ + "name": "blockchain_ui", + "version": "1.0.0", + "description": "Blockchain UI module for the Logos application", + "author": "Logos Blockchain Team", + "type": "ui", + "main": "blockchain_ui", + "dependencies": ["liblogos_blockchain_module"], + "category": "blockchain", + "build": { + "type": "cmake", + "files": [ + "src/BlockchainPlugin.cpp", + "src/BlockchainPlugin.h", + "src/BlockchainBackend.cpp", + "src/BlockchainBackend.h", + "src/blockchain_resources.qrc" + ] + }, + "capabilities": [ + "ui_components", + "blockchain" + ] +} diff --git a/nix/app.nix b/nix/app.nix new file mode 100644 index 0000000..00ebdc3 --- /dev/null +++ b/nix/app.nix @@ -0,0 +1,250 @@ +# Builds the logos-blockchain-ui-app standalone application +{ pkgs, common, src, logosLiblogos, logosSdk, logosBlockchainModule, logosCapabilityModule, logosBlockchainUI, logosDesignSystem }: + +pkgs.stdenv.mkDerivation rec { + pname = "logos-blockchain-ui-app"; + version = common.version; + + inherit src; + inherit (common) buildInputs cmakeFlags meta; + + # Add logosSdk to nativeBuildInputs for logos-cpp-generator + nativeBuildInputs = common.nativeBuildInputs ++ [ logosSdk pkgs.patchelf pkgs.removeReferencesTo ]; + + # Provide Qt/GL runtime paths so the wrapper can inject them + qtLibPath = pkgs.lib.makeLibraryPath ( + [ + pkgs.qt6.qtbase + pkgs.qt6.qtremoteobjects + pkgs.zstd + pkgs.krb5 + pkgs.zlib + pkgs.glib + pkgs.stdenv.cc.cc + pkgs.freetype + pkgs.fontconfig + ] + ++ pkgs.lib.optionals pkgs.stdenv.isLinux [ + pkgs.libglvnd + pkgs.mesa.drivers + pkgs.xorg.libX11 + pkgs.xorg.libXext + pkgs.xorg.libXrender + pkgs.xorg.libXrandr + pkgs.xorg.libXcursor + pkgs.xorg.libXi + pkgs.xorg.libXfixes + pkgs.xorg.libxcb + ] + ); + qtPluginPath = "${pkgs.qt6.qtbase}/lib/qt-6/plugins"; + qmlImportPath = "${placeholder "out"}/lib:${pkgs.qt6.qtbase}/lib/qt-6/qml"; + + # This is a GUI application, enable Qt wrapping + dontWrapQtApps = false; + + # This is an aggregate runtime layout; avoid stripping to prevent hook errors + dontStrip = true; + + # Ensure proper Qt environment setup via wrapper + qtWrapperArgs = [ + "--prefix" "LD_LIBRARY_PATH" ":" qtLibPath + "--prefix" "QT_PLUGIN_PATH" ":" qtPluginPath + "--prefix" "QML2_IMPORT_PATH" ":" qmlImportPath + ]; + + preConfigure = '' + runHook prePreConfigure + + # Set macOS deployment target to match Qt frameworks + export MACOSX_DEPLOYMENT_TARGET=12.0 + + # Copy logos-cpp-sdk headers to expected location + echo "Copying logos-cpp-sdk headers for app..." + mkdir -p ./logos-cpp-sdk/include/cpp + cp -r ${logosSdk}/include/cpp/* ./logos-cpp-sdk/include/cpp/ + + # Also copy core headers + echo "Copying core headers..." + mkdir -p ./logos-cpp-sdk/include/core + cp -r ${logosSdk}/include/core/* ./logos-cpp-sdk/include/core/ + + # Copy SDK library files to lib directory + echo "Copying SDK library files..." + mkdir -p ./logos-cpp-sdk/lib + if [ -f "${logosSdk}/lib/liblogos_sdk.dylib" ]; then + cp "${logosSdk}/lib/liblogos_sdk.dylib" ./logos-cpp-sdk/lib/ + elif [ -f "${logosSdk}/lib/liblogos_sdk.so" ]; then + cp "${logosSdk}/lib/liblogos_sdk.so" ./logos-cpp-sdk/lib/ + elif [ -f "${logosSdk}/lib/liblogos_sdk.a" ]; then + cp "${logosSdk}/lib/liblogos_sdk.a" ./logos-cpp-sdk/lib/ + fi + + runHook postPreConfigure + ''; + + # Additional environment variables for Qt and RPATH cleanup + preFixup = '' + runHook prePreFixup + + # Set up Qt environment variables + export QT_PLUGIN_PATH="${pkgs.qt6.qtbase}/lib/qt-6/plugins" + export QML_IMPORT_PATH="${pkgs.qt6.qtbase}/lib/qt-6/qml" + + # Remove any remaining references to /build/ in binaries and set proper RPATH + find $out -type f -executable -exec sh -c ' + if file "$1" | grep -q "ELF.*executable"; then + # Use patchelf to clean up RPATH if it contains /build/ + if patchelf --print-rpath "$1" 2>/dev/null | grep -q "/build/"; then + echo "Cleaning RPATH for $1" + patchelf --remove-rpath "$1" 2>/dev/null || true + fi + # Set proper RPATH for the main binary + if echo "$1" | grep -q "/logos-blockchain-ui-app$"; then + echo "Setting RPATH for $1" + patchelf --set-rpath "$out/lib" "$1" 2>/dev/null || true + fi + fi + ' _ {} \; + + # Also clean up shared libraries + find $out -name "*.so" -exec sh -c ' + if patchelf --print-rpath "$1" 2>/dev/null | grep -q "/build/"; then + echo "Cleaning RPATH for $1" + patchelf --remove-rpath "$1" 2>/dev/null || true + fi + ' _ {} \; + + runHook prePostFixup + ''; + + configurePhase = '' + runHook preConfigure + + echo "Configuring logos-blockchain-ui-app..." + echo "liblogos: ${logosLiblogos}" + echo "cpp-sdk: ${logosSdk}" + echo "blockchain-module: ${logosBlockchainModule}" + echo "capability-module: ${logosCapabilityModule}" + echo "blockchain-ui: ${logosBlockchainUI}" + echo "logos-design-system: ${logosDesignSystem}" + + # Verify that the built components exist + test -d "${logosLiblogos}" || (echo "liblogos not found" && exit 1) + test -d "${logosSdk}" || (echo "cpp-sdk not found" && exit 1) + test -d "${logosBlockchainModule}" || (echo "blockchain-module not found" && exit 1) + test -d "${logosCapabilityModule}" || (echo "capability-module not found" && exit 1) + test -d "${logosBlockchainUI}" || (echo "blockchain-ui not found" && exit 1) + test -d "${logosDesignSystem}" || (echo "logos-design-system not found" && exit 1) + + cmake -S app -B build \ + -GNinja \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_OSX_DEPLOYMENT_TARGET=12.0 \ + -DCMAKE_INSTALL_RPATH_USE_LINK_PATH=FALSE \ + -DCMAKE_INSTALL_RPATH="" \ + -DCMAKE_SKIP_BUILD_RPATH=TRUE \ + -DLOGOS_LIBLOGOS_ROOT=${logosLiblogos} \ + -DLOGOS_CPP_SDK_ROOT=$(pwd)/logos-cpp-sdk + + runHook postConfigure + ''; + + buildPhase = '' + runHook preBuild + + cmake --build build + echo "logos-blockchain-ui-app built successfully!" + + runHook postBuild + ''; + + installPhase = '' + runHook preInstall + + # Create output directories + mkdir -p $out/bin $out/lib $out/modules + + # Install our app binary + if [ -f "build/bin/logos-blockchain-ui-app" ]; then + cp build/bin/logos-blockchain-ui-app "$out/bin/" + echo "Installed logos-blockchain-ui-app binary" + fi + + # Copy the core binaries from liblogos + if [ -f "${logosLiblogos}/bin/logoscore" ]; then + cp -L "${logosLiblogos}/bin/logoscore" "$out/bin/" + echo "Installed logoscore binary" + fi + if [ -f "${logosLiblogos}/bin/logos_host" ]; then + cp -L "${logosLiblogos}/bin/logos_host" "$out/bin/" + echo "Installed logos_host binary" + fi + + # Copy required shared libraries from liblogos + if ls "${logosLiblogos}/lib/"liblogos_core.* >/dev/null 2>&1; then + cp -L "${logosLiblogos}/lib/"liblogos_core.* "$out/lib/" || true + fi + + # Copy SDK library if it exists + if ls "${logosSdk}/lib/"liblogos_sdk.* >/dev/null 2>&1; then + cp -L "${logosSdk}/lib/"liblogos_sdk.* "$out/lib/" || true + fi + + # Determine platform-specific plugin extension + OS_EXT="so" + case "$(uname -s)" in + Darwin) OS_EXT="dylib";; + Linux) OS_EXT="so";; + MINGW*|MSYS*|CYGWIN*) OS_EXT="dll";; + esac + + # Copy module plugins into the modules directory + if [ -f "${logosCapabilityModule}/lib/capability_module_plugin.$OS_EXT" ]; then + cp -L "${logosCapabilityModule}/lib/capability_module_plugin.$OS_EXT" "$out/modules/" + fi + if [ -f "${logosBlockchainModule}/lib/liblogos_blockchain_module.$OS_EXT" ]; then + cp -L "${logosBlockchainModule}/lib/liblogos_blockchain_module.$OS_EXT" "$out/modules/" + fi + + # Copy liblogos_blockchain library to modules directory (needed by blockchain module) + if [ -f "${logosBlockchainModule}/lib/liblogos_blockchain.$OS_EXT" ]; then + cp -L "${logosBlockchainModule}/lib/liblogos_blockchain.$OS_EXT" "$out/modules/" + fi + + # Copy blockchain_ui Qt plugin to root directory (not modules, as it's loaded differently) + if [ -f "${logosBlockchainUI}/lib/blockchain_ui.$OS_EXT" ]; then + cp -L "${logosBlockchainUI}/lib/blockchain_ui.$OS_EXT" "$out/" + fi + + # Copy design system QML module (Logos/DesignSystem) for runtime + if [ -d "${logosDesignSystem}/lib/Logos/DesignSystem" ]; then + mkdir -p "$out/lib/Logos" + cp -R "${logosDesignSystem}/lib/Logos/DesignSystem" "$out/lib/Logos/" + echo "Copied Logos Design System to lib/Logos/DesignSystem/" + fi + + # Create a README for reference + cat > $out/README.txt < +#include +#include + +BlockchainBackend::BlockchainBackend(LogosAPI* logosAPI, QObject* parent) + : QObject(parent), + m_status(NotStarted), + m_configPath(""), + m_logos(nullptr), + m_blockchainModule(nullptr) +{ + + m_configPath = QString::fromUtf8(qgetenv("LB_CONFIG_PATH")); + + if (!logosAPI) { + logosAPI = new LogosAPI("core", this); + } + + m_logos = new LogosModules(logosAPI); + + if (!m_logos) { + setStatus(ErrorNotInitialized); + return; + } + + m_blockchainModule = &m_logos->liblogos_blockchain_module; + + if (m_blockchainModule && !m_blockchainModule->on("newBlock", [this](const QVariantList& data) { + onNewBlock(data); + })) { + setStatus(ErrorSubscribeFailed); + } +} + +BlockchainBackend::~BlockchainBackend() +{ + stopBlockchain(); +} + +void BlockchainBackend::setStatus(BlockchainStatus newStatus) +{ + if (m_status != newStatus) { + m_status = newStatus; + emit statusChanged(); + } +} + +void BlockchainBackend::clearLogs() +{ + emit logsCleared(); +} + +void BlockchainBackend::setConfigPath(const QString& path) +{ + const QString localPath = QUrl::fromUserInput(path).toLocalFile(); + if (m_configPath != localPath) { + m_configPath = localPath; + emit configPathChanged(); + } +} + +void BlockchainBackend::startBlockchain() +{ + if (!m_blockchainModule) { + setStatus(ErrorNotInitialized); + return; + } + + setStatus(Starting); + + int result = m_blockchainModule->start(m_configPath, QString()); + + if (result == 0 || result == 1) { + setStatus(Running); + } else if (result == 2) { + setStatus(ErrorConfigMissing); + } else if (result == 3) { + setStatus(ErrorStartFailed); + } else { + setStatus(ErrorStartFailed); + } +} + +void BlockchainBackend::stopBlockchain() +{ + if (m_status != Running && m_status != Starting) { + return; + } + + if (!m_blockchainModule) { + setStatus(ErrorNotInitialized); + return; + } + + setStatus(Stopping); + + int result = m_blockchainModule->stop(); + + if (result == 0 || result == 1) { + setStatus(Stopped); + } else { + setStatus(ErrorStopFailed); + } +} + +void BlockchainBackend::onNewBlock(const QVariantList& data) +{ + QString timestamp = QDateTime::currentDateTime().toString("HH:mm:ss"); + if (!data.isEmpty()) { + QString blockInfo = data.first().toString(); + QString shortInfo = blockInfo.left(80); + if (blockInfo.length() > 80) { + shortInfo += "..."; + } + emit newBlockMessage(QString("[%1] 📦 New block: %2\n").arg(timestamp, shortInfo)); + } else { + emit newBlockMessage(QString("[%1] 📦 New block (no data)\n").arg(timestamp)); + } +} diff --git a/src/BlockchainBackend.h b/src/BlockchainBackend.h new file mode 100644 index 0000000..1e16da3 --- /dev/null +++ b/src/BlockchainBackend.h @@ -0,0 +1,63 @@ +#pragma once + +#include +#include +#include +#include "logos_api.h" +#include "logos_api_client.h" +#include "logos_sdk.h" + +// Type of the blockchain module proxy (has start(), stop(), on() etc.) +using BlockchainModuleProxy = std::remove_reference_t().liblogos_blockchain_module)>; + +class BlockchainBackend : public QObject { + Q_OBJECT + +public: + enum BlockchainStatus { + NotStarted = 0, + Starting, + Running, + Stopping, + Stopped, + Error, + ErrorNotInitialized, + ErrorConfigMissing, + ErrorStartFailed, + ErrorStopFailed, + ErrorSubscribeFailed + }; + Q_ENUM(BlockchainStatus) + + Q_PROPERTY(BlockchainStatus status READ status NOTIFY statusChanged) + Q_PROPERTY(QString configPath READ configPath WRITE setConfigPath NOTIFY configPathChanged) + + explicit BlockchainBackend(LogosAPI* logosAPI = nullptr, QObject* parent = nullptr); + ~BlockchainBackend(); + + BlockchainStatus status() const { return m_status; } + QString configPath() const { return m_configPath; } + + void setConfigPath(const QString& path); + Q_INVOKABLE void clearLogs(); + +public slots: + Q_INVOKABLE void startBlockchain(); + Q_INVOKABLE void stopBlockchain(); + void onNewBlock(const QVariantList& data); + +signals: + void statusChanged(); + void configPathChanged(); + void newBlockMessage(const QString& message); + void logsCleared(); + +private: + void setStatus(BlockchainStatus newStatus); + + BlockchainStatus m_status; + QString m_configPath; + + LogosModules* m_logos; + BlockchainModuleProxy* m_blockchainModule; +}; diff --git a/src/BlockchainPlugin.cpp b/src/BlockchainPlugin.cpp new file mode 100644 index 0000000..896777b --- /dev/null +++ b/src/BlockchainPlugin.cpp @@ -0,0 +1,40 @@ +#include "BlockchainPlugin.h" +#include "BlockchainBackend.h" +#include +#include +#include +#include +#include +#include + +QWidget* BlockchainPlugin::createWidget(LogosAPI* logosAPI) { + qDebug() << "BlockchainPlugin::createWidget called"; + + QQuickWidget* quickWidget = new QQuickWidget(); + quickWidget->setResizeMode(QQuickWidget::SizeRootObjectToView); + + qmlRegisterType("BlockchainBackend", 1, 0, "BlockchainBackend"); + + BlockchainBackend* backend = new BlockchainBackend(logosAPI, quickWidget); + + quickWidget->rootContext()->setContextProperty("backend", backend); + + QString qmlPath = "qrc:/BlockchainView.qml"; + QString envPath = qgetenv("BLOCKCHAIN_UI_QML_PATH"); + if (!envPath.isEmpty() && QFile::exists(envPath)) { + qmlPath = QUrl::fromLocalFile(QFileInfo(envPath).absoluteFilePath()).toString(); + qDebug() << "Loading QML from file system:" << qmlPath; + } + + quickWidget->setSource(QUrl(qmlPath)); + + if (quickWidget->status() == QQuickWidget::Error) { + qWarning() << "BlockchainPlugin: Failed to load QML:" << quickWidget->errors(); + } + + return quickWidget; +} + +void BlockchainPlugin::destroyWidget(QWidget* widget) { + delete widget; +} diff --git a/src/BlockchainPlugin.h b/src/BlockchainPlugin.h new file mode 100644 index 0000000..0480555 --- /dev/null +++ b/src/BlockchainPlugin.h @@ -0,0 +1,14 @@ +#pragma once + +#include +#include + +class BlockchainPlugin : public QObject, public IComponent { + Q_OBJECT + Q_INTERFACES(IComponent) + Q_PLUGIN_METADATA(IID IComponent_iid FILE "metadata.json") + +public: + Q_INVOKABLE QWidget* createWidget(LogosAPI* logosAPI = nullptr) override; + void destroyWidget(QWidget* widget) override; +}; diff --git a/src/BlockchainView.qml b/src/BlockchainView.qml new file mode 100644 index 0000000..e82abc0 --- /dev/null +++ b/src/BlockchainView.qml @@ -0,0 +1,291 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import QtQuick.Dialogs +import QtCore + +import BlockchainBackend +import Logos.DesignSystem + +Rectangle { + id: root + + QtObject { + id: _d + function getStatusString(status) { + switch(status) { + case BlockchainBackend.NotStarted: return "Not Started"; + case BlockchainBackend.Starting: return "Starting..."; + case BlockchainBackend.Running: return "Running"; + case BlockchainBackend.Stopping: return "Stopping..."; + case BlockchainBackend.Stopped: return "Stopped"; + case BlockchainBackend.Error: return "Error"; + case BlockchainBackend.ErrorNotInitialized: return "Error: Module not initialized"; + case BlockchainBackend.ErrorConfigMissing: return "Error: Config path missing"; + case BlockchainBackend.ErrorStartFailed: return "Error: Failed to start node"; + case BlockchainBackend.ErrorStopFailed: return "Error: Failed to stop node"; + case BlockchainBackend.ErrorSubscribeFailed: return "Error: Failed to subscribe to events"; + default: return "Unknown"; + } + } + function getStatusColor(status) { + switch(status) { + case BlockchainBackend.Running: return Theme.palette.success; + case BlockchainBackend.Starting: return Theme.palette.warning; + case BlockchainBackend.Stopping: return Theme.palette.warning; + case BlockchainBackend.NotStarted: return Theme.palette.error; + case BlockchainBackend.Stopped: return Theme.palette.error; + case BlockchainBackend.Error: + case BlockchainBackend.ErrorNotInitialized: + case BlockchainBackend.ErrorConfigMissing: + case BlockchainBackend.ErrorStartFailed: + case BlockchainBackend.ErrorStopFailed: + case BlockchainBackend.ErrorSubscribeFailed: return Theme.palette.error; + default: return Theme.palette.textSecondary; + } + } + } + + color: Theme.palette.background + + Connections { + target: backend + function onLogMessage(message) { + logsContainer.logsText += message + } + function onNewBlockMessage(message) { + logsContainer.logsText += message + } + function onLogsCleared() { + logsContainer.logsText = "" + } + } + + SplitView { + anchors.fill: parent + anchors.margins: Theme.spacing.large + orientation: Qt.Vertical + + // Tpp: Status and Controls + ColumnLayout { + SplitView.fillWidth: true + SplitView.minimumHeight: 200 + SplitView.preferredHeight: implicitHeight + spacing: Theme.spacing.large + + // Status Card + Rectangle { + Layout.alignment: Qt.AlignHCenter + Layout.preferredWidth: parent.width * 0.9 + implicitHeight: content.implicitHeight + 2 * Theme.spacing.large + Layout.preferredHeight: implicitHeight + color: Theme.palette.backgroundTertiary + radius: Theme.spacing.radiusLarge + border.color: Theme.palette.border + border.width: 1 + + ColumnLayout { + id: content + + anchors.left: parent.left + anchors.right: parent.right + anchors.top: parent.top + anchors.margins: Theme.spacing.large + spacing: Theme.spacing.medium + + Text { + Layout.alignment: Qt.AlignLeft + font.pixelSize: 14//Theme.typography.primaryText + font.bold: true + text: _d.getStatusString(backend.status) + color: _d.getStatusColor(backend.status) + } + + // Chain info + Text { + Layout.alignment: Qt.AlignLeft + Layout.topMargin: -Theme.spacing.medium + text: "Mainnet - chain ID 1" + font.pixelSize: 12//Theme.typography.secondaryText + color: Theme.palette.textSecondary + } + + // Start/Stop Button + Button { + Layout.alignment: Qt.AlignHCenter + Layout.preferredWidth: parent.width + Layout.preferredHeight: 50 + + background: Rectangle { + color: parent.pressed || parent.hovered ? + Theme.palette.backgroundMuted: + Theme.palette.backgroundSecondary + radius: Theme.spacing.radiusXlarge + border.color: Theme.palette.border + border.width: 1 + } + + enabled: !!backend.configPath && backend.status !== BlockchainBackend.Starting && backend.status !== BlockchainBackend.Stopping + text: backend.status === BlockchainBackend.Running ? "Stop Node" : "Start Node" + onClicked: { + if (backend.status === BlockchainBackend.Running) { + backend.stopBlockchain() + } else { + backend.startBlockchain() + } + } + } + } + } + + // Status Card + Rectangle { + Layout.alignment: Qt.AlignHCenter + Layout.preferredWidth: parent.width * 0.9 + implicitHeight: content2.implicitHeight + 2 * Theme.spacing.large + Layout.preferredHeight: implicitHeight + color: Theme.palette.backgroundTertiary + radius: Theme.spacing.radiusLarge + border.color: Theme.palette.border + border.width: 1 + + RowLayout { + id: content2 + + anchors.left: parent.left + anchors.right: parent.right + anchors.top: parent.top + anchors.margins: Theme.spacing.large + spacing: Theme.spacing.medium + + ColumnLayout { + Text { + text: "Current Config: " + font.pixelSize: 14//Theme.typography.primary + font.bold: true + color: Theme.palette.text + } + // Config Path (collapsible/minimal) + Text { + text: (backend.configPath || "No file selected") + font.pixelSize: 12//Theme.typography.secondary + color: Theme.palette.textSecondary + elide: Text.ElideMiddle + } + } + + // Choose New Config file + Button { + Layout.alignment: Qt.AlignRight + Layout.preferredWidth: 100 + Layout.preferredHeight: 50 + + background: Rectangle { + color: parent.pressed || parent.hovered ? + Theme.palette.backgroundMuted: + Theme.palette.backgroundSecondary + radius: Theme.spacing.radiusXlarge + border.color: Theme.palette.border + border.width: 1 + } + + text: qsTr("Change") + onClicked: { + fileDialog.open() + } + } + } + + Item { Layout.fillHeight: true } + } + } + + // Right: Logs + Item { + id: logsPane + SplitView.fillWidth: true + SplitView.minimumHeight: 200 + SplitView.fillHeight: true + + ColumnLayout { + anchors.fill: parent + anchors.margins: Theme.spacing.large + spacing: Theme.spacing.medium + + // Logs header + RowLayout { + Layout.fillWidth: true + spacing: Theme.spacing.medium + + Text { + text: "Logs" + font.pixelSize: Theme.typography.secondaryText + font.bold: true + color: Theme.palette.text + } + + Item { Layout.fillWidth: true } + + Button { + text: "Clear" + font.pixelSize: Theme.typography.secondaryText + Layout.preferredWidth: 80 + Layout.preferredHeight: 32 + onClicked: backend.clearLogs() + } + } + + // Logs view (accumulated from logMessage signals) + Item { + id: logsContainer + Layout.fillWidth: true + Layout.fillHeight: true + + property string logsText: "" + + + ScrollView { + anchors.fill: parent + clip: true + + background: Rectangle { + color: Theme.palette.backgroundSecondary + radius: Theme.spacing.radiusLarge + border.color: Theme.palette.border + border.width: 1 + } + + TextArea { + id: logsTextArea + readOnly: true + text: logsContainer.logsText || "No logs yet..." + font.pixelSize: Theme.typography.secondaryText + font.family: "Monaco, Menlo, Courier, monospace" + wrapMode: TextArea.Wrap + selectByMouse: true + color: Theme.palette.text + padding: Theme.spacing.medium + + background: Rectangle { + color: "transparent" + } + + onTextChanged: { + cursorPosition = text.length + } + } + } + } + } + } + } + FileDialog { + id: fileDialog + modality: Qt.NonModal + nameFilters: ["YAML files (*.yaml)"] + currentFolder: StandardPaths.standardLocations(StandardPaths.DocumentsLocation)[0] + onAccepted: { + backend.configPath = selectedFile + } + } +} diff --git a/src/blockchain_resources.qrc b/src/blockchain_resources.qrc new file mode 100644 index 0000000..3eaa825 --- /dev/null +++ b/src/blockchain_resources.qrc @@ -0,0 +1,5 @@ + + + BlockchainView.qml + +