After the amm_module refactor, this crate is linked only by the module (the
UI delegates to modules().amm_module and links nothing), so its home under
apps/amm/ and the name "client" were both misnomers: it's the AMM business
logic the module wraps, reached across an FFI boundary — the same relationship
logos_execution_zone has with wallet_ffi. Co-locate it with the module that
owns it and name it for that role.
The FFI surface is unchanged — the exported functions are already amm_* (not
amm_client_*) — so only the crate, directory, generated header, dylib, and
package names move. The module's call sites are untouched; it just includes the
renamed header.
- apps/amm/client → modules/amm/ffi (git-tracked rename; history preserved)
- crate amm_client → amm_ffi: package name, include/amm_ffi.h, libamm_ffi.dylib,
AMM_FFI_H guard, build.rs output path, tests/public_api.rs import
- workspace member path + Cargo.lock
- flake.nix: pname, -p, header-copy path, dylib install_name, packages.amm_ffi,
ammModuleOutputs externalLibInputs, DYLD wrapper
- modules/amm: metadata external_libraries, CMakeLists EXTERNAL_LIBS, impl
#include + comments, README, flake note
- apps/amm/flake.nix: drop the now-dead amm_client external-lib input (the UI
links no external lib of its own)
Resulting layout:
modules/amm/
src/ # C++ module (amm_module_impl.{h,cpp})
ffi/ # Rust crate amm_ffi (Cargo.toml, src/, include/amm_ffi.h)
The AMM host FFI was split across two crates with two ABI styles: the
typed-C `amm_client_ffi` (swap primitives, under programs/) and the
JSON/wire `amm_client` (new-position flow, under apps/). Fold both into a
single `amm_client` crate exposing one JSON C ABI, and delete
`programs/amm/client-ffi`.
Rust:
- Re-express the swap path as `api/swap.rs` operations on the existing
`call::<T>` dispatch — swap_pair, resolve_pool, swap_plan, program_id —
reusing `pair::derive_pair` (no more duplicated PDA derivation) and
`risc0_zkvm::serde` for the SwapExactInput words (the same encoding the
guest decodes). The account list and signer flags stay byte-identical
to the old typed path.
- Generate a single header (`include/amm_client.h`) covering all ops via
cbindgen; bump cbindgen 0.27 -> 0.28 for `#[unsafe(no_mangle)]` support.
C++:
- Extend the `AmmClient` wrapper with the four swap ops.
- Add `SwapRuntime` (mirrors `NewPositionRuntime`): reads accounts through
the wallet, drives the swap ops, submits the transaction.
- `AmmUiBackend` swap methods now delegate to `SwapRuntime`, dropping ~390
lines of typed-FFI and byte-twiddling. `program_id` becomes a JSON op,
and the swap clock is derived via `derive_pair` (clock_core::CLOCK_01)
instead of a hardcoded base58 literal — same account, verified.
Add a "Create Pool" flow to the AMM app that lets a user open a new
liquidity position — seeding a pool's initial liquidity — from token
selection and amount entry, through a confirmation dialog, to on-chain
submission.
- client crate (apps/amm/client): pure, testable protocol logic — account
decoding, pair/position modelling, and quote/plan computation — exposed to
the app over a C ABI (config/networks.json drives network selection).
- C++ runtime + backend: AmmClient, ActiveNetwork, and NewPositionRuntime,
wired into AmmUiBackend (new resolve/quote/submit slots).
- QML flow: NewPositionForm, NewPositionFlow state, NewPositionConfirmation-
Dialog, TokenSelectorModal, and reusable Amm* presentational components
(theme, surfaces, buttons) + AmountMath.js.
- tests: C++ (NewPositionRuntimeTest, ActiveNetworkTest) and QML
(tst_NewPositionForm, tst_LiquidityPage, tst_TokenAmountInput, …).
Move the spel-framework dependency from the 0x-r4bbit/spel fork
(v0.5.0 @ 91023c9, the refactor/lez-v020-compat branch) to the released
logos-co/spel tag v0.6.0.
spel v0.6.0 is built against the final logos-execution-zone v0.2.0, not
the v0.2.0-rc6 this repo pinned. The two must match: with rc6, the guest
ELF build fails because spel's lee_core::program::ValidityWindow and the
repo's own copy are distinct types the #[lez_program] macro can't unify.
So this also bumps every logos-execution-zone pin (lee/lee_core aliased
as nssa/nssa_core, plus clock_core) from v0.2.0-rc6 to the final v0.2.0.
- 10 Cargo.toml switched to logos-co/spel tag v0.6.0
- 24 logos-execution-zone pins across 18 Cargo.toml moved rc6 -> v0.2.0
- All 7 Cargo.lock files re-resolved (root + 5 guest workspaces +
benchmark); pulls in lee_core v0.1.0 (v0.2.0) as a spel transitive dep
Guest ImageIDs change as a result: the ID hashes the whole guest ELF,
which links the updated spel-framework and lee_core object code, even
though the program sources are unchanged. Update any ImageID-derived
values (deployed program IDs, PDA addresses, AMM/ATA program-id inputs)
before submitting transactions.
Bump the LEZ dependency from the `lez-core-v0.2.0` tag to `v0.2.0-rc6` across
the workspace and all guest manifests (still resolving via the renamed
`lee_core`/`lee` packages), and regenerate the lockfiles to match.
rc6 moved the clock program out of `nssa` into a separate system-programs crate
(gated behind the guest-building `artifacts` feature), so adapt the tests:
- Import `ClockAccountData` and `CLOCK_01_PROGRAM_ACCOUNT_ID` from `clock_core`
instead of `nssa`, and build clock data via `ClockAccountData::to_bytes()`
rather than hand-encoding the Borsh layout.
- `V03State::new()` no longer auto-creates the clock account, so AMM tests seed
the canonical 1-block clock explicitly before ops that read it.
- `advance_clock` now writes the clock account directly via
`force_insert_account` (the clock can no longer be ticked with a real
transaction), matching how upstream rc6 state-machine tests seed accounts.
- Add the `clock_core` dependency to integration_tests/benchmark.
Bump the LEZ dependency from the `v0.2.0-rc3` tags to the released
`lez-core-v0.2.0` tag across the workspace and all guest manifests. The crate
was renamed upstream, so `nssa_core`/`nssa` now resolve via the `lee_core`/`lee`
packages, and spel-framework points at the `refactor/lez-v020-compat` fork
branch for compatibility.
Adapt the integration tests to the new API surface:
- `NssaError` is now `LeeError` (error variants unchanged).
- Account inputs move from numeric mask vectors (`vec![2, 0, 0]`) to typed
`InputAccountIdentity` values (e.g. `PrivateUnauthorized { epk, view_tag,
npk, ssk, identifier }`).
- `ViewingPublicKey::from_scalar` → `from_seed(d, z)`; `AccountId::from(&npk)`
→ `AccountId::for_regular_private_account(&npk, 0)`; ephemeral-key/shared-
secret setup → `SharedSecretKey::encapsulate_deterministic(...)` with the
circuit filling the EPK.
Regenerate all guest Cargo.lock files and the workspace lockfile to match.
Add the first end-to-end coverage of the oracle's RecordTick path, which
previously existed only as native unit tests:
- amm_twap_observations_accumulate_across_swaps_and_yield_time_weighted_average:
drives swaps + RecordTick across simulated time, then checks the cumulative
accumulator and the consulted time-weighted average.
- amm_twap_record_tick_sampling_guard_skips_calls_below_min_interval: exercises
the min-interval sampling guard through the real instruction path.
Running RecordTick through the zkVM surfaced that committing the oracle-owned
~100 KiB observations account costs ~50.9M cycles — over the 2^25 (~33.5M)
public-execution limit — so the instruction aborted on chain. Reduce
OBSERVATIONS_CAPACITY 6396 -> 2048 (~16.8M cycles, ~half the limit); window
coverage is unchanged, only sampling resolution.
Add programs/benchmark, a standalone crate (excluded from the workspace so CI
and the Makefile skip it) that runs the guest ELF through the RISC Zero
executor and reports the per-instruction cycle split, reproducing the on-chain
pass/fail at the limit. Its cost-vs-capacity sweep still spans to 6396, guarding
against bumping capacity back into the over-budget range.
This relaxes some of the rules introduced in the previous commit.
To simplify testing, building and formatting locally and on CI, we also
introduce a dedicated makefile
- Updated `nssa_core` and `spel-framework` dependencies to their respective release candidates in `Cargo.toml` and `Cargo.lock` files for `amm`, `ata`, and `token` modules.
- Enhanced the `new_definition` function in `amm/src/new_definition.rs` to include new claim logic and updated PDA seed calculations.
- Modified tests in `integration_tests/tests/amm.rs`, `integration_tests/tests/ata.rs`, and `integration_tests/tests/token.rs` to accommodate changes in transaction handling and account initialization.
- Refactored account initialization logic in `ata/src/create.rs` and `token/src/initialize.rs` to include authorization claims.
- Updated various functions in `token/src/mint.rs`, `token/src/new_definition.rs`, and `token/src/transfer.rs` to utilize the new claim system for account states.
- Adjusted the IDL generation tool to use the latest version of `spel-framework-core`.
Move IDL files to artifacts/ and add a convention-based CI check that
discovers all programs via */methods/guest/src/bin/*.rs and fails if
any program is missing its IDL or has one that is out of date.