Skip to content

Longbridge broker: order submit/replace fails at N-API boundary — decimal.js values passed to SDK's native Decimal fields #959

Description

@fanfpy

Environment

  • OpenAlice: dev (checked 2026-08-02, commit 6fba9da)
  • OS: macOS (likely platform-independent — failure is in N-API unwrapping)
  • Broker: Longbridge (paper/demo account)
  • Longbridge Node SDK: 4.0.5

Summary

Submitting or replacing an order through the Longbridge broker pack fails at
runtime: the N-API binding cannot unwrap decimal fields such as
SubmitOrderOptions.submittedQuantity because the adapter passes decimal.js
instances instead of the SDK's native longbridge.Decimal class. The
as unknown as never casts in LongbridgeBroker.ts only suppress the
TypeScript error — the class mismatch survives to runtime.

Expected behavior

A limit/trailing order on a Longbridge paper account submits successfully, and
modifyOrder replaces quantity/price/trigger successfully.

Actual behavior

tradeCtx.submitOrder() / tradeCtx.replaceOrder() fail at the native
boundary when the payload contains decimal.js values.

Actual error:

Reproduction steps

  1. Configure a Longbridge paper/demo account in UTA.
  2. Place an order through the Longbridge broker pack (e.g., AAPL.US limit buy
    with quantity + limit price + trigger price).
  3. submitOrder fails at the N-API unwrap step.
  4. (Optional) call modifyOrderreplaceOrder fails the same way on
    quantity/price/trigger fields.

Root cause

services/uta/src/domain/trading/brokers/longbridge/LongbridgeBroker.ts
builds SubmitOrderOptions/ReplaceOrderOptions directly from OpenAlice's
decimal.js Decimal values (lines ~297–327 on dev), then casts with
as unknown as never. The Longbridge SDK 4.0.5 write APIs require instances
of the SDK's exported Decimal class; N-API unwrapping expects that exact
class at runtime.

Proposed fix

PR #704 (#704) converts at the
write boundary via new LongbridgeDecimal(value.toString()) — a string
round-trip, so no precision is lost through JavaScript number — covering:

  • submit: quantity, limit price, trigger price, trailing percent
  • replace: quantity, limit price, trigger price

It includes regression tests asserting SDK Decimal class identity and exact
decimal strings; tsc --noEmit and the package typecheck pass. Live-paper
verification was not possible locally (no independently verified paper
account available) — happy to run it if a paper account can be provided or
once the fix is integrated.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions