Skip to content

cluster-tool + flow-liq-yield: bootstrap sysio.swap/sysio.liq and drive the LIQ reward flow end to end - #104

Open
heifner wants to merge 2 commits into
simple_swapfrom
feature/liq-yield-flow
Open

heifner wants to merge 2 commits into
simple_swapfrom
feature/liq-yield-flow

Conversation

@heifner

@heifner heifner commented Sep 22, 2026 •

Copy link
Copy Markdown
Contributor

Stacked on #98 (simple_swap). The branch also carries origin/master (21 commits simple_swap lacks, including #93's WIRE-352 harness changes), so the files view includes those until #98 catches up with master. Pairs with Wire-Network/wire-sysio#634 (the depot side: sysio.liq, the msgch handlers, the depot cranks, the createlink sweep hook) and Wire-Network/wire-libraries-ts#84 (the regenerated SysioContractTypes this harness compiles against); an e2e dispatch needs all three branch overrides.

Bootstrap

  • The depot's shadow-liq system is bootstrapped where a real depot needs it, unconditionally: SwapConfig (sysio.swap::setconfig — governance sysio, system token 9,WIRE), ShadowLiqTokens (one sysio.liq::create per registered liq token: LIQETH, LIQSOL) and LiqConfig (sysio.liq::setkicker), between MockReserves and UnderwriterConfig.
  • MockLiqPools is opt-in — --enable-mock-liq-pools / ClusterBuildOptions.enableMockLiqPools, default false at every layer and persisted in ClusterConfigSchema — the same five-layer shape as --enable-mock-reserves. It seeds one sysio.liq::regliqpool yield pool per shadow inside the epoch-0 window, minting the pool shadow from nothing, which is why a real / external depot never sets it. The pools' tick pacing (a 30 s horizon, a 30 % depth cap) lets one tickyield sell a whole reported yield, which is what makes the flow's claim assertion exact.
  • Steps.contracts.sysio.liq (planCreate, planSetkicker, planRegliqpool, planSweep, planClaim, planDesyndicate) and Steps.contracts.sysio.swap (planSetconfig): one write per Step, typed on the generated action data.
  • Steps.user.planProvisionWire is the shared home of the WIRE-user provisioning flow-swap-from-wire carried locally.

flow-liq-yield

The reward flow on the real liqsol_core paths and the real depot contracts, nothing injected and nothing cranked by hand: synd → the syndication parks (the key is not linked) → createlink → the inline sweep delivers it → bonus yield + report_liq_yield → LIQ_YIELD lands in liqpending, outside supply → the batch operators' queueyield mints it into the swap's reservoir → their tickyield sells it and the index moves → claim pays exactly owed(row, index) and the pot falls by the same → desyndicate → DESYNDICATE_LIQ in a DEPOT_OUTPOST_SOLANA envelope → the user's liqSOL ATA grows by the burned amount. The depot's epoch is asserted to keep advancing across every attestation. Reads go through the typed table accessors; every write is a Report Step; budgets derive from ProtocolTiming.

Harness fixes the run surfaced

  • confirmSignature returned on a confirmed / finalized status before looking at the transaction's err. A transaction the runtime processed with an error is still included in a block, so it reaches those statuses too — an on-chain failure was reported as success. Found when a liqSOL deposit refused by EpochRewardsActive passed as OK and synd then found the ATA it never created; it also meant submitWithEpochRewardsRetry's on-chain-failure branch could never fire. The error is now checked first; tests added for the confirmed and finalized shapes.
  • WireClient.symbolCodeKeyRange(field, code): the exact [code, code + 1) KV range for a row keyed by one symbol_code (JSON key object, uint64 as a decimal string; lower_bound inclusive, upper_bound exclusive). A bare code string as a bound is a nodeop parse error, and sysio.liq::yieldidx's value carries no identity, so it can only be read this way. Tests added.

Also

  • .pnpmfile.cjs: WIRE_LIBRARIES_TS_PATH / WIRE_SYSIO_PATH point the sibling links at worktrees (the Linked … lines are the record of what resolved).
  • oppEnvelopeScan.containsDesyndicateLIQ; SolanaLiqSyndicationTool.readLiqsolBalance.
  • flow-liq-syndication: its user never links, so under #634 the syndication parks rather than credits — the scenario and README say so, and its liveness phase is named DepotKeepsAdvancing.
  • README / CLAUDE.md: the flag, the phases, the flow list, the worktree-linking env vars.

Environment note

Tools master's roster seeding (#87) calls OPPInbound.installInitialRoster, which wire-ethereum next only has as a private _installInitialRoster; the public one is Wire-Network/wire-ethereum#205 (wne-41_next-fix). Until #205 merges, a local run of ANY flow on this branch needs --ethereum-path at that branch, and an e2e dispatch needs BRANCH_WIRE_ETHEREUM=wne-41_next-fix beside the three overrides above. Not introduced here — inherited from master. Likewise from master: the StartScripts phase copies the pre-built @wireio/debugging-server bundle (dist/bundle/wire-debugging-server.cjs), which the root tsc -b does not produce — a fresh worktree needs pnpm --filter @wireio/debugging-server bundle (or the package's prepare) before a cluster is created.

