Skip to content

Info endpoints: userBorrowLendInterest, liquidatable - #154

Merged
TuxedoFish merged 2 commits into
mainfrom
endpoint/borrow-lend-interest-liquidatable
Sep 8, 2026
Merged

Info endpoints: userBorrowLendInterest, liquidatable#154
TuxedoFish merged 2 commits into
mainfrom
endpoint/borrow-lend-interest-liquidatable

Conversation

@TuxedoFish

@TuxedoFish TuxedoFish commented Sep 8, 2026

Copy link
Copy Markdown
Owner

Summary

  • Adds userBorrowLendInterest (RestApi::userBorrowLendInterest, WebsocketApi::userBorrowLendInterest) - completes the borrow/lend read-side alongside the existing borrowLendUserState/borrowLendReserveState/allBorrowLendReserveStates.
  • Adds liquidatable (RestApi::liquidatable, WebsocketApi::liquidatable) - liquidation-risk data useful for any trading bot/risk dashboard.
  • Follows the CONTRIBUTING.md "Adding a new /info endpoint" pattern end-to-end: RequestTypes.h enum/toString/isAuthenticated, ResponseTypes.h structs, InfoRequestBuilder, RestApiMessageParser (with validateStructure() first), RestEndpointListener callbacks, RestApi sync+async, WebsocketApi, tests, README coverage table, and an example extension for each.

Closes #123
Closes #127

Field-shape verification (read before relying on this)

Both endpoints were probed live against mainnet (https://api.hyperliquid.xyz/info) and testnet (https://api.hyperliquid-testnet.xyz/info):

  • liquidatable: confirmed the request takes no user param - {"type":"liquidatable"} is accepted and returns [] on both networks. Passing a user field is silently accepted but ignored (still []). An invalid type value gets a real deserialization error, confirming "liquidatable" is a recognized type. Third-party doc mirrors (quicknode/chainstack/dwellir) describe a different, single-object, user-scoped shape ({liquidatable, leverage, marginUsed, ...}) - live testing shows that's wrong; the real endpoint is a global, unauthenticated array of currently-liquidatable positions.
  • userBorrowLendInterest: now confirmed against a real populated testnet response, not just the TS SDK (see below).

userBorrowLendInterest - real testnet response (populated)

$ curl -s -X POST https://api.hyperliquid-testnet.xyz/info -H "Content-Type: application/json" \
    -d '{"type":"userBorrowLendInterest","user":"0x6829Fdea522a6Fc3697311d2Ab93414BAd4b0C55"}'

[{"time":1788868810000,"token":"USDC","borrow":"0.0","supply":"0.0000008"},
 {"time":1788865210011,"token":"USDC","borrow":"0.0","supply":"0.00000079"},
 ... 62 entries total, all token="USDC", borrow="0.0", varying "supply" ...]

This exactly matches RestApiMessageParser::parseUserBorrowLendInterest's field names, types, and read order (time/token/borrow/supply, borrow/supply as string-encoded numbers via parseNumberField). tests/rest_borrow_lend_test.cpp's ParseUserBorrowLendInterestPopulated test now uses one of these real entries verbatim instead of a synthetic/TS-SDK-derived one.

liquidatable - still no populated example found

No account (mainnet or testnet, several plausible active/whale/HLP-vault addresses tried) returned a non-empty liquidatable array, so the array element shape is still taken from the official @nktkas/hyperliquid TypeScript SDK's source (src/api/info/_methods/liquidatable.ts), not independently confirmed against a live populated payload:

  • liquidatable response element: { user: string, positionIndex: { isolated: { asset: number } }, marginAvailable: [number, number] }. The upstream SDK itself flags two things as unconfirmed: a possible cross variant of positionIndex (not modeled here - only isolated is currently confirmed to exist), and the meaning of the two marginAvailable values (kept as an untyped std::array<double, 2> rather than guessing semantic names).

Please double-check liquidatable's populated-array-element shape before relying on it in a real integration, per this project's documented policy on unverified field shapes. userBorrowLendInterest no longer carries this caveat.

Test plan

  • cmake -S . -B build -DHYPERLIQUID_WARNINGS_AS_ERRORS=ON -DHYPERLIQUID_BUILD_TESTS=ON -DHYPERLIQUID_BUILD_EXAMPLES=ON -DCMAKE_TOOLCHAIN_FILE=$VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake - configures clean
  • cmake --build build -j12 - builds with zero warnings/errors
  • ctest --test-dir build - 28/28 test binaries pass (100%)
  • Request-builder + response-parser unit tests in tests/rest_borrow_lend_test.cpp (userBorrowLendInterest, now using a real testnet capture) and tests/rest_market_data_test.cpp (liquidatable), plus WebsocketApi wrapper coverage in tests/websocket_api_test.cpp
  • Rebased onto latest main (post-Info endpoints: twapHistory, userTwapSliceFillsByTime, activeAssetData #157) - README coverage count and a test-file conflict resolved, full clean rebuild/retest after rebasing
  • build/ removed before committing

🤖 Generated with Claude Code

https://claude.ai/code/session_018Le73N2EZjGLsCqmCScAse

@codecov

codecov Bot commented Sep 8, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 78.76106% with 24 lines in your changes missing coverage. Please review.
✅ Project coverage is 69.84%. Comparing base (0b9bdc9) to head (2392d26).

Files with missing lines Patch % Lines
src/rest/RestApi.cpp 0.00% 12 Missing ⚠️
src/rest/RestApiMessageParser.cpp 80.39% 10 Missing ⚠️
include/hyperliquid/rest/RestEndpointListener.h 0.00% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #154      +/-   ##
==========================================
+ Coverage   69.72%   69.84%   +0.11%     
==========================================
  Files          53       53              
  Lines        8404     8517     +113     
  Branches      526      531       +5     
==========================================
+ Hits         5860     5949      +89     
- Misses       2541     2565      +24     
  Partials        3        3              

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@github-actions github-actions Bot added the ready for review CI passed; ready to be reviewed label Sep 8, 2026
TuxedoFish and others added 2 commits September 8, 2026 13:07
Completes the borrow/lend read-side (userBorrowLendInterest joins
borrowLendUserState/borrowLendReserveState/allBorrowLendReserveStates)
and adds liquidatable risk data, wiring both through RestApi and
WebsocketApi with request-builder and response-parser tests.

userBorrowLendInterest's request/response shape and liquidatable's
{type:"liquidatable"} (no user param) request are cross-checked against
the official @nktkas/hyperliquid TS SDK source and confirmed live
against mainnet (both return an accepted, well-formed empty array for
every account tried - no populated example could be captured live, so
the populated-response field shapes are inferred from the TS SDK
source, not independently confirmed).

Closes #123
Closes #127

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Le73N2EZjGLsCqmCScAse
Replaces the TS-SDK-derived synthetic fixture with an actual populated
entry from a real testnet account (POST /info
{"type":"userBorrowLendInterest","user":"0x6829..."}), confirming the
parser's field names/types/read-order against genuine wire data rather
than a second-hand schema.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Le73N2EZjGLsCqmCScAse
@TuxedoFish
TuxedoFish force-pushed the endpoint/borrow-lend-interest-liquidatable branch from c169fdb to 2392d26 Compare September 8, 2026 12:12
@TuxedoFish
TuxedoFish merged commit 6c2c7b6 into main Sep 8, 2026
12 checks passed
@TuxedoFish
TuxedoFish deleted the endpoint/borrow-lend-interest-liquidatable branch September 8, 2026 12:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready for review CI passed; ready to be reviewed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Implement liquidatable Implement userBorrowLendInterest

1 participant