Skip to content

Feat/refactor routing based on reflect core sdk - #2

Open
danielpavel wants to merge 12 commits into
mainfrom
feat/refactor-routing-based-on-reflect-core-sdk
Open

Feat/refactor routing based on reflect core sdk#2
danielpavel wants to merge 12 commits into
mainfrom
feat/refactor-routing-based-on-reflect-core-sdk

Conversation

@danielpavel

Copy link
Copy Markdown

No description provided.

Workspace of per-(aggregator, program) crates over reflect-sdk: jupiter/lending
and titan/lending. Each adapter only deserializes state and delegates quoting
and building to the SDK, so a quote is byte-identical to execution. Jupiter
vendors the Amm trait + Swap tag (its upstream crate pulls an incompatible
solana line); Titan vendors the TradingVenue template. The members glob grows
as programs (bonds/rlp/whitelabel) and aggregators are added.
Drive the Titan venue's built mint/redeem ix in LiteSVM against a forged
Reserve+Kamino snapshot and assert the dest-balance delta equals the
adapter quote, atom-exact, both directions across a swept amount band.

The forged state is dumped from reflect-core's Mollusk forge (pinned to
an incompatible solana line, so it cannot link directly) and committed
as a fixture; reflect_main.so ships alongside it, Kamino programs are
RPC-dumped and cached on first run.

Jupiter reuses the same fixture for quote==sdk.

Regen recipe lives in forge-dump.patch.
jupiter/lending and titan/lending duplicated the same account
plumbing and SDK delegation for the lending strategy. New
reflect-routing-core crate holds that logic once (LendingVenue);
both shims become thin translations to their aggregator's trait,
with an AccountBytes seam abstracting the two hosts' fetch models.

Concrete types, not generics: one implementation exists today, so
a shared trait across program families would be premature.
The core extraction silently changed host behavior and added an
indirection layer; restore the contracts and cut the seam:

- titan: NotInitialized guards on quote/generate_swap_instruction,
  per-account NoAccountFound, and update_state errors on a pairless
  strategy instead of registering a zero-token market.
- jupiter: a present-but-undecodable seed fails update() again.
- core: discovery_keys takes the two seed byte slices and returns
  Result (decode failure != still cold); load ingests
  (key, owner, data) tuples via the SDK's from_account_map; the
  built StrategyAccounts is cached behind an Arc so quote/build
  stop cloning + re-deserializing per call (titan bounds() path).
- AccountBytes trait, its three shim adapters, and RouteMint
  deleted (SDK MintInfo re-exported); docs no longer advertise a
  ReflectRoutingVenue trait that does not exist.
BondVenue mirrors LendingVenue's shape (two-phase seed/discover/load,
Arc-cached StrategyAccounts, mint-pair quote/build) but delegates the
mint-pair classification entirely to the SDK's bond_route/
bond_quote_by_mints, since a basket maps a pair onto one of three
different ops instead of a single mint/redeem toggle. route() is
exposed separately from quote/build so the Jupiter shim can pick its
Swap tag before building.
ReflectBondVenue maps BondVenue onto Titan's TradingVenue contract:
the 4-seed two-phase fetch (vs lending's 2), a basket that may hold
Token-2022 assets, and a redeem leg whose baked min_out is a USD@1e6
floor rather than out-token atoms (documented on generate_swap_
instruction; Titan's own output check is the token-level guard for
that leg). trading_venue/ and account_caching/ are vendored verbatim
from titan/lending; PoolProtocol grows a ReflectBonds variant instead
of ReflectLending, this crate carries no lending code.
ReflectBondsAmm mirrors ReflectLendingAmm's two-phase Jupiter Amm
handshake, but bonds need 4 seed accounts instead of 2 (controller +
asset_registry + multiocular + main), so cached seed bytes are a
fixed array. get_swap_and_account_metas picks the Swap tag from the
venue's mint-pair route (mint/swap/redeem), each a placeholder pending
Jupiter's own tag assignment for bonds - the account order is pinned
now, the wire tags are a follow-up cross-org handoff. No bond fee is
input-denominated, so quote() always reports fee_amount = 0.
Forged 2-asset basket snapshot (reflect-core bond_forge_dump_tests)
+ the reflect_main.so that forged it, replayed here: the committed
ReflectBondVenue quotes and builds each direction (asset->receipt
mint, receipt->asset constructed redeem, asset<->asset swap) and the
executed dest-balance delta must equal the quote atom-exact, swept
over three amounts, plus zero/over-ask edges.

Mint and redeem legs may consume LESS than the ExactIn request (the
deposit allocator clamps single-sided deposits to imbalance caps;
the constructed redeem re-derives the burn from achieved gross) -
quote and execution clamp identically, so only overspend fails;
swap is asserted spend-exact.
Reuses the Titan crate's forged snapshot: the Amm quote must equal an
independently wired core BondVenue quote (4 direction pairs x 3
amounts) - the Titan LiteSVM suite proves that venue equals on-chain
execution, so quote==execution transfers here without an SVM. Also
pins the route->placeholder-tag mapping and the per-route account-meta
ORDER (user sole signer) - the positional contract for the Jupiter
handoff - and that an over-capacity redeem surfaces as Err, never a
lying quote.
Reflect whitelabel (proxy) branded pair as routing venue.
Reflect rlp (insurance pool) as routing venue:

restake (asset -> LP) and swap (asset -> asset).
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