Feat/amm swap onchain - #226
Conversation
There was a problem hiding this comment.
Pull request overview
Adds a host-facing C ABI + UI wiring to perform real on-chain AMM SwapExactInput transactions, including PDA derivation and on-chain account decoding, and updates the Nix flake packaging to expose the UI and FFI library cleanly.
Changes:
- Introduce
amm_client_ffiRust crate (cbindgen-generated header, build script) for instruction encoding, PDA derivation, and on-chain account decoding. - Wire the AMM QML UI backend to resolve pools, load token config from JSON, and submit real
SwapExactInputtransactions. - Update repository/root Nix flake + workspace membership to build/package the FFI library and expose the UI as
amm-ui.
Reviewed changes
Copilot reviewed 24 out of 26 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| programs/amm/client-ffi/src/swap.rs | Adds instruction-word builder for SwapExactInput plus roundtrip test. |
| programs/amm/client-ffi/src/pool.rs | Adds Borsh decoding helpers for PoolDefinition/AmmConfig into client-friendly views. |
| programs/amm/client-ffi/src/pda.rs | Adds program-id-from-ELF and PDA derivation helpers delegating to core crates. |
| programs/amm/client-ffi/src/lib.rs | Exposes the C ABI surface (swap words, free, PDA helpers, decode helpers). |
| programs/amm/client-ffi/cbindgen.toml | Configures cbindgen output for a C header. |
| programs/amm/client-ffi/Cargo.toml | Declares the new FFI crate and its dependencies/build-deps. |
| programs/amm/client-ffi/build.rs | Generates amm_client_ffi.h during build. |
| programs/amm/client-ffi/amm_client_ffi.h | Adds the generated C header for consumers. |
| flake.nix | Builds/packages amm_client_ffi and exposes the UI as amm-ui (no default). |
| Cargo.toml | Adds the new programs/amm/client-ffi crate to the workspace. |
| Cargo.lock | Adds lock entries for the new crate and its build-time deps (cbindgen/clap/etc.). |
| apps/amm/src/AmmUiBackend.rep | Extends the Qt remote-object interface with AMM pool resolution, swap, and token list APIs. |
| apps/amm/src/AmmUiBackend.h | Wires new slots and includes the generated FFI header. |
| apps/amm/src/AmmUiBackend.cpp | Implements pool resolution, swap submission, and token-list loading using the FFI layer. |
| apps/amm/README.md | Updates run instructions and documents AMM_PROGRAM_BIN + TOKENS_CONFIG runtime requirements. |
| apps/amm/qml/pages/SwapPage.qml | Switches token list to backend-provided config and connects swap success/failure signals. |
| apps/amm/qml/Main.qml | Injects the backend into SwapPage when ready. |
| apps/amm/qml/components/swap/TokenVisuals.js | Adds deterministic UI avatar derivation (color/letter) from token symbol. |
| apps/amm/qml/components/swap/TokenSelectorModal.qml | Updates token selector visuals to use derived avatar + definition id. |
| apps/amm/qml/components/swap/TokenListItem.qml | Updates token list item visuals to use derived avatar + definition id. |
| apps/amm/qml/components/swap/TokenInput.qml | Updates token input visuals to use derived avatar. |
| apps/amm/qml/components/swap/SwapCard.qml | Replaces dummy swap flow with backend resolve+submit flow and new UX state handling. |
| apps/amm/metadata.json | Declares amm_client_ffi as an external library and adds include path for headers. |
| apps/amm/flake.nix | Notes the app is built from the repo-root flake (now that it needs amm_client_ffi). |
| apps/amm/CMakeLists.txt | Links the module against the external amm_client_ffi library. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
91fddd6 to
de6f177
Compare
…ids from AMM config)
…align amm_client_ffi to lee_core v0.2.0
…ore to sequencer rev 415964d7
1fd73f8 to
7f17e06
Compare
…sized pool fee, sync flake run docs
…-ms and program-binary docs
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 26 out of 28 changed files in this pull request and generated 6 comments.
Comments suppressed due to low confidence (3)
apps/amm/src/AmmUiBackend.cpp:567
- These comments refer to AMM_PROGRAM_BIN as an “ELF”, but AMM_PROGRAM_BIN is documented/used as the packaged RISC Zero ProgramBinary (.bin) (and the Rust helper uses ProgramBinary::decode). Calling it ELF here can easily cause someone to point the env var at the raw guest ELF and get a mismatched program id.
// 1. Load the deployed AMM program's ELF. We can't derive this ourselves —
// it must match whatever is actually deployed on the target sequencer.
apps/amm/src/AmmUiBackend.cpp:574
- This comment says the program id is derived from “ELF bytes”, but the input is the packaged program binary (.bin). Updating the wording reduces the risk of someone supplying the wrong artifact.
// 2. Derive the AMM program id from the ELF bytes.
apps/amm/src/AmmUiBackend.cpp:707
- Same terminology issue as resolvePool(): AMM_PROGRAM_BIN is a packaged program binary (.bin), not a raw ELF. Keeping this comment accurate helps prevent accidental use of the wrong file type when debugging swap failures.
// 2. Load the deployed AMM program's ELF (must match resolvePool's — both
// read the same AMM_PROGRAM_BIN — since the instruction is proven against
// this exact binary's image id).
| fn main() { | ||
| let crate_dir = | ||
| std::env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR is set by cargo"); | ||
| cbindgen::generate(&crate_dir) | ||
| .expect("cbindgen") | ||
| .write_to_file(format!("{crate_dir}/amm_client_ffi.h")); | ||
| println!("cargo:rerun-if-changed=src/lib.rs"); | ||
| println!("cargo:rerun-if-changed=src"); | ||
| println!("cargo:rerun-if-changed=cbindgen.toml"); |
…ocs; clarify sharedWalletIsOpen
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 26 out of 28 changed files in this pull request and generated 5 comments.
Comments suppressed due to low confidence (1)
programs/amm/client-ffi/src/pda.rs:16
program_id_from_elftakes bytes of a RISC ZeroProgramBinary(.bin) (per its docstring and implementation), but its name/parameter (elf) strongly suggest callers should pass a raw ELF. Because the computed image id is sensitive to the exact byte format, this naming is likely to cause misuse. Consider renaming toprogram_id_from_bin(and updating the exported C ABI accordingly) to match what the function actually expects.
/// Computes the `ProgramId` (Image ID) of a deployed program binary — the RISC
/// Zero `ProgramBinary` (`.bin`) format produced by the guest build, NOT a raw
/// ELF (the `elf` bytes are decoded via `ProgramBinary::decode`) — the same way
/// the sequencer/wallet does when deploying a program.
pub fn program_id_from_elf(elf: &[u8]) -> Result<ProgramId, String> {
let binary = ProgramBinary::decode(elf).map_err(|e| format!("{e:?}"))?;
let id = binary.compute_image_id().map_err(|e| format!("{e:?}"))?;
Ok(id.into())
| uint8_t defA[32]; | ||
| uint8_t defB[32]; | ||
| if (!hexToBytes32(defAHex, defA) || !hexToBytes32(defBHex, defB)) { | ||
| qWarning() << "AmmUiBackend::resolvePool: invalid defAHex/defBHex"; | ||
| out[QStringLiteral("error")] = QStringLiteral("bad_config"); | ||
| return out; | ||
| } | ||
|
|
||
| uint8_t poolPda[32]; | ||
| amm_client_pool_pda(&ammId, &defA, &defB, &poolPda); | ||
| const QString poolHex = bytes32ToHex(poolPda); |
| pub unsafe extern "C" fn amm_client_pool_pda( | ||
| amm: *const ProgramId, | ||
| def_a: *const [u8; 32], | ||
| def_b: *const [u8; 32], | ||
| out: *mut [u8; 32], | ||
| ) { | ||
| *out = pda::pool_pda(*amm, acc(def_a), acc(def_b)).into_value(); | ||
| } |
| /** | ||
| * Computes the `ProgramId` (Image ID) of a compiled guest ELF. Returns | ||
| * `false` on an invalid ELF, leaving `out` unwritten. | ||
| * | ||
| * # Safety | ||
| * `elf` must be valid for reads of `elf_len` bytes, and `out` must be a | ||
| * valid, non-null pointer to writable memory for a `ProgramId`. | ||
| */ | ||
| bool amm_client_program_id_from_elf(const uint8_t *elf, uintptr_t elf_len, ProgramId *out); |
| AMM_PROGRAM_BIN=$(pwd)/programs/amm/methods/guest/target/riscv32im-risc0-zkvm-elf/docker/amm.bin \ | ||
| TOKENS_CONFIG=$(pwd)/amm-tokens.json \ | ||
| nix run .#amm-ui |
| AMM_PROGRAM_BIN=$(pwd)/programs/amm/methods/guest/target/riscv32im-risc0-zkvm-elf/docker/amm.bin \ | ||
| TOKENS_CONFIG=$(pwd)/amm-tokens.json \ | ||
| nix run .#amm-ui |
No description provided.