CI

The repo's own Build and test check is red by construction until the upstream packages publish: a standalone clone resolves @wireio/opp-typescript-models and @wireio/sdk-core from npm, and the published versions carry neither the SYNDICATE_LIQ / LIQ_YIELD / DESYNDICATE_LIQ attestations (Wire-Network/wire-sysio#609 / #634's bundle) nor the swap / liq contract types (Wire-Network/wire-libraries-ts#84). #98 is red the same way. The e2e gate with the branch overrides above is the check that exercises this branch.

Verification

pnpm build green
pnpm run lint green
pnpm test (final tree) green — 237 suites, 2234 tests
flow-liq-yield (local, run-flow.mjs + heartbeat monitor) SUCCEEDED — 207 Report steps ok (bootstrap + the 9 scenario phases), 2026-09-22; runs 1–4 fell to the items above (the KV bound encoding, Wire-Network/wire-ethereum#205, the debugging-server bundle, confirmSignature)
e2e gate (wire-platform-build-system run 35772325409, BRANCH_WIRE_SYSIO=feature/liq-yield-claiming BRANCH_WIRE_LIBRARIES_TS=feature/liq-yield-contract-types BRANCH_WIRE_TOOLS_TS=feature/liq-yield-flow BRANCH_WIRE_ETHEREUM=wne-41_next-fix BRANCH_WIRE_SOLANA=codex/merge-develop-into-next-20260922) green — all 17 flows passed, incl. liq-yield (792 s) and liq-syndication (561 s), 2026-09-22

@heifner

heifner commented Sep 24, 2026

Copy link
Copy Markdown
Contributor Author

e2e: three runs, all green. Every one passed BRANCH_WIRE_TOOLS_TS=feature/liq-yield-flow, which resolved to f22987b3 — this PR's head.

Run Started Result
35905786811 2026-09-23 18:55Z 17 of 17 flows, 0 failed, 122 min
35877211864 2026-09-23 14:51Z 17 of 17 flows, 0 failed, 107 min
35772325409 2026-09-22 19:12Z 17 of 17 flows, 0 failed

Overrides on all three: BRANCH_WIRE_SYSIO=feature/liq-yield-claiming, BRANCH_WIRE_LIBRARIES_TS=feature/liq-yield-contract-types, BRANCH_WIRE_TOOLS_TS=feature/liq-yield-flow, BRANCH_WIRE_ETHEREUM=wne-41_next-fix (Wire-Network/wire-ethereum#205, for the public installInitialRoster tools master's roster seeding needs), BRANCH_WIRE_SOLANA=codex/merge-develop-into-next-20260922.

The 17 are master's 15 plus liq-yield and liq-syndication, which exist only on this branch. The wire-sysio side of those runs has since merged as 4a20f64967 (Wire-Network/wire-sysio#634), so the depot code they exercised is what sits on master now.

Build and test is red here by construction, not from a defect in the diff: a standalone CI clone resolves @wireio/sdk-core and @wireio/opp-typescript-models from npm, and neither yet carries Wire-Network/wire-libraries-ts#84's regenerated sysio.liq / sysio.swap types or #634's attestations. It clears once #84 releases and this branch's package.json points at that version.

@jglanz jglanz left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

If you choose to merge, make sure to rebase first. Otherwise @jglanz will merge when implementing new flow scenarios over the coming days

…ve the LIQ reward flow end to end

The bootstrap configures the swap, opens one shadow symbol per registered liq
token and sets the kicker; the mock yield pools are opt-in
(--enable-mock-liq-pools), seeded inside the epoch-0 window like the mock
reserves. Steps.contracts.sysio.{liq,swap} are the per-action factories;
Steps.user.planProvisionWire is the shared WIRE-user provisioning
flow-swap-from-wire carried locally.

flow-liq-yield: synd -> parked -> createlink sweeps it -> report_liq_yield ->
liqpending -> the batch operators' queueyield and tickyield -> claim pays
exactly owed(row, index) -> desyndicate -> DESYNDICATE_LIQ pays the liqSOL ATA.

Two harness fixes the run surfaced: confirmSignature checked a tx's err only
after returning on a confirmed status, so an on-chain failure passed as
success; WireClient.symbolCodeKeyRange reads a KV row keyed by one symbol_code
exactly (a bare code as a bound is a nodeop parse error).

.pnpmfile.cjs takes WIRE_LIBRARIES_TS_PATH / WIRE_SYSIO_PATH so a worktree links
its sibling worktrees. Pairs with wire-sysio#634 and wire-libraries-ts#84.

Change-Id: I67ceaa5927bb8deb4a71ed70426e223e41a44b22
sdk-core and shared to 1.0.92, the wire-libraries-ts release carrying
the regenerated SysioContractTypes for sysio.liq and sysio.swap
(wire-libraries-ts#84). Produced by scripts/update-wireio-deps.mjs.

Change-Id: I803eca9e735ebf7082843418b8945adfb537fac0

This branch has not been deployed

No deployments
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.

2 participants