Skip to content

fix(cli): correct OptionBook/RFQ math, enable WETH closes, cut 0.2.0 - #56

Merged
Shawnchee merged 6 commits into
mainfrom
fix/tnuts-cli
Aug 19, 2026
Merged

Shawnchee merged 6 commits into
mainfrom
fix/tnuts-cli

Conversation

@Shawnchee

Copy link
Copy Markdown
Collaborator

CLI-only correctness release. Touches cli/ plus a one-line root lockfile version sync (0.2.5 → 0.3.0, catching up to the already-published SDK). No SDK source is modified.

Why

Several OptionBook and RFQ paths were producing wrong numbers or unfillable requests:

  • book preview / book fill divided prices by the collateral token's decimals instead of the protocol's fixed 8-decimal price scale, and divided contract counts by 1e8 instead of the 6-decimal contract scale — premiums rendered 100x high, contract counts 100x low.
  • The SDK picks a vanilla CALL implementation without considering collateral, so a USDC vanilla call built a USDC + INVERSE_CALL request that no maker could fill.
  • offerEndTimestamp is stamped at build time, and an ERC-20 approval plus two prompts routinely consumed the whole 45s window — RFQs were mined already expired.
  • book fill re-resolved orders by (maker, nonce) before broadcast, but Odette reuses nonces across batches, so it could resolve the wrong order.

What changed

Area Change
book Correct decimal scaling; show only cash-settled USDC maker asks; re-resolve the exact EIP-712 signature pre-broadcast; approve the premium ceiling
rfq Vanilla ETH calls require --collateral-token WETH and route to INVERSE_CALL; deadlines restamped at broadcast; offers above the fixed buyer reserve rejected
position WETH closes now supported via exact bigint reserve math; payout is read-only inspection with correct exit codes
wallet Native ETH balance
output Addresses, tx hashes and RFQ public keys never truncate; key/value tables wrap to terminal width

Breaking

  • book fill --order-index no longer performs live fills — indices shift as orders fill/cancel, so it is accepted only with --dry-run. Live fills need the stable selector flags and exit 2 otherwise.
  • Vanilla BTC CALL RFQs are rejected — they previously produced a broken USDC inverse-call request. BTC inverse calls need cbBTC, not yet exposed.
  • Displayed premiums and contract counts change by 100x in the corrected direction. Any automation parsing these needs review.
  • position payout dry-run action renamed payout → inspect-automatic-payout.

Hence 0.2.0, not a patch. Full detail in cli/CHANGELOG.md.

Verification

  • npm run typecheck, npm run build, npm test all pass (regression tests added for book eligibility and RFQ routing, now wired to npm test).
  • Smoke-tested live against Base: book orders, book preview, book fill --dry-run, book check, rfq build for both USDC and WETH paths, wallet balance, position list, keys show.
  • Reserve math verified equivalent to the previous float path on all USDC cases; the float path was off by 1 wei on 18-decimal WETH amounts, which the bigint path fixes.
  • On-chain quotations() reads confirm the buyer-reserve guard compares against the real escrowed value.

Known gaps

  • position close still fails at the broadcast restamp if the option expires within (offer window + approval/confirm time). Narrowed by an up-front guard but not eliminated; rfq request has the same residual by construction.
  • renderArrayTable can still overflow for wide tables like position list beyond 5 rows — pre-existing, unchanged here.

- Raise the hex threshold to 68 so addresses (42), tx hashes (66) and
  compressed RFQ public keys (68) never collapse; only larger blobs do, and
  they keep a `(N chars)` length suffix so calldata size stays checkable.
- Raise the string threshold to 140 so copy/paste next-step commands survive.
- Wrap key/value tables to the terminal width instead of overflowing it.
…e orders

- Scale prices by the protocol's fixed 8-decimal price scale and contract
  counts by the collateral scale; premiums rendered 100x high and contract
  counts 100x low.
- Recompute the preview premium for the contracts actually filled, and approve
  its ceiling so a fill cannot revert on a one-unit rounding difference.
- Show only cash-settled USDC maker asks, excluding physical implementations,
  maker bids, expired orders and zero-liquidity orders.
- Re-resolve the exact EIP-712 signature before broadcast, since Odette reuses
  nonces, and allow the volatile `--order-index` only with `--dry-run`.
…adlines

- Require explicit `--collateral-token WETH` for vanilla ETH calls and override
  the SDK's collateral-blind implementation choice; the old USDC pairing built
  requests no maker could fill.
- Restamp `offerEndTimestamp` immediately before broadcast so approvals and
  confirmation prompts cannot consume the whole offer window.
- Reject offers above the RFQ's fixed buyer reserve, which can never settle
  because a buyer cannot top up an existing request.
- Denominate WETH inverse-call scenario payouts in ETH instead of dollars.
- Size the closing reserve with exact bigint math so 18-decimal amounts, which
  exceed Number.MAX_SAFE_INTEGER, are no longer rounded through a float; USDC
  results are unchanged.
- Restamp the closing RFQ deadline before broadcast, and reject up front a
  close whose option expires inside the offer window.
- Drop the signer requirement from `position payout` and propagate exit codes;
  r12 settles automatically and there is no user-callable claim.
- Add a `structure` column to `position list`.
- Include the native balance in `wallet balance` and accept `--token ETH`.
- Render the full wallet address in `wallet show`, the primary copy surface.
- Bump the CLI to 0.2.0: displayed numbers change and `book fill --order-index`
  no longer performs live fills, so this is not a patch.
- Document the release in cli/CHANGELOG.md and refresh the README banner,
  orders table, keyless `rfq build` example and WETH close docs.
- Wire the regression tests to `npm test`.
- Sync the root lockfile to the published SDK version 0.3.0.
@Shawnchee
Shawnchee merged commit e97da1e into main Aug 19, 2026
6 checks passed
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