Skip to content

refactor: remove symbol↔counter_id conversions and type RankCategoriesResponse - #562

Draft
sunli829 wants to merge 12 commits into
mainfrom
feat/remove-counter-id-conversion
Draft

refactor: remove symbol↔counter_id conversions and type RankCategoriesResponse#562
sunli829 wants to merge 12 commits into
mainfrom
feat/remove-counter-id-conversion

Conversation

@sunli829

@sunli829 sunli829 commented Aug 10, 2026

Copy link
Copy Markdown
Collaborator

Summary

Remove all client-side symbol ↔ counter_id conversions and replace untyped serde_json::Value in the public API with proper typed / optional fields, across all language SDKs (Rust, Python, Node.js, Java, C, C++).

Remove symbol ↔ counter_id conversions

  • Delete the utils/counter module (symbol_to_counter_id, counter_id_to_symbol, index_symbol_to_counter_id, deserialize_counter_id_as_symbol, CSV lookup tables).
  • Remove the public QuoteContext::symbol_to_counter_ids and resolve_counter_ids methods (async + blocking).
  • All request parameters now send the user-supplied symbol (e.g. AAPL.US, HSI.HK) directly; all response types read symbol from the server instead of converting from counter_id.

Type RankCategoriesResponse

MarketContext.rank_categories now returns a structured response instead of raw JSON:

  • RankSubCategory { key, name, market } — leaf node; key is passed directly to rank_list
  • RankCategory { key, name, sub_categories }
  • RankCategoriesResponse { categories }
  • The ib_ prefix is stripped from keys so they can be passed straight to rank_list.

Replace remaining serde_json::Value in the public API

Write methods now return unit instead of the raw server body:

  • AlertContext::add/update/delete, SharelistContext::delete/add_securities/remove_securities/sort_securities() / void / Promise<void>.

Typed / optional fields:

  • TopMoversResponse.next_params: serde_json::ValueString (pagination cursor; empty means no more pages).
  • FlowItem.executed_timestamp: serde_json::ValueOption<String> (nullable Unix-seconds string).
  • StockRatings.multi_score / industry_mean_score / industry_median_score and RatingIndicator.score / RatingLeafIndicator.scoreOption<f64>; StockRatings.industry_rank / industry_totalOption<i64>.
  • AlertItem.value_map (AlertContext.list / update): serde_json::Value → typed AlertValueMap with a price and a chg field, exactly one populated per alert condition. price is a decimal (Rust/Python Decimal, Java BigDecimal, Node.js/C decimal string), chg a float (Rust f64, Python float, Java nullable Double, Node.js number, C const double* NULL-when-absent). Adds an f64_opt_str serde helper, a new Java AlertValueMap class, and a nested C lb_alert_value_map_t.
  • CorpActionLive.status (FundamentalContext.corp_action): serde_json::ValueString (string-or-int deserializer). The bindings already surfaced it as a string, but the JSON-value form produced an inconsistent quoted value (e.g. "\"2\""); it now normalizes to a clean string (e.g. "2").
  • IndustryRankItem.counter_id / IndustryPeerNode.counter_idsymbol.
  • IndustryPeersResponse.top → optional (server may return null).
  • ExecutiveGroup.symbol → optional (server may omit / return empty).

All changes are mirrored across every binding: Rust, Python (+ openapi.pyi), Node.js, Java (+ a boxed JavaDouble wrapper, regenerated classes), C (+ regenerated longbridge.h), and C++.

🤖 Generated with Claude Code

All outbound request parameters now send the user-supplied symbol
(e.g. AAPL.US, HSI.HK) directly to the server without any client-side
conversion. All inbound response fields are read as symbols directly
without conversion back from counter_id format.

Changes:
- Remove symbol_to_counter_id / index_symbol_to_counter_id from all
  request Query structs and JSON bodies across FundamentalContext,
  MarketContext, DCAContext, AlertContext, QuoteContext, TradeContext,
  SharelistContext, PortfolioContext
- Remove counter_id_to_symbol / deserialize_counter_id_as_symbol from
  all response deserialization in context and types files
- Delete utils/counter.rs and the embedded US-ETF/IX/WT.csv data files
- Delete symbol_to_counter_ids and resolve_counter_ids public methods
  from QuoteContext and blocking::QuoteContext
- Remove utils module from lib.rs
- Add api_test example binary for end-to-end testing
…ucts

All language SDKs now return structured types from rank_categories instead
of raw JSON strings/values.  New types: RankSubCategory (key, name, market)
and RankCategory (key, name, sub_categories).  The ib_ prefix is still
stripped from keys so callers can pass them directly to rank_list.

Also updates the api_test example to use sub_categories[0].key (the correct
key to pass to rank_list) instead of first_tags[0].key.
… typed fields

Removes untyped serde_json::Value from user-facing responses/requests and
tightens optional fields across all language SDKs.

Write methods return unit:
- AlertContext::add/update/delete and SharelistContext::delete/
  add_securities/remove_securities/sort_securities now return ()/void
  instead of the raw server JSON (the body carried nothing useful).

Typed / optional fields:
- TopMoversResponse.next_params: serde_json::Value -> String (cursor).
- FlowItem.executed_timestamp: serde_json::Value -> Option<String>.
- StockRatings.multi_score/industry_mean_score/industry_median_score and
  RatingIndicator/RatingLeafIndicator.score -> Option<f64>;
  StockRatings.industry_rank/industry_total -> Option<i64>.
