feat(scenarios): add HumidiFi state preparation - #16
92Infinitus92 wants to merge 6 commits into
Conversation
dd2c404 to
79e1e95
Compare
The Tessera, HumidiFi and GoonFi parameter structs deserialized their fields as snake_case, so a client sending surfnetPort the way the pump, get_template and search_constant_options tools expect it was ignored and the read fell back to port 8899. Scenario tools now share one convention.
No behavior change. The PR shrinks by about 350 lines: - fair_value and liquidity share one masked-pubkey-pair reader and one persisted freshness override; the second vault owner check was unreachable and is gone - HumidiFiMarket fields are pub(crate) with read-only getters for the MCP crate, so no caller outside core can build one by hand - MCP tools share the market-reading prefix and fail through one Result path; the two staging-order tests become one - unit tests use shared fixtures and tables; the live suite drops the price-band smoke test that the executed exchange-rate test subsumes and keeps the independent XOR key oracles for u64 fields and pubkeys - the cli HTTP test is removed: the etalon protocols add none there - README loses dated narratives and text that repeats the templates - the fair-value tool description says it is not for staleness scenarios, which use the humidifi-stale-quote template - imports follow the nightly rustfmt grouping the CI check enforces
| Ok(OverrideInstance::new( | ||
| freshness.id.clone(), | ||
| PREPARATION_SLOT, | ||
| AccountAddress::Pubkey(market.to_string()), | ||
| ) | ||
| .with_values(HashMap::from([( | ||
| "last_update_slot".to_string(), | ||
| serde_json::Value::Null, | ||
| )])) | ||
| .with_label("Keep HumidiFi quote fresh".to_string())) |
There was a problem hiding this comment.
Freshness expires after one write
The builder schedules last_update_slot only once at slot 0. If the scenario executes after max_staleness_slots, no later override refreshes the quote, so HumidiFi rejects it as stale. This also affects the liquidity builder, which uses the same helper, and contradicts the documentation that says scenarios running past the freshness window refresh at a later slot. Schedule additional freshness overrides within the market's window or otherwise preserve the refresh behavior.
Prompt To Fix With AI
This is a comment left during a code review.
Path: crates/core/src/scenarios/protocols/humidifi/v1/fair_value.rs
Line: 246-255
Comment:
**Freshness expires after one write**
The builder schedules `last_update_slot` only once at slot 0. If the scenario executes after `max_staleness_slots`, no later override refreshes the quote, so HumidiFi rejects it as stale. This also affects the liquidity builder, which uses the same helper, and contradicts the documentation that says scenarios running past the freshness window refresh at a later slot. Schedule additional freshness overrides within the market's window or otherwise preserve the refresh behavior.
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.There was a problem hiding this comment.
@greptileai The behaviour is deliberate, but the doc comment you quoted was wrong, so thanks for catching it.
Every override the builder emits sits at relative slot 0, so the scenario it produces is one slot long. Studio's Play pauses the clock at that slot before registering the scenario, so a swap sent there reads an age of zero. There is no later slot in the scenario to schedule a second refresh into.
Repeating the write is also not something the engine can do on its own any more. Base commit 475b48e removed override persistence, and the scenarios README now carries the rule: an override is applied once, and its result stays in the account until a transaction or another override writes it again.
So what needed fixing was the sentence, which claimed a scenario past the market's window refreshes itself. Nothing does that. Fixed in bf0758a: the comment and the README now say the builder writes freshness once, and a scenario extended past the window needs a second freshness override of its own. The same wording is corrected on the GoonFi and Tessera branches.
There was a problem hiding this comment.
That clarification is correct. The builder intentionally creates a one-slot scenario, Play pauses at the preparation slot, and the one-time freshness write is sufficient for the intended swap. Since override persistence was removed, automatic refresh is not available; scenarios that extend beyond the staleness window must add their own later freshness override. Commit bf0758a corrects the HumidiFi comment and README, so this finding is resolved and no code change is needed.
HumidiFi markets can now be discovered and prepared through the existing scenario and MCP paths. Adds fair-value, persistent-freshness, stale-quote and liquidity scenarios, with an explicitly selected market and guarded raw-layout writes. Fair-value scenarios fetch the market before Play, then keep its quote fresh locally.
Stacked on #15 (
feat/scenarios/raw-layout). Reuses its raw-layout materializer and registry loader, adding an optional eight-byte XOR mask for HumidiFi account fields.Validation:
cargo fmt --all -- --checkcargo test --offline --workspace --features surfpool-core/ignore_tests_ci -- --test-threads=1: 943 passed, 0 failed, 66 ignored.cargo test --offline -p surfpool-core --features integration-tests tests::humidifi -- --test-threads=1 --nocapture: 10 passed, including deployed-program swap and exact account-byte checks.cargo clippy --offline --workspace --all-targets: exit 0, existing warnings.cargo build --offline --release --features supervisor_ui: exit 0.The live integration tests execute the deployed HumidiFi program in the test VM through the documented DFlow test wrapper.
The PR appears safe to merge with no outstanding actionable findings.
Fix with agent prompt
Summary
This PR adds HumidiFi market discovery and state preparation through the existing scenario and MCP interfaces.
Diagram
sequenceDiagram participant Client participant MCP participant SurfnetRPC participant Builder participant ScenarioEngine Client->>MCP: List HumidiFi markets MCP->>SurfnetRPC: getProgramAccounts SurfnetRPC-->>MCP: Candidate market accounts MCP->>MCP: Validate layout, schema, mints MCP-->>Client: Explicit market choices Client->>MCP: Create fair-value or liquidity scenario MCP->>SurfnetRPC: Read market, mints, and optional vaults SurfnetRPC-->>MCP: Hydrated account snapshot MCP->>Builder: Validated accounts and requested values Builder-->>MCP: Scenario overrides at preparation slot MCP->>ScenarioEngine: Register scenario Client->>ScenarioEngine: Play ScenarioEngine->>ScenarioEngine: Apply guarded raw-layout and balance writesReviews (7) · Last reviewed commit: "docs(humidifi): say that the freshness o..."