2026-07-13 21:01:40 +02:00
|
|
|
{
|
2026-08-19 01:36:02 -03:00
|
|
|
description = "LEZ programs — host client modules and FFIs";
|
2026-07-13 21:01:40 +02:00
|
|
|
|
|
|
|
|
inputs = {
|
|
|
|
|
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
|
|
|
|
flake-utils.url = "github:numtide/flake-utils";
|
|
|
|
|
crane.url = "github:ipetkov/crane";
|
|
|
|
|
rust-overlay = {
|
|
|
|
|
url = "github:oxalica/rust-overlay";
|
|
|
|
|
inputs.nixpkgs.follows = "nixpkgs";
|
|
|
|
|
};
|
2026-07-13 22:20:12 +02:00
|
|
|
|
|
|
|
|
# The AMM QML UI module (apps/amm) is built from this same flake so it can
|
2026-07-29 15:57:24 +02:00
|
|
|
# reference the amm_ffi crate package via `self` — no filesystem
|
2026-07-13 22:20:12 +02:00
|
|
|
# path or git-remote reference to this repo is needed (see apps/amm/flake.nix
|
|
|
|
|
# history: a `git+file://` URL pointing at a local checkout is
|
|
|
|
|
# machine-specific and not portable).
|
|
|
|
|
logos-module-builder.url = "github:logos-co/logos-module-builder";
|
|
|
|
|
|
|
|
|
|
# Core wallet module (the LEZ wallet FFI Qt plugin). The input name must
|
2026-07-17 16:13:29 +02:00
|
|
|
# match the metadata.json `dependencies` entry so the builder can resolve it
|
|
|
|
|
# as a module dependency.
|
|
|
|
|
#
|
|
|
|
|
# Fork of logos-blockchain/logos-execution-zone-module @ d70225ced with the
|
|
|
|
|
# QtRO serialization fix: send_generic_public_transaction's `instruction` uses
|
|
|
|
|
# a byte-string IPC type so the args survive the cross-process boundary (at
|
|
|
|
|
# d70225ced the API already takes program_id_hex instead of program_elf/deps).
|
|
|
|
|
# See docs/amm-swap-qtro-serialization-bug.md.
|
|
|
|
|
logos_execution_zone = {
|
|
|
|
|
url = "github:gravityblast/logos-execution-zone-module?ref=fix/generic-tx-instruction-bstr";
|
|
|
|
|
|
|
|
|
|
# Override the module's pinned LEZ monorepo (logos-execution-zone) to the
|
|
|
|
|
# SAME rev the target sequencer runs (415964d7): the wallet client and the
|
|
|
|
|
# sequencer must agree on the JSON-RPC API, or tx submission fails at
|
|
|
|
|
# runtime with `MethodNotFound`. 415964d7's wallet_ffi takes a program id
|
|
|
|
|
# for send_generic_public_transaction, matching the d70225ced module.
|
|
|
|
|
inputs.logos-execution-zone.url =
|
|
|
|
|
"github:logos-blockchain/logos-execution-zone?rev=415964d7f9043a1bfe28da8d0e8b3a6f64abb258";
|
|
|
|
|
};
|
2026-08-19 01:36:02 -03:00
|
|
|
|
2026-07-13 21:01:40 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
outputs =
|
2026-07-13 22:20:12 +02:00
|
|
|
inputs@{ self, nixpkgs, flake-utils, crane, rust-overlay, logos-module-builder, logos_execution_zone, ... }:
|
|
|
|
|
let
|
|
|
|
|
crateOutputs = flake-utils.lib.eachDefaultSystem (
|
2026-07-13 21:01:40 +02:00
|
|
|
system:
|
|
|
|
|
let
|
|
|
|
|
pkgs = import nixpkgs {
|
|
|
|
|
inherit system;
|
|
|
|
|
overlays = [ rust-overlay.overlays.default ];
|
|
|
|
|
};
|
|
|
|
|
# Honor the repo's pinned toolchain (rust-toolchain.toml -> 1.94.0).
|
|
|
|
|
rustToolchain = pkgs.rust-bin.fromRustupToolchainFile ./rust-toolchain.toml;
|
|
|
|
|
craneLib = (crane.mkLib pkgs).overrideToolchain rustToolchain;
|
|
|
|
|
|
2026-08-19 01:36:02 -03:00
|
|
|
# Whole Cargo workspace, excluding build outputs and non-Rust assets.
|
|
|
|
|
# Crane still sees Cargo.lock and every path dependency, while local
|
|
|
|
|
# target directories cannot become multi-gigabyte Nix source snapshots.
|
|
|
|
|
src = craneLib.cleanCargoSource ./.;
|
2026-07-13 21:01:40 +02:00
|
|
|
|
2026-08-19 01:36:02 -03:00
|
|
|
# Scope every build to one host FFI package. The workspace also has
|
|
|
|
|
# methods crates whose build scripts compile RISC Zero guests; package
|
|
|
|
|
# scoping keeps those target-specific builds out of host module builds.
|
|
|
|
|
mkHostFfi =
|
|
|
|
|
{
|
|
|
|
|
package,
|
|
|
|
|
sourceDir,
|
|
|
|
|
header,
|
|
|
|
|
}:
|
|
|
|
|
let
|
|
|
|
|
commonArgs = {
|
|
|
|
|
inherit src;
|
|
|
|
|
strictDeps = true;
|
|
|
|
|
pname = package;
|
|
|
|
|
version = "0.1.0";
|
|
|
|
|
cargoExtraArgs = "-p ${package}";
|
|
|
|
|
doCheck = false;
|
|
|
|
|
# cbindgen runs as a Rust build-dependency from build.rs.
|
|
|
|
|
};
|
|
|
|
|
cargoArtifacts = craneLib.buildDepsOnly commonArgs;
|
|
|
|
|
in
|
|
|
|
|
craneLib.buildPackage (
|
|
|
|
|
commonArgs
|
|
|
|
|
// {
|
|
|
|
|
inherit cargoArtifacts;
|
|
|
|
|
postInstall =
|
|
|
|
|
''
|
|
|
|
|
mkdir -p $out/include
|
|
|
|
|
cp ${sourceDir}/include/${header} $out/include/
|
|
|
|
|
''
|
|
|
|
|
+ pkgs.lib.optionalString pkgs.stdenv.isDarwin ''
|
|
|
|
|
# Use an absolute store install-name because the module
|
|
|
|
|
# builder does not stage external dylibs beside the plugin.
|
|
|
|
|
if [ -f $out/lib/lib${package}.dylib ]; then
|
|
|
|
|
install_name_tool -id "$out/lib/lib${package}.dylib" $out/lib/lib${package}.dylib
|
|
|
|
|
fi
|
|
|
|
|
'';
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
ammFfi = mkHostFfi {
|
|
|
|
|
package = "amm_ffi";
|
|
|
|
|
sourceDir = "modules/amm/ffi";
|
|
|
|
|
header = "amm_ffi.h";
|
2026-07-13 21:01:40 +02:00
|
|
|
};
|
|
|
|
|
|
2026-08-19 01:36:02 -03:00
|
|
|
tokenFfi = mkHostFfi {
|
|
|
|
|
package = "token_ffi";
|
|
|
|
|
sourceDir = "modules/token/ffi";
|
|
|
|
|
header = "token_ffi.h";
|
|
|
|
|
};
|
2026-07-13 21:01:40 +02:00
|
|
|
in
|
|
|
|
|
{
|
2026-07-29 15:57:24 +02:00
|
|
|
packages.default = ammFfi;
|
|
|
|
|
packages.amm_ffi = ammFfi;
|
2026-08-19 01:36:02 -03:00
|
|
|
packages.token_ffi = tokenFfi;
|
2026-07-13 21:01:40 +02:00
|
|
|
}
|
|
|
|
|
);
|
2026-07-13 22:20:12 +02:00
|
|
|
|
2026-07-29 15:57:24 +02:00
|
|
|
# The AMM QML UI module (apps/amm). It links no amm_ffi library of its
|
2026-07-22 13:56:42 +02:00
|
|
|
# own — the AMM logic lives in the amm_module core module, which the UI
|
|
|
|
|
# depends on (declared in apps/amm/metadata.json, reached via
|
|
|
|
|
# modules().amm_module in the backend) alongside the logos_execution_zone
|
|
|
|
|
# wallet module.
|
2026-07-13 22:20:12 +02:00
|
|
|
appOutputs = logos-module-builder.lib.mkLogosQmlModule {
|
|
|
|
|
src = ./apps/amm;
|
|
|
|
|
configFile = ./apps/amm/metadata.json;
|
2026-07-22 13:56:42 +02:00
|
|
|
# amm_module isn't a flake input — it's built from this same flake below
|
|
|
|
|
# (ammModuleOutputs) — so inject it into flakeInputs under its dependency
|
|
|
|
|
# name so the builder's dependency resolver finds it (reads its .lidl to
|
|
|
|
|
# generate the modules().amm_module wrapper). The wallet module stays a
|
|
|
|
|
# direct dep too, so both the UI and amm_module resolve the one shared
|
|
|
|
|
# wallet instance.
|
|
|
|
|
flakeInputs = inputs // { amm_module = ammModuleOutputs; };
|
2026-07-29 15:57:24 +02:00
|
|
|
# The UI links no external lib of its own — the AMM brain (amm_ffi) is
|
2026-07-22 13:56:42 +02:00
|
|
|
# linked by amm_module, which the UI reaches via modules().amm_module.
|
|
|
|
|
externalLibInputs = { };
|
2026-07-15 11:55:39 -03:00
|
|
|
# The AMM UI links the shared C++ wallet access lib and bundles the
|
|
|
|
|
# Logos.Wallet QML module (apps/shared/wallet). apps/amm/flake.nix wires
|
|
|
|
|
# these via its `shared_wallet` input; when built from this root flake
|
|
|
|
|
# the source lives in-tree, so point CMake straight at it and stage the
|
|
|
|
|
# built QML module the same way. Keep in sync with apps/amm/flake.nix.
|
|
|
|
|
preConfigure = ''
|
|
|
|
|
cmakeFlagsArray+=("-DLOGOS_WALLET_SOURCE_DIR=${./apps/shared/wallet}")
|
2026-08-14 20:29:55 -03:00
|
|
|
cmakeFlagsArray+=("-DLOGOS_WALLET_GENERATED_DIR=$PWD/generated_code/include")
|
2026-07-15 11:55:39 -03:00
|
|
|
'';
|
|
|
|
|
postInstall = ''
|
2026-08-14 20:29:55 -03:00
|
|
|
walletQmlDescriptor="$(find "$PWD" -type f -path '*/shared-wallet/qml/Logos/Wallet/qmldir' -print -quit)"
|
|
|
|
|
if [ -z "$walletQmlDescriptor" ]; then
|
2026-07-15 11:55:39 -03:00
|
|
|
echo "Built Logos.Wallet QML module not found"
|
|
|
|
|
exit 1
|
|
|
|
|
fi
|
2026-08-14 20:29:55 -03:00
|
|
|
walletQmlDir="$(dirname "$walletQmlDescriptor")"
|
2026-08-19 14:09:15 +02:00
|
|
|
# Stage Logos.Wallet at the plugin ROOT as PURE QML (strip every
|
|
|
|
|
# plugin/resource directive). Same rationale as tokenAppOutputs below:
|
|
|
|
|
# Basecamp rejects `prefer :/qt/qml/...` with "Invalid null URL", and
|
|
|
|
|
# keeping the module at the root (never under qml/) avoids leaking
|
|
|
|
|
# qml/NavBar.qml et al. into Basecamp's shared import path where it
|
|
|
|
|
# would collide with other plugins' identically-named types. Standalone
|
|
|
|
|
# reaches this root module via QML_IMPORT_PATH (see the amm-ui app
|
|
|
|
|
# wrapper). Keep in sync with tokenAppOutputs / apps/amm/flake.nix.
|
2026-08-14 20:29:55 -03:00
|
|
|
walletQmlInstallDir="$out/lib/Logos/Wallet"
|
|
|
|
|
mkdir -p "$walletQmlInstallDir"
|
|
|
|
|
cp -r "$walletQmlDir/." "$walletQmlInstallDir/"
|
2026-08-19 14:09:15 +02:00
|
|
|
grep -vE '^(linktarget|optional plugin|plugin|classname|typeinfo|prefer)([[:space:]]|$)' \
|
|
|
|
|
"$walletQmlInstallDir/qmldir" > "$walletQmlInstallDir/qmldir.pureqml"
|
|
|
|
|
mv "$walletQmlInstallDir/qmldir.pureqml" "$walletQmlInstallDir/qmldir"
|
2026-08-14 20:29:55 -03:00
|
|
|
test -f "$walletQmlInstallDir/qmldir"
|
|
|
|
|
'';
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
# Token QML UI (apps/token). This UI consumes the token_module core
|
|
|
|
|
# module through its generated Logos SDK and the reusable shared wallet
|
|
|
|
|
# access/QML module. Keep the output separate so Basecamp can install or
|
|
|
|
|
# run `token-ui` independently from the AMM UI.
|
|
|
|
|
tokenAppOutputs = logos-module-builder.lib.mkLogosQmlModule {
|
|
|
|
|
src = ./apps/token;
|
|
|
|
|
configFile = ./apps/token/metadata.json;
|
|
|
|
|
flakeInputs = inputs // { token_module = tokenModuleOutputs; };
|
|
|
|
|
externalLibInputs = { };
|
|
|
|
|
preConfigure = ''
|
|
|
|
|
cmakeFlagsArray+=("-DLOGOS_WALLET_SOURCE_DIR=${./apps/shared/wallet}")
|
|
|
|
|
cmakeFlagsArray+=("-DLOGOS_WALLET_GENERATED_DIR=$PWD/generated_code/include")
|
|
|
|
|
'';
|
|
|
|
|
postInstall = ''
|
|
|
|
|
walletQmlDescriptor="$(find "$PWD" -type f -path '*/shared-wallet/qml/Logos/Wallet/qmldir' -print -quit)"
|
|
|
|
|
if [ -z "$walletQmlDescriptor" ]; then
|
|
|
|
|
echo "Built Logos.Wallet QML module not found"
|
|
|
|
|
exit 1
|
|
|
|
|
fi
|
|
|
|
|
walletQmlDir="$(dirname "$walletQmlDescriptor")"
|
2026-08-15 00:39:29 -03:00
|
|
|
# Stage the shared Logos.Wallet module at the plugin ROOT (NOT under
|
|
|
|
|
# qml/), and strip every plugin/resource directive from its qmldir so
|
|
|
|
|
# it loads as PURE QML from the co-located .qml files. Two reasons:
|
|
|
|
|
# 1. Basecamp's QML sandbox rejects `prefer :/qt/qml/...` (and the
|
|
|
|
|
# `classname`/`typeinfo`/`linktarget` it pairs with) with
|
|
|
|
|
# "Invalid null URL" — that compiled resource isn't registered
|
|
|
|
|
# there. The .qml files are physically present, so the module
|
|
|
|
|
# resolves without any native plugin; Token drives wallet ops
|
|
|
|
|
# through TokenUiBackend regardless.
|
|
|
|
|
# 2. Basecamp adds the *containing dir* of every discovered Logos.*
|
|
|
|
|
# module to a shared QML import path. Keeping Logos.Wallet at the
|
|
|
|
|
# root means only the root is shared — putting it under qml/ would
|
|
|
|
|
# also leak qml/NavBar.qml et al. into that shared namespace and
|
|
|
|
|
# collide with other plugins' identically-named types (e.g. amm's
|
|
|
|
|
# NavBar). Standalone reaches this root module via QML_IMPORT_PATH
|
|
|
|
|
# (see the token-ui app wrapper), not a qml/ stub. Keep in sync
|
|
|
|
|
# with apps/amm.
|
2026-07-15 11:55:39 -03:00
|
|
|
walletQmlInstallDir="$out/lib/Logos/Wallet"
|
|
|
|
|
mkdir -p "$walletQmlInstallDir"
|
|
|
|
|
cp -r "$walletQmlDir/." "$walletQmlInstallDir/"
|
2026-08-15 00:39:29 -03:00
|
|
|
grep -vE '^(linktarget|optional plugin|plugin|classname|typeinfo|prefer)([[:space:]]|$)' \
|
|
|
|
|
"$walletQmlInstallDir/qmldir" > "$walletQmlInstallDir/qmldir.pureqml"
|
|
|
|
|
mv "$walletQmlInstallDir/qmldir.pureqml" "$walletQmlInstallDir/qmldir"
|
2026-07-15 11:55:39 -03:00
|
|
|
test -f "$walletQmlInstallDir/qmldir"
|
|
|
|
|
'';
|
2026-07-13 22:20:12 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
# Expose the AMM QML UI as a NAMED app/package (`amm-ui`) rather than
|
|
|
|
|
# `<sys>.default` — the repo is expected to grow more UIs over time,
|
|
|
|
|
# each runnable via `nix run .#<name>`. `appOutputs.apps.<sys>.default`
|
|
|
|
|
# and `appOutputs.packages.<sys>.default` (the UI launcher and its
|
|
|
|
|
# bundle, respectively) are renamed to `amm-ui`; no `default` survives
|
|
|
|
|
# for either attribute set.
|
|
|
|
|
appApps = appOutputs.apps or { };
|
|
|
|
|
appPkgs = appOutputs.packages or { };
|
2026-08-14 20:29:55 -03:00
|
|
|
tokenAppApps = tokenAppOutputs.apps or { };
|
|
|
|
|
tokenAppPkgs = tokenAppOutputs.packages or { };
|
2026-07-13 22:20:12 +02:00
|
|
|
|
2026-08-15 00:39:29 -03:00
|
|
|
# Keep the token UI's Basecamp install artifacts addressable after the
|
|
|
|
|
# core token module is merged into the same package set. Both builders
|
|
|
|
|
# expose an `lgx` attribute, so a named alias prevents the core module
|
|
|
|
|
# package from shadowing the UI package.
|
|
|
|
|
tokenUiPackages = builtins.mapAttrs (
|
|
|
|
|
system: attrs:
|
|
|
|
|
(if attrs ? lgx then { token-ui-lgx = attrs.lgx; } else { })
|
|
|
|
|
// (if attrs ? lgx-portable then { token-ui-lgx-portable = attrs.lgx-portable; } else { })
|
|
|
|
|
// (if attrs ? install then { token-ui-install = attrs.install; } else { })
|
|
|
|
|
// (if attrs ? install-portable then { token-ui-install-portable = attrs.install-portable; } else { })
|
|
|
|
|
) tokenAppPkgs;
|
|
|
|
|
|
2026-08-19 14:09:15 +02:00
|
|
|
# Same aliasing for the AMM UI's Basecamp install artifacts, so its lgx
|
|
|
|
|
# isn't shadowed by the amm core module's bare `lgx` in the merged set.
|
|
|
|
|
ammUiPackages = builtins.mapAttrs (
|
|
|
|
|
system: attrs:
|
|
|
|
|
(if attrs ? lgx then { amm-ui-lgx = attrs.lgx; } else { })
|
|
|
|
|
// (if attrs ? lgx-portable then { amm-ui-lgx-portable = attrs.lgx-portable; } else { })
|
|
|
|
|
// (if attrs ? install then { amm-ui-install = attrs.install; } else { })
|
|
|
|
|
// (if attrs ? install-portable then { amm-ui-install-portable = attrs.install-portable; } else { })
|
|
|
|
|
) appPkgs;
|
|
|
|
|
|
2026-07-22 13:56:42 +02:00
|
|
|
# AMM core module (modules/amm): the AMM business logic as a headless
|
2026-07-29 15:57:24 +02:00
|
|
|
# `core` Logos module. It links the amm_ffi crate (the transport-
|
2026-07-22 13:56:42 +02:00
|
|
|
# independent AMM brain, resolved via `self`) and depends on the
|
|
|
|
|
# logos_execution_zone wallet module (declared in modules/amm/metadata.json,
|
|
|
|
|
# reached via modules().logos_execution_zone in the impl). Exposed as the
|
|
|
|
|
# `amm-module` package; no UI/app output.
|
|
|
|
|
ammModuleOutputs = logos-module-builder.lib.mkLogosModule {
|
|
|
|
|
src = ./modules/amm;
|
|
|
|
|
configFile = ./modules/amm/metadata.json;
|
|
|
|
|
flakeInputs = inputs;
|
|
|
|
|
externalLibInputs = {
|
2026-07-29 15:57:24 +02:00
|
|
|
amm_ffi = { input = self; packages.default = "amm_ffi"; };
|
2026-07-22 13:56:42 +02:00
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
ammModulePkgs = ammModuleOutputs.packages or { };
|
|
|
|
|
|
2026-08-19 14:09:15 +02:00
|
|
|
# Alias the AMM core module's Basecamp install artifacts (explicit
|
|
|
|
|
# `amm-module-lgx` / `amm-module-install`), same collision reason as the
|
|
|
|
|
# token module aliases below.
|
|
|
|
|
ammModuleAliases = builtins.mapAttrs (
|
|
|
|
|
system: attrs:
|
|
|
|
|
(if attrs ? lgx then { amm-module-lgx = attrs.lgx; } else { })
|
|
|
|
|
// (if attrs ? install then { amm-module-install = attrs.install; } else { })
|
|
|
|
|
) ammModulePkgs;
|
|
|
|
|
|
2026-08-19 01:36:02 -03:00
|
|
|
# Token core module (modules/token): complete Token Program inspection
|
|
|
|
|
# and transaction planning/orchestration surface. The Qt-free universal
|
|
|
|
|
# module links token_ffi and reuses the host-loaded wallet module.
|
|
|
|
|
tokenModuleOutputs = logos-module-builder.lib.mkLogosModule {
|
|
|
|
|
src = ./modules/token;
|
|
|
|
|
configFile = ./modules/token/metadata.json;
|
|
|
|
|
flakeInputs = inputs;
|
|
|
|
|
externalLibInputs = {
|
|
|
|
|
token_ffi = { input = self; packages.default = "token_ffi"; };
|
|
|
|
|
};
|
|
|
|
|
tests = {
|
|
|
|
|
dir = ./modules/token/tests;
|
|
|
|
|
mockCLibs = [ "token_ffi" ];
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
tokenModulePkgs = tokenModuleOutputs.packages or { };
|
|
|
|
|
|
2026-08-15 00:39:29 -03:00
|
|
|
# Alias the token core module's Basecamp install artifacts. The bare
|
|
|
|
|
# `lgx` / `install` attrs collide across builders in the merged package
|
|
|
|
|
# set (last write wins), so expose an explicit `token-module-lgx` /
|
|
|
|
|
# `token-module-install` that resolves unambiguously.
|
|
|
|
|
tokenModuleAliases = builtins.mapAttrs (
|
|
|
|
|
system: attrs:
|
|
|
|
|
(if attrs ? lgx then { token-module-lgx = attrs.lgx; } else { })
|
|
|
|
|
// (if attrs ? install then { token-module-install = attrs.install; } else { })
|
|
|
|
|
) tokenModulePkgs;
|
|
|
|
|
|
2026-07-16 14:14:20 +02:00
|
|
|
# Wrap the app launcher to export DYLD_FALLBACK_LIBRARY_PATH pointing at the
|
2026-07-29 15:57:24 +02:00
|
|
|
# amm_ffi lib. The logos module builder links the plugin against
|
|
|
|
|
# @rpath/libamm_ffi.dylib but does NOT stage that dylib into the
|
2026-07-16 14:14:20 +02:00
|
|
|
# plugin-dir it loads at runtime, so dlopen fails with "Failed to load UI
|
|
|
|
|
# plugin". Adding the crate's store lib dir to DYLD's fallback search path
|
|
|
|
|
# lets the loader find it (the store path stays in the closure).
|
2026-08-19 14:09:15 +02:00
|
|
|
# Also prepend the AMM UI module's `lib` dir to QML_IMPORT_PATH so the
|
|
|
|
|
# standalone shell resolves `import Logos.Wallet` from the plugin ROOT
|
|
|
|
|
# (staged there, never under qml/, by the appOutputs postInstall — see the
|
|
|
|
|
# wrapTokenQmlImportPath rationale). logos-standalone-app appends any
|
|
|
|
|
# pre-existing QML_IMPORT_PATH to what it sets.
|
2026-07-16 14:14:20 +02:00
|
|
|
wrapWithDyld = system: app:
|
|
|
|
|
let
|
|
|
|
|
pkgs = import nixpkgs { inherit system; overlays = [ rust-overlay.overlays.default ]; };
|
2026-07-29 15:57:24 +02:00
|
|
|
ammFfi = crateOutputs.packages.${system}.amm_ffi;
|
2026-08-19 14:09:15 +02:00
|
|
|
moduleDir = appPkgs.${system}.default;
|
2026-07-16 14:14:20 +02:00
|
|
|
in
|
|
|
|
|
app // {
|
|
|
|
|
program = "${pkgs.writeShellScript "run-amm-ui" ''
|
2026-07-29 15:57:24 +02:00
|
|
|
export DYLD_FALLBACK_LIBRARY_PATH="${ammFfi}/lib''${DYLD_FALLBACK_LIBRARY_PATH:+:$DYLD_FALLBACK_LIBRARY_PATH}"
|
2026-08-19 14:09:15 +02:00
|
|
|
export QML_IMPORT_PATH="${moduleDir}/lib''${QML_IMPORT_PATH:+:$QML_IMPORT_PATH}"
|
2026-07-16 14:14:20 +02:00
|
|
|
exec ${app.program} "$@"
|
|
|
|
|
''}";
|
|
|
|
|
};
|
|
|
|
|
|
2026-07-13 22:20:12 +02:00
|
|
|
renamedApps = builtins.mapAttrs (
|
|
|
|
|
system: attrs:
|
2026-07-16 14:14:20 +02:00
|
|
|
(builtins.removeAttrs attrs [ "default" ]) // (if attrs ? default then { amm-ui = wrapWithDyld system attrs.default; } else { })
|
2026-07-13 22:20:12 +02:00
|
|
|
) appApps;
|
|
|
|
|
|
2026-08-15 00:39:29 -03:00
|
|
|
# Prepend the token UI module's `lib` dir to QML_IMPORT_PATH before the
|
|
|
|
|
# standalone shell runs. The shared Logos.Wallet module is staged at the
|
|
|
|
|
# plugin ROOT (lib/Logos/Wallet), NOT under the view dir (lib/qml) — see
|
|
|
|
|
# the tokenAppOutputs postInstall for why (Basecamp shared-import-path
|
|
|
|
|
# collisions). But the standalone shell only searches the view dir for
|
|
|
|
|
# unqualified imports, so `import Logos.Wallet` from lib/qml/Main.qml would
|
|
|
|
|
# not resolve without help. logos-standalone-app appends any pre-existing
|
|
|
|
|
# QML_IMPORT_PATH to the paths it sets, so exporting lib here makes the
|
|
|
|
|
# root module resolvable with no qml/ stub. tokenAppPkgs.<sys>.default is
|
|
|
|
|
# the module derivation whose /lib is the plugin dir the app loads.
|
|
|
|
|
wrapTokenQmlImportPath = system: app:
|
|
|
|
|
let
|
|
|
|
|
pkgs = import nixpkgs { inherit system; overlays = [ rust-overlay.overlays.default ]; };
|
|
|
|
|
moduleDir = tokenAppPkgs.${system}.default;
|
|
|
|
|
in
|
|
|
|
|
app // {
|
|
|
|
|
program = "${pkgs.writeShellScript "run-token-ui" ''
|
|
|
|
|
export QML_IMPORT_PATH="${moduleDir}/lib''${QML_IMPORT_PATH:+:$QML_IMPORT_PATH}"
|
|
|
|
|
exec ${app.program} "$@"
|
|
|
|
|
''}";
|
|
|
|
|
};
|
|
|
|
|
|
2026-08-14 20:29:55 -03:00
|
|
|
renamedTokenApps = builtins.mapAttrs (
|
|
|
|
|
system: attrs:
|
2026-08-15 00:39:29 -03:00
|
|
|
(builtins.removeAttrs attrs [ "default" ]) // (if attrs ? default then { token-ui = wrapTokenQmlImportPath system attrs.default; } else { })
|
2026-08-14 20:29:55 -03:00
|
|
|
) tokenAppApps;
|
|
|
|
|
|
|
|
|
|
mergedApps = builtins.mapAttrs (
|
|
|
|
|
system: attrs:
|
|
|
|
|
attrs // (renamedTokenApps.${system} or { })
|
|
|
|
|
) renamedApps;
|
|
|
|
|
|
2026-07-13 22:20:12 +02:00
|
|
|
mergedPackages = builtins.mapAttrs (
|
|
|
|
|
system: cratePkgs:
|
|
|
|
|
let
|
|
|
|
|
appSysPkgs = appPkgs.${system} or { };
|
2026-08-19 14:09:15 +02:00
|
|
|
ammUiSysPkgs = ammUiPackages.${system} or { };
|
2026-08-14 20:29:55 -03:00
|
|
|
tokenAppSysPkgs = tokenAppPkgs.${system} or { };
|
2026-08-15 00:39:29 -03:00
|
|
|
tokenUiSysPkgs = tokenUiPackages.${system} or { };
|
2026-07-22 13:56:42 +02:00
|
|
|
ammModSysPkgs = ammModulePkgs.${system} or { };
|
2026-08-19 14:09:15 +02:00
|
|
|
ammModAliasPkgs = ammModuleAliases.${system} or { };
|
2026-08-19 01:36:02 -03:00
|
|
|
tokenModSysPkgs = tokenModulePkgs.${system} or { };
|
2026-08-15 00:39:29 -03:00
|
|
|
tokenModAliasPkgs = tokenModuleAliases.${system} or { };
|
2026-07-13 22:20:12 +02:00
|
|
|
in
|
|
|
|
|
(builtins.removeAttrs cratePkgs [ "default" ])
|
|
|
|
|
// (builtins.removeAttrs appSysPkgs [ "default" ])
|
|
|
|
|
// (if appSysPkgs ? default then { amm-ui = appSysPkgs.default; } else { })
|
2026-08-19 14:09:15 +02:00
|
|
|
// ammUiSysPkgs
|
2026-08-14 20:29:55 -03:00
|
|
|
// (builtins.removeAttrs tokenAppSysPkgs [ "default" ])
|
|
|
|
|
// (if tokenAppSysPkgs ? default then { token-ui = tokenAppSysPkgs.default; } else { })
|
2026-08-15 00:39:29 -03:00
|
|
|
// tokenUiSysPkgs
|
2026-07-22 13:56:42 +02:00
|
|
|
// (builtins.removeAttrs ammModSysPkgs [ "default" ])
|
|
|
|
|
// (if ammModSysPkgs ? default then { amm-module = ammModSysPkgs.default; } else { })
|
2026-08-19 14:09:15 +02:00
|
|
|
// ammModAliasPkgs
|
2026-08-19 01:36:02 -03:00
|
|
|
// (builtins.removeAttrs tokenModSysPkgs [ "default" ])
|
|
|
|
|
// (if tokenModSysPkgs ? default then { token-module = tokenModSysPkgs.default; } else { })
|
2026-08-15 00:39:29 -03:00
|
|
|
// tokenModAliasPkgs
|
2026-07-13 22:20:12 +02:00
|
|
|
) crateOutputs.packages;
|
|
|
|
|
in
|
|
|
|
|
(builtins.removeAttrs appOutputs [ "apps" "packages" ])
|
|
|
|
|
// {
|
2026-08-14 20:29:55 -03:00
|
|
|
apps = mergedApps;
|
2026-07-13 22:20:12 +02:00
|
|
|
packages = mergedPackages;
|
|
|
|
|
};
|
2026-07-13 21:01:40 +02:00
|
|
|
}
|