- IndustryRankItem.counter_id / IndustryPeerNode.counter_id -> symbol.
- IndustryPeersResponse.top -> Option (server may return null).
- ExecutiveGroup.symbol -> Option<String> (server may omit/empty).

All changes are mirrored across Rust, Python (+ .pyi), Node.js, Java
(+ JavaDouble boxed wrapper), C (+ regenerated longbridge.h), and C++.
@sunli829
sunli829 force-pushed the feat/remove-counter-id-conversion branch from 2aeb033 to baa2af7 Compare August 10, 2026 11:18
…fix stale docs

The SDK no longer performs any symbol<->counter_id conversion, so drop the
misleading "counter_id" naming from request parameters and doc comments:

- Rust blocking wrappers (industry_peers, US-series fundamental methods):
  parameter counter_id -> symbol (value unchanged, sent as-is).
- Java IndustryPeersOptions.counterId -> symbol; C/C++ industry_peers
  parameter name -> symbol.
- Refresh doc comments that still said "converted from counter_id" /
  "Internal counter_id" across Rust, Python (.pyi), Node.js and Java.

The only genuine counter_id fields kept are Order.counter_id (a matched
counter-order id) and industry_counter_id (an industry classification code) —
neither is a security symbol.
FundamentalContext.getIndustryRank and getIndustryPeers declared native
methods in SdkNative and called them, but java/src had no JNI implementation
(runtime UnsatisfiedLinkError) and the result types were never registered for
class-ref init.

- Add Java_..._fundamentalContextGetIndustryRank / GetIndustryPeers.
- Register IndustryRankItem/Group/Response and IndustryPeersTop/PeerNode/
  Response in init.rs.
business_segments, business_segments_history, financial_report_snapshot and
institution_rating_views were declared in SdkNative and called from
FundamentalContext.java but had no JNI implementation (UnsatisfiedLinkError),
and their result types were not registered for class-ref init.

- Add the four JNI functions (symbol-only ones via the symbol_method! macro;
  the two opts-based ones read their option fields and leak the short
  report/period codes to satisfy the core's Option<&'static str> params).
- Register the BusinessSegment*, InstitutionRatingView* and
  *ReportSnapshot* result classes in init.rs.
…nable/disable

Java's AlertContext exposed enable(String)/disable(String) convenience methods
whose native functions (alertContextEnable/Disable) were never implemented
(UnsatisfiedLinkError), while the implemented alertContextUpdate JNI had no
Java declaration. The other language SDKs expose update(AlertItem) and toggle
enabled through it.

- AlertContext: replace enable/disable with update(AlertItem).
- SdkNative: drop alertContextEnable/Disable decls; add alertContextUpdate.
Removed the blanket #![allow(missing_docs)] from all 10 types modules.
Eight were already fully documented; documented the remainder:
- fundamental: all US-series struct fields (company/valuation/financial-
  statement/dividends/ETF/key-metrics/analyst-consensus overviews).
- asset: statement list/item/download fields.
- added module docs to the `pub mod types;` declarations.

trade/types.rs still has undocumented US-series fields but never carried an
allow(missing_docs); left as-is (crate lint is warn, not deny).
…s-clean

Documented the remaining ~158 undocumented public fields in trade/types.rs
(USOrderHistory, USButtonControl, USChargeItem/Detail, USAttachedOrder,
USOrderDetail, USCashEntry, USCryptoEntry, USStockEntry, USAssetOverview,
USRealizedPLMetric/Entry, USRealizedPL). The whole `longbridge` crate now
builds with zero missing_docs warnings.
Replace two more untyped `serde_json::Value` fields in the public API with
proper typed fields, mirrored across every binding (Rust, Python, Node.js,
Java, C).

- `AlertItem.value_map` (AlertContext.list / update) -> typed `AlertValueMap`
  with a `price` (absolute-price threshold) and `chg` (percentage-change
  threshold) field, exactly one populated per alert condition. `price` is a
  decimal (Rust/Python `Decimal`, Java `BigDecimal`, Node.js/C decimal string)
  and `chg` a float (Rust `f64`, Python `float`, Java nullable `Double`,
  Node.js `number`, C `const double*`). Adds an `f64_opt_str` serde helper and
  a new Java `AlertValueMap` class; C exposes a nested `lb_alert_value_map_t`.
- `CorpActionLive.status` (FundamentalContext.corp_action) -> `String` via a
  string-or-int deserializer. The bindings already surfaced it as a string but
  the JSON-value form produced an inconsistent, quoted value (e.g. `"\"2\""`);
  it now normalizes to a clean string (e.g. `"2"`).
… SDK

Commit 68bb715 typed AlertItem.value_map across Rust/Python/Node.js/Java/C
but missed the C++ binding, so the C++ SDK failed to compile (convert.hpp
could not build alert::AlertItem — value_map is now a struct, not a string).

- Add a C++ `AlertValueMap { std::string price; std::optional<double> chg; }`
  and change `AlertItem.value_map` to it.
- Update convert (C→C++) and the update path (C++→C) accordingly.

Verified all CMake SOURCES translation units pass -fsyntax-only.
AlertContext.delete and SharelistContext.delete / remove_securities
previously sent their parameters in a JSON body on a DELETE request.
Move them to the query string (ids / symbols) and drop the body
entirely for SharelistContext.delete, matching the existing
QuoteContext.delete_watchlist_group convention.

Verified against the .xyz stage gateway: all three now issue body-less
DELETE requests and the server accepts the query-param form.
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