Skip to content

feat(scenarios): add HumidiFi state preparation - #16

Open
92Infinitus92 wants to merge 6 commits into
feat/scenarios/raw-layoutfrom
wip/humidifi-rebuild
Open

92Infinitus92 wants to merge 6 commits into
feat/scenarios/raw-layoutfrom
wip/humidifi-rebuild

Conversation

@92Infinitus92

@92Infinitus92 92Infinitus92 commented Sep 14, 2026

Copy link
Copy Markdown
Collaborator

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 -- --check
  • cargo 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.

RetriggerConfidence Score: 5/5

The PR appears safe to merge with no outstanding actionable findings.

Fix All in Claude CodeFindings

  1. P1 Freshness expires after one write
Fix with agent prompt
### Issue 1
crates/core/src/scenarios/protocols/humidifi/v1/fair_value.rs:246-255
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.
Summary

This PR adds HumidiFi market discovery and state preparation through the existing scenario and MCP interfaces.

  • Adds guarded XOR-aware raw-layout templates for fair value, freshness, stale quotes, and vault liquidity.
  • Validates market ownership, schema version, mint metadata, and vault relationships before building scenarios.
  • Exposes market discovery and scenario creation through MCP and shared scenario types.
  • Adds unit and live integration coverage for account encoding, discovery, swaps, staleness, and liquidity changes.
  • Clarifies that builder-generated freshness is applied once at Play and must be extended explicitly for scenarios spanning the staleness window.
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 writes
Loading

Reviews (7) · Last reviewed commit: "docs(humidifi): say that the freshness o..."

Comment thread crates/core/src/scenarios/protocols/humidifi/v1/liquidity.rs
Comment thread crates/core/src/scenarios/protocols/humidifi/v1/fair_value.rs Outdated
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
Comment on lines +246 to +255
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()))

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 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.

Fix in Claude Code Fix in Codex Fix in Cursor

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@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.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant