Skip to content

Promote SDK to beta status (0.5.14): swap RFQ defects fixed, error info surfaced#7

Merged
ngurmen merged 8 commits into
mainfrom
mng/fix-swap-flow
May 9, 2026
Merged

Promote SDK to beta status (0.5.14): swap RFQ defects fixed, error info surfaced#7
ngurmen merged 8 commits into
mainfrom
mng/fix-swap-flow

Conversation

@ngurmen
Copy link
Copy Markdown
Contributor

@ngurmen ngurmen commented May 9, 2026

Summary

This branch carries the 0.5.14 release: it hardens the swap (RFQ) path end-to-end after extensive mainnet testing through a bot consumer, quiets known-noisy init logs, surfaces meaningful error information on failed swaps, and promotes the SDK from alpha to beta maturity.

Beta Justification

  • CLOB surface: long-running Fuji testnet exposure across orders, deposits/withdrawals, market data, and websocket subscriptions.
  • Swap (RFQ) surface: previously untested at the application layer because Dexalot has no testnet RFQ infra. This branch closes that gap with six successful mainnet AVAX/USDC swaps, fixing every defect surfaced along the way.
  • Quality: 872 unit tests, 100% line coverage on core/swap.py and core/base.py, mypy clean, ruff clean, no # type: ignore / # noqa.

The pre-1.0 SemVer caveat stays — `Please Note: The public interface may undergo breaking changes` remains in the README.

Changes (chronological)

Commit What it does
`03d0123` fix(swap): rewrite quote transformation to match the documented flat `{order, signature, tx}` shape (drop `secureQuote` envelope), unwrap `{success, quote}` envelope, normalize `chain_id`/`quote_id` aliases. `_to_int` helper for hex/decimal/None coercion on `nonceAndMeta`. `_compute_msg_value` for native-asset sells. `_get_rfq_contract(chain_id)` resolves to the connected chain's provider rather than always Dexalot L1. Contract address checksumming via `Web3.to_checksum_address`.
`0a8ef98` doc(README): update RFQ Quotes API documentation.
`474d7ec` chore(release): bump version to 0.5.14.
`460414e` fix(base): demote rfq_pairs HTTP 4xx to debug — chains without an RFQ deployment (e.g. Ethereum) used to log a warning on every `initialize_client`.
`97a854b` fix(base): extend the demotion to all non-200 paths — the Dexalot RFQ endpoint actually returns 500 for unsupported chains. `_fetch_rfq_pairs` is best-effort at init; real failures surface from the trade-time call.
`b1f6b51` fix(swap): `execute_rfq_swap` failures now return `Transaction reverted: tx=0x..., block=N, reason=RF-XXX-NN`. New `_extract_revert_reason` helper replays the failing tx as `eth_call` against the failing block to recover the on-chain revert string.
`5686dbd` chore(release): promote PyPI trove classifier and README copy from alpha to beta.

Test plan

  • `make test` — 872 unit tests pass
  • `make cov` — 100% coverage on the modified files (`core/swap.py`, `core/base.py`)
  • `make lint` — clean
  • `make mypy` — clean
  • Mainnet RFQ swap: six successful trades from `trade_bots` against Avalanche C-Chain (`0x8d7401`, `0x9f6b4f`, `0x9bfe44`, `0x16506122`, `0x1db59188`, `0x04cfc77b`).
  • Reverted swap: surfaced revert reason via `_extract_revert_reason` on the one transient revert observed during testing.
  • Init logs: confirmed `Rfq Pairs Fetch Failed` is no longer emitted on `initialize_client` calls in production.

Upgrade notes

  • Callers that consumed firm-quote responses as `{secure_quote: {...}}` need to read the flat top-level `order`/`signature`/`tx` keys directly (matches the documented API).
  • `execute_rfq_swap` failure messages now include `tx=...`, `block=...`, and (when available) `reason=...`. Code that string-matches on the literal `Transaction reverted` prefix still works; consumers can additionally parse the new fields for debugging.

ngurmen added 7 commits May 9, 2026 02:51
- Introduced normalization of API quote responses to ensure consistent snake_case keys.
- Added handling for envelope-layer failures in the quote API response.
- Updated tests to cover new transformation logic and ensure existing keys are preserved.
- Removed deprecated secure_quote handling and streamlined order data transformation.
…yment)

The RFQ pairs fetch walks every connected chain on initialize_client.
Chains without an RFQ deployment (e.g. Ethereum) returned 4xx and the
catch-all warning logged 'rfq_pairs_fetch_failed' on every init,
polluting logs.

Distinguish HTTP status codes: 200 stores pairs, 4xx logs at debug
(expected absence), 5xx and network errors keep the warning.
The previous fix only quieted 4xx; Dexalot's RFQ endpoint returns 500
('Couldn't fetch resources!') for chains without an RFQ deployment
(e.g. Ethereum/chainid=1), so the catch-all warning kept firing on
every initialize_client.

_fetch_rfq_pairs is best-effort at init time. Chains that fail just
stay out of self.rfq_pairs; any real trade attempt against an empty
pair surfaces a meaningful error from get_swap_pairs or
get_swap_firm_quote. The warning at init was pure noise.

Demote both the non-200 status branch and the catch-all exception
branch to debug. Avalanche-specific recovery at the end of
_fetch_rfq_pairs is unchanged.
execute_rfq_swap previously returned just 'Transaction reverted' on
status=0 receipts, dropping the tx hash and block number — leaving
callers no way to inspect the failure on-chain. The receipt-status
check now includes the tx hash and block number in the failure
message, and a new _extract_revert_reason helper replays the original
transaction as eth_call against the failing block to surface the
solidity revert string (e.g. RF-EXP-01 for an expired quote).
Update PyPI trove classifier from 'Development Status :: 3 - Alpha' to
'Development Status :: 4 - Beta', and reword the README disclaimer
('first public release ... in alpha testing' -> 'public release ... in
beta testing') to match.

Maturity evidence:
- CLOB surface: long-running Fuji testnet exposure across orders,
  deposits/withdrawals, market data, and websocket subscriptions.
- Swap (RFQ) surface: end-to-end mainnet trades on this branch
  (six successful AVAX/USDC swaps via execute_rfq_swap), seven defects
  fixed at root (envelope unwrap, contract checksum, hex nonceAndMeta
  coercion, native msg.value, RFQ chain routing, RFQ pairs noise,
  reverted-tx info).
- 872 unit tests, 100% line coverage, mypy clean, no '# type: ignore'
  or '# noqa'.
- Active production consumer (trade_bots) routes every Dexalot call
  through this SDK, exercising swap, CLOB, balances, deposit/withdraw,
  pairs, and candle data on real users.

The 'public interface may undergo breaking changes' caveat stays - we
remain pre-1.0 per SemVer.
@ngurmen ngurmen requested review from ilkerulutas and oytunsan May 9, 2026 19:39
Format-only follow-up for swap.py / test_swap.py touched in b1f6b51
(surface tx_hash, block, revert reason on failed swap). Local make
format wasn't run after that change; CI's ruff format --check caught
it on the PR. No semantic change.
@ngurmen ngurmen requested review from cdincoglu and removed request for ilkerulutas May 9, 2026 20:44
@ngurmen ngurmen merged commit 364d5aa into main May 9, 2026
3 checks passed
@ngurmen ngurmen deleted the mng/fix-swap-flow branch May 9, 2026 20:45
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.

3 participants