Files
dex/sdk/go/client_nogrpc.go
zeekayandHanzo Dev 05796eb725 fix: FIX Latest — ExecType said what OrdStatus already said
The gateway spoke 8=FIX.4.4 and reported a fill as ExecType 1/2 — the pair
FIX Latest retired precisely because it duplicated order state into the
event field. Both fields carried the same thing, so nothing on the wire
distinguished "a trade happened" from "the order is done", and a client
could read either.

Session layer is now FIXT.1.1; the application layer is FIX.5.0SP2 + EP307,
named on the Logon by DefaultApplVerID(1137) and ApplExtID(1156). Every
fill is ExecType=F (Trade) and OrdStatus alone moves Partial -> Filled.
Nothing depended on the old BeginString, so the wire moved with the
semantics instead of straddling both. This is the wire pkg/dexprotocol
already documents (150=F, 39=1|2).

A partially-filled IOC also never reached a terminal state: the last report
said Partial and nothing followed, leaving a client waiting for an end that
never came. It now closes with Canceled.

Vocabulary, one word per concept: execReport -> execution, gateway
OrderFill -> Fill, multisig ExecutionResult -> Result (it holds an error
string, never an execution).

Deletes the SDK's hand-rolled FIX encoder — it pinned a second protocol
version, omitted BodyLength entirely so the acceptor would have rejected
every frame, and sendFIXMessage returned nil without sending.

Co-authored-by: Hanzo Dev <[email protected]>
2026-08-07 09:09:37 -07:00

131 lines
3.4 KiB
Go

//go:build !grpc
// Package lxsdk is the gRPC-backed Go SDK for the LX trading platform.
//
// In the default build (no `grpc` build tag), gRPC support is excluded
// so consumers compile zero gRPC code. NewClient and NewHighFrequencyClient
// return an explanatory error. Rebuild with `-tags=grpc` to get the
// real client.
//
// External trading clients that do not need the binary gRPC transport
// should use the JSON-RPC + WebSocket SDK at
// github.com/luxfi/dex/sdk/go/client instead.
package lxsdk
import (
"errors"
"sync"
"sync/atomic"
"time"
)
// ErrGRPCNotBuilt is returned when the SDK is used without the `grpc`
// build tag. Rebuild with `go build -tags=grpc` to enable.
var ErrGRPCNotBuilt = errors.New("lxsdk: gRPC client requires the `grpc` build tag (rebuild with -tags=grpc)")
// Side represents order side.
type Side int
const (
Buy Side = iota
Sell
)
// OrderType represents order type.
type OrderType int
const (
Market OrderType = iota
Limit
Stop
StopLimit
)
// Order represents a trading order.
type Order struct {
ID string
Symbol string
Price float64
Quantity float64
Side Side
Type OrderType
Timestamp time.Time
}
// Trade represents an executed trade.
type Trade struct {
ID string
OrderID string
Symbol string
Price float64
Quantity float64
Side Side
Timestamp time.Time
}
// Client is the no-op placeholder for the gRPC client. All operations
// return ErrGRPCNotBuilt.
type Client struct {
address string
// Match the gRPC build's exported observability surface so consumers
// compile against both builds.
ordersSent atomic.Int64
tradesRecv atomic.Int64
latencyNanos atomic.Int64
mu sync.RWMutex
}
// NewClient returns an error in the default build. Rebuild with `-tags=grpc`.
func NewClient(address string) (*Client, error) {
return nil, ErrGRPCNotBuilt
}
// SendOrder returns ErrGRPCNotBuilt.
func (c *Client) SendOrder(symbol string, price, quantity float64, side Side) (*Order, error) {
return nil, ErrGRPCNotBuilt
}
// SendBulkOrders returns ErrGRPCNotBuilt.
func (c *Client) SendBulkOrders(orders []*Order) error { return ErrGRPCNotBuilt }
// CancelOrder returns ErrGRPCNotBuilt.
func (c *Client) CancelOrder(orderID string) error { return ErrGRPCNotBuilt }
// Subscribe returns ErrGRPCNotBuilt.
func (c *Client) Subscribe(symbols []string, callback func(*Trade)) error { return ErrGRPCNotBuilt }
// GetOrderBook returns ErrGRPCNotBuilt.
func (c *Client) GetOrderBook(symbol string) (bids, asks []Order, err error) {
return nil, nil, ErrGRPCNotBuilt
}
// GetMetrics returns zeroed metrics.
func (c *Client) GetMetrics() map[string]interface{} {
return map[string]interface{}{
"orders_sent": c.ordersSent.Load(),
"trades_received": c.tradesRecv.Load(),
"latency_ns": c.latencyNanos.Load(),
"latency_ms": float64(c.latencyNanos.Load()) / 1e6,
}
}
// GetThroughput returns 0.
func (c *Client) GetThroughput() float64 { return 0 }
// Close is a no-op.
func (c *Client) Close() error { return nil }
// HighFrequencyClient placeholder.
type HighFrequencyClient struct{ *Client }
// NewHighFrequencyClient returns ErrGRPCNotBuilt.
func NewHighFrequencyClient(address string) (*HighFrequencyClient, error) {
return nil, ErrGRPCNotBuilt
}
// SendOrderAsync is a no-op.
func (hft *HighFrequencyClient) SendOrderAsync(symbol string, price, quantity float64, side Side) {
}