Skip to content

feat(asset-rfq): serve the asset-swap-v3 covenant beside v2 (solver back-half) - #343

Draft
d4rp4t wants to merge 2 commits into
feat/covenant-versioningfrom
feat/covenant-versioning-backhalf
Draft

d4rp4t wants to merge 2 commits into
feat/covenant-versioningfrom
feat/covenant-versioning-backhalf

Conversation

@d4rp4t

@d4rp4t d4rp4t commented Nov 7, 2026

Copy link
Copy Markdown
Contributor

What

The solver half of asset-swap covenant versioning: one solver serves both the
v2 and the v3 (ts-sdk #1147) offer covenant on the arkade↔arkade RFQ corridor at
once, indefinitely, so the fixed program rolls out without breaking deployed
wallets.

  • Baseline pinned to v2. #1147 flips the swap package's default offer program
    to v3. assetOfferGeneration(version) maps the negotiated covenant to the SDK
    generation — anything but asset-swap-v3 (baseline and absent alike) compiles
    the previous tree — and deriveOffer threads it. A request that names no
    covenant derives v2, byte-identical to today.
  • Negotiate and serve v3. A corridor declares every covenant it can build
    (CorridorDescriptor.covenantVersions, absent = baseline alone). Negotiation
    picks the client's most-preferred version the deployment also serves, echoes it
    as covenant_version, and threads it to the derivation via
    QuoteOptions.covenantVersion. The asset corridor declares [v2, v3].
  • verifyOfferAddress-style agreement is unchanged: the client funds the address
    it derived, and offerConsistency still re-derives and matches the funded
    script exactly — negotiation chooses, verification guards.

Why

The asset-swap v2 payout leaf is pinned to a fixed output index (safe for a
single deposit, unsafe for a batched book); #1147 fixes it as a new program whose
address differs. Changing the covenant changes the address, so it cannot be
swapped under deployed wallets — it has to be an opt-in second covenant served
beside v2 for as long as the rollout needs. This is the solver side of that; the
client side is ts-sdk #1191.

Stacked / blocked

  • Base: feat/covenant-versioning (feat(rfq): version swap covenants across RFQ methods #313 — the negotiation front-half).
  • Depends on ts-sdk #1147 (cursor/pair-offer-fulfill-input-a4e3) for the v3
    program. It is unreleased, so CI here will stay red against the pinned
    @arkade-os/swap 0.1.0-rc.34 / sdk 0.5.0-rc.31
    — offerVtxoScript's
    generation argument does not exist until the SDK carrying #1147 is released and
    the solver's pins are bumped. That bump is the merge gate; this stays a draft
    until then.
  • Validated locally against a build of #1147 (+#1191) linked into the workspace:
    typecheck, build, test and format all green on that SDK.

Deliberately out of scope (follow-ups)

  • No covenant_version DB column. Not needed for correctness: fill, settle
    and offerConsistency all run on the funded offer, which carries its
    swapPkScript, and the SDK's swapProgramBinding matches either generation
    from that at runtime. A column would be observability only (admin console).
  • No wallet.ts VHTLC reconcile. Linking the #1147 SDK build surfaces a
    separate, unrelated drift: 5 claim/refund tests expect sign called 2–3× and
    now see 1× (a checkpoint-signing change in the SDK's master, not the asset-swap
    axis). Adopting the released SDK will need the wallet layer reconciled to that
    flow — tracked separately, not mixed into this PR.

Testing

  • Four gates green against the linked #1147 build.
  • New: covenant version → generation mapping; solver-vs-SDK address agreement on
    both v2 and v3; a fresh v3 derivation differs from v2; negotiation picks the
    client's top served version and falls back when the top is disabled; the
    baseline path names no version; the negotiated version reaches deriveOffer.
  • No regtest / e2e run.

…ved vocabulary

ts-sdk #1147 flips the swap package's default offer program to v3 (the arkadec
asset-swap/sats-swap tree that fixes v2's pinned payout-leaf index). Linked into
the solver, that silently changes every quoted offer address — a v2 client's
deposit would land at a v3 address it never derived.

Pin the derivation explicitly: `assetOfferGeneration` maps a covenant version to
the SDK generation, and anything but asset-swap-v3 (baseline and absent alike)
compiles the previous tree. `deriveOffer` now takes the negotiated version and
threads it through; with nothing negotiated yet it derives v2, byte-identical to
today. Add asset-swap-v3 to RFQ_COVENANT_VERSIONS so a deployment serves it
alongside v2, opt-in per request — never as the baseline.

Front-half only: the negotiation layer does not yet pick v3 (next commit).
The front-half quoted only the corridor's single baseline. Let a corridor
declare every covenant it can BUILD (CorridorDescriptor.covenantVersions, absent
= baseline alone), and have negotiation pick the client's most-preferred version
the deployment also serves, echo it, and thread it to the quote through
QuoteOptions.covenantVersion. The asset corridor declares [v2, v3]: v2 stays the
baseline a request naming no covenant gets, v3 is served opt-in.

The chosen version reaches the offer derivation via the orchestrator's request,
so a v3 negotiation derives the v3 address the client funds. A request that does
not negotiate is unchanged: baseline v2, no covenant_version echoed.

Backward-compatible for single-covenant corridors — they declare no
covenantVersions, so buildable is the baseline and the behaviour is byte-identical.
@coderabbitai

coderabbitai Bot commented Nov 7, 2026

Copy link
Copy Markdown
Contributor

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

Share